@neat.is/core 0.8.1-dev.20260817 → 0.8.2-dev.20260818
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-3PXRQH53.js → chunk-T4UGEMWN.js} +1176 -524
- package/dist/chunk-T4UGEMWN.js.map +1 -0
- package/dist/{chunk-OJ6BW63H.js → chunk-WLCHTXO3.js} +2 -2
- package/dist/cli.cjs +1710 -1057
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +1398 -745
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +1411 -758
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +1305 -652
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +4 -2
- package/dist/chunk-3PXRQH53.js.map +0 -1
- /package/dist/{chunk-OJ6BW63H.js.map → chunk-WLCHTXO3.js.map} +0 -0
package/dist/server.cjs
CHANGED
|
@@ -59,8 +59,8 @@ function mountBearerAuth(app, opts) {
|
|
|
59
59
|
]);
|
|
60
60
|
const publicRead = opts.publicRead === true;
|
|
61
61
|
app.addHook("preHandler", (req, reply, done) => {
|
|
62
|
-
const
|
|
63
|
-
if (exactUnauthPaths.has(
|
|
62
|
+
const path71 = (req.url.split("?")[0] ?? "").replace(/\/+$/, "");
|
|
63
|
+
if (exactUnauthPaths.has(path71) || PROJECT_SCOPED_UNAUTH_PATTERN.test(path71)) {
|
|
64
64
|
done();
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
@@ -192,8 +192,8 @@ function reshapeGrpcRequest(req) {
|
|
|
192
192
|
};
|
|
193
193
|
}
|
|
194
194
|
function resolveProtoRoot() {
|
|
195
|
-
const here =
|
|
196
|
-
return
|
|
195
|
+
const here = import_node_path50.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
196
|
+
return import_node_path50.default.resolve(here, "..", "proto");
|
|
197
197
|
}
|
|
198
198
|
function loadTraceService() {
|
|
199
199
|
const protoRoot = resolveProtoRoot();
|
|
@@ -261,13 +261,13 @@ async function startOtelGrpcReceiver(opts) {
|
|
|
261
261
|
})
|
|
262
262
|
};
|
|
263
263
|
}
|
|
264
|
-
var import_node_url,
|
|
264
|
+
var import_node_url, import_node_path50, import_node_crypto2, grpc, protoLoader;
|
|
265
265
|
var init_otel_grpc = __esm({
|
|
266
266
|
"src/otel-grpc.ts"() {
|
|
267
267
|
"use strict";
|
|
268
268
|
init_cjs_shims();
|
|
269
269
|
import_node_url = require("url");
|
|
270
|
-
|
|
270
|
+
import_node_path50 = __toESM(require("path"), 1);
|
|
271
271
|
import_node_crypto2 = require("crypto");
|
|
272
272
|
grpc = __toESM(require("@grpc/grpc-js"), 1);
|
|
273
273
|
protoLoader = __toESM(require("@grpc/proto-loader"), 1);
|
|
@@ -413,8 +413,8 @@ function websocketChannelPathOf(attrs) {
|
|
|
413
413
|
const v = attrs[key];
|
|
414
414
|
if (typeof v === "string" && v.length > 0) {
|
|
415
415
|
const q = v.indexOf("?");
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
416
|
+
const path71 = q === -1 ? v : v.slice(0, q);
|
|
417
|
+
if (path71.length > 0) return path71;
|
|
418
418
|
}
|
|
419
419
|
}
|
|
420
420
|
return void 0;
|
|
@@ -476,10 +476,10 @@ function parseOtlpRequest(body) {
|
|
|
476
476
|
return out;
|
|
477
477
|
}
|
|
478
478
|
function loadProtoRoot() {
|
|
479
|
-
const here =
|
|
480
|
-
const protoRoot =
|
|
479
|
+
const here = import_node_path51.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
480
|
+
const protoRoot = import_node_path51.default.resolve(here, "..", "proto");
|
|
481
481
|
const root = new import_protobufjs.default.Root();
|
|
482
|
-
root.resolvePath = (_origin, target) =>
|
|
482
|
+
root.resolvePath = (_origin, target) => import_node_path51.default.resolve(protoRoot, target);
|
|
483
483
|
root.loadSync(
|
|
484
484
|
"opentelemetry/proto/collector/trace/v1/trace_service.proto",
|
|
485
485
|
{ keepCase: true }
|
|
@@ -710,12 +710,12 @@ async function buildOtelReceiver(opts) {
|
|
|
710
710
|
};
|
|
711
711
|
return decorated;
|
|
712
712
|
}
|
|
713
|
-
var
|
|
713
|
+
var import_node_path51, import_node_url2, import_fastify, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody;
|
|
714
714
|
var init_otel = __esm({
|
|
715
715
|
"src/otel.ts"() {
|
|
716
716
|
"use strict";
|
|
717
717
|
init_cjs_shims();
|
|
718
|
-
|
|
718
|
+
import_node_path51 = __toESM(require("path"), 1);
|
|
719
719
|
import_node_url2 = require("url");
|
|
720
720
|
import_fastify = __toESM(require("fastify"), 1);
|
|
721
721
|
import_protobufjs = __toESM(require("protobufjs"), 1);
|
|
@@ -731,7 +731,7 @@ var init_otel = __esm({
|
|
|
731
731
|
|
|
732
732
|
// src/server.ts
|
|
733
733
|
init_cjs_shims();
|
|
734
|
-
var
|
|
734
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
735
735
|
|
|
736
736
|
// src/graph.ts
|
|
737
737
|
init_cjs_shims();
|
|
@@ -755,7 +755,7 @@ function getGraph(project = DEFAULT_PROJECT) {
|
|
|
755
755
|
init_cjs_shims();
|
|
756
756
|
var import_fastify2 = __toESM(require("fastify"), 1);
|
|
757
757
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
758
|
-
var
|
|
758
|
+
var import_types88 = require("@neat.is/types");
|
|
759
759
|
|
|
760
760
|
// src/extend/index.ts
|
|
761
761
|
init_cjs_shims();
|
|
@@ -2015,7 +2015,7 @@ var import_node_fs5 = require("fs");
|
|
|
2015
2015
|
var import_node_path5 = __toESM(require("path"), 1);
|
|
2016
2016
|
var import_yaml = require("yaml");
|
|
2017
2017
|
var import_types3 = require("@neat.is/types");
|
|
2018
|
-
var SERVICE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs", ".ts", ".tsx", ".py", ".go", ".rb", ".php"]);
|
|
2018
|
+
var SERVICE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs", ".ts", ".tsx", ".py", ".go", ".rb", ".php", ".cs", ".java"]);
|
|
2019
2019
|
var CONFIG_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".yaml", ".yml"]);
|
|
2020
2020
|
var JSON_CONFIG_FILENAMES = /* @__PURE__ */ new Set(["app.json", "app.config.json", "eas.json"]);
|
|
2021
2021
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -2338,6 +2338,10 @@ function languageForPath(relPath) {
|
|
|
2338
2338
|
return "ruby";
|
|
2339
2339
|
case ".php":
|
|
2340
2340
|
return "php";
|
|
2341
|
+
case ".cs":
|
|
2342
|
+
return "csharp";
|
|
2343
|
+
case ".java":
|
|
2344
|
+
return "java";
|
|
2341
2345
|
case ".ts":
|
|
2342
2346
|
case ".tsx":
|
|
2343
2347
|
return "typescript";
|
|
@@ -2874,8 +2878,8 @@ function chiRoutesFromSource(source, parser) {
|
|
|
2874
2878
|
chiWalk(tree.rootNode, "", out);
|
|
2875
2879
|
return out;
|
|
2876
2880
|
}
|
|
2877
|
-
function stripChiRegex(
|
|
2878
|
-
return
|
|
2881
|
+
function stripChiRegex(path71) {
|
|
2882
|
+
return path71.replace(/\{([^{}:]+):[^{}]*\}/g, "{$1}");
|
|
2879
2883
|
}
|
|
2880
2884
|
function chiWalk(node, prefix, out) {
|
|
2881
2885
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
@@ -3547,9 +3551,9 @@ function rubyRocketRoute(args) {
|
|
|
3547
3551
|
if (!pair || pair.type !== "pair") continue;
|
|
3548
3552
|
const k = pair.childForFieldName("key");
|
|
3549
3553
|
if (k?.type !== "string") continue;
|
|
3550
|
-
const
|
|
3551
|
-
if (
|
|
3552
|
-
return { path:
|
|
3554
|
+
const path71 = rubyLiteral(k);
|
|
3555
|
+
if (path71 === null) continue;
|
|
3556
|
+
return { path: path71, target: rubyLiteral(pair.childForFieldName("value")) };
|
|
3553
3557
|
}
|
|
3554
3558
|
return null;
|
|
3555
3559
|
}
|
|
@@ -4777,7 +4781,7 @@ function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line)
|
|
|
4777
4781
|
}
|
|
4778
4782
|
return sid;
|
|
4779
4783
|
}
|
|
4780
|
-
function landObservedSymbol(graph, fileNodeId, service, relPath, callSite) {
|
|
4784
|
+
function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint = true) {
|
|
4781
4785
|
const line = callSite.line;
|
|
4782
4786
|
if (line === void 0) return fileNodeId;
|
|
4783
4787
|
let sawSymbol = false;
|
|
@@ -4792,7 +4796,7 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite) {
|
|
|
4792
4796
|
}
|
|
4793
4797
|
});
|
|
4794
4798
|
if (candidates.length > 0) return pickContainingSymbol(candidates, callSite.fn);
|
|
4795
|
-
if (sawSymbol && callSite.fn) {
|
|
4799
|
+
if (mint && sawSymbol && callSite.fn) {
|
|
4796
4800
|
return ensureObservedSymbolNode(graph, fileNodeId, service, relPath, callSite.fn, line);
|
|
4797
4801
|
}
|
|
4798
4802
|
return fileNodeId;
|
|
@@ -5198,6 +5202,20 @@ function incidentAffectedNode(span, graph, scanPath) {
|
|
|
5198
5202
|
const callSite = callSiteFromSpan(span, serviceNode, scanPath);
|
|
5199
5203
|
if (callSite) {
|
|
5200
5204
|
const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
|
|
5205
|
+
const canonicalService = serviceNode && typeof serviceNode.name === "string" ? serviceNode.name : span.service;
|
|
5206
|
+
if (graph) {
|
|
5207
|
+
const fusedFileId = (0, import_types7.fileId)(canonicalService, relPath);
|
|
5208
|
+
if (graph.hasNode(fusedFileId)) {
|
|
5209
|
+
return landObservedSymbol(
|
|
5210
|
+
graph,
|
|
5211
|
+
fusedFileId,
|
|
5212
|
+
canonicalService,
|
|
5213
|
+
relPath,
|
|
5214
|
+
{ ...callSite, relPath },
|
|
5215
|
+
false
|
|
5216
|
+
);
|
|
5217
|
+
}
|
|
5218
|
+
}
|
|
5201
5219
|
return (0, import_types7.fileId)(span.service, relPath);
|
|
5202
5220
|
}
|
|
5203
5221
|
return sid;
|
|
@@ -5536,7 +5554,11 @@ async function handleSpan(ctx, span) {
|
|
|
5536
5554
|
...span.exception?.type ? { exceptionType: span.exception.type } : {},
|
|
5537
5555
|
...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
|
|
5538
5556
|
...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
|
|
5539
|
-
|
|
5557
|
+
// Attribute to where the failure originated — the symbol / file / service
|
|
5558
|
+
// the throwing span named (incidentAffectedNode, ADR-191) — the same
|
|
5559
|
+
// source-based attribution the durable receiver write uses, not the
|
|
5560
|
+
// outbound edge target this span happened to mint.
|
|
5561
|
+
affectedNode: incidentAffectedNode(span, ctx.graph, ctx.scanPath)
|
|
5540
5562
|
};
|
|
5541
5563
|
await appendErrorEvent(ctx, ev);
|
|
5542
5564
|
}
|
|
@@ -5574,29 +5596,29 @@ function promoteFrontierNodes(graph, opts = {}) {
|
|
|
5574
5596
|
toPromote.push({ frontierId: id, serviceId: target });
|
|
5575
5597
|
});
|
|
5576
5598
|
let promoted = 0;
|
|
5577
|
-
for (const { frontierId: frontierId2, serviceId:
|
|
5599
|
+
for (const { frontierId: frontierId2, serviceId: serviceId12 } of toPromote) {
|
|
5578
5600
|
if (opts.policies && opts.policies.length > 0 && opts.policyCtx) {
|
|
5579
5601
|
const gate = canPromoteFrontier(graph, frontierId2, opts.policies, opts.policyCtx);
|
|
5580
5602
|
if (!gate.allowed) {
|
|
5581
5603
|
continue;
|
|
5582
5604
|
}
|
|
5583
5605
|
}
|
|
5584
|
-
rewireFrontierEdges(graph, frontierId2,
|
|
5606
|
+
rewireFrontierEdges(graph, frontierId2, serviceId12);
|
|
5585
5607
|
graph.dropNode(frontierId2);
|
|
5586
5608
|
promoted++;
|
|
5587
5609
|
}
|
|
5588
5610
|
return promoted;
|
|
5589
5611
|
}
|
|
5590
|
-
function rewireFrontierEdges(graph, frontierId2,
|
|
5612
|
+
function rewireFrontierEdges(graph, frontierId2, serviceId12) {
|
|
5591
5613
|
const inbound = [...graph.inboundEdges(frontierId2)];
|
|
5592
5614
|
const outbound = [...graph.outboundEdges(frontierId2)];
|
|
5593
5615
|
for (const edgeId of inbound) {
|
|
5594
5616
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
5595
|
-
rebuildEdge(graph, edge, edge.source,
|
|
5617
|
+
rebuildEdge(graph, edge, edge.source, serviceId12, edgeId);
|
|
5596
5618
|
}
|
|
5597
5619
|
for (const edgeId of outbound) {
|
|
5598
5620
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
5599
|
-
rebuildEdge(graph, edge,
|
|
5621
|
+
rebuildEdge(graph, edge, serviceId12, edge.target, edgeId);
|
|
5600
5622
|
}
|
|
5601
5623
|
}
|
|
5602
5624
|
function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
|
|
@@ -5915,19 +5937,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
5915
5937
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
5916
5938
|
let best = { path: [start], edges: [] };
|
|
5917
5939
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
5918
|
-
function step(node,
|
|
5919
|
-
if (
|
|
5920
|
-
best = { path: [...
|
|
5940
|
+
function step(node, path71, edges) {
|
|
5941
|
+
if (path71.length > best.path.length) {
|
|
5942
|
+
best = { path: [...path71], edges: [...edges] };
|
|
5921
5943
|
}
|
|
5922
|
-
if (
|
|
5944
|
+
if (path71.length - 1 >= maxDepth) return;
|
|
5923
5945
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
5924
5946
|
for (const [srcId, edge] of incoming) {
|
|
5925
5947
|
if (visited.has(srcId)) continue;
|
|
5926
5948
|
visited.add(srcId);
|
|
5927
|
-
|
|
5949
|
+
path71.push(srcId);
|
|
5928
5950
|
edges.push(edge);
|
|
5929
|
-
step(srcId,
|
|
5930
|
-
|
|
5951
|
+
step(srcId, path71, edges);
|
|
5952
|
+
path71.pop();
|
|
5931
5953
|
edges.pop();
|
|
5932
5954
|
visited.delete(srcId);
|
|
5933
5955
|
}
|
|
@@ -5942,7 +5964,7 @@ function databaseRootCauseShape(graph, origin, walk9) {
|
|
|
5942
5964
|
for (const id of walk9.path) {
|
|
5943
5965
|
const owner = resolveOwningService(graph, id);
|
|
5944
5966
|
if (!owner) continue;
|
|
5945
|
-
const { id:
|
|
5967
|
+
const { id: serviceId12, svc } = owner;
|
|
5946
5968
|
const deps = svc.dependencies ?? {};
|
|
5947
5969
|
for (const pair of candidatePairs) {
|
|
5948
5970
|
const declared = deps[pair.driver];
|
|
@@ -5955,7 +5977,7 @@ function databaseRootCauseShape(graph, origin, walk9) {
|
|
|
5955
5977
|
);
|
|
5956
5978
|
if (!result.compatible) {
|
|
5957
5979
|
return {
|
|
5958
|
-
rootCauseNode:
|
|
5980
|
+
rootCauseNode: serviceId12,
|
|
5959
5981
|
rootCauseReason: result.reason ?? "incompatible driver",
|
|
5960
5982
|
...result.minDriverVersion ? {
|
|
5961
5983
|
fixRecommendation: `Upgrade ${svc.name} ${pair.driver} driver to >= ${result.minDriverVersion}`
|
|
@@ -5970,7 +5992,7 @@ function serviceRootCauseShape(graph, _origin, walk9) {
|
|
|
5970
5992
|
for (const id of walk9.path) {
|
|
5971
5993
|
const owner = resolveOwningService(graph, id);
|
|
5972
5994
|
if (!owner) continue;
|
|
5973
|
-
const { id:
|
|
5995
|
+
const { id: serviceId12, svc } = owner;
|
|
5974
5996
|
const deps = svc.dependencies ?? {};
|
|
5975
5997
|
const serviceNodeEngine = svc.nodeEngine;
|
|
5976
5998
|
for (const constraint of nodeEngineConstraints()) {
|
|
@@ -5979,7 +6001,7 @@ function serviceRootCauseShape(graph, _origin, walk9) {
|
|
|
5979
6001
|
const result = checkNodeEngineConstraint(constraint, declared, serviceNodeEngine);
|
|
5980
6002
|
if (!result.compatible && result.reason) {
|
|
5981
6003
|
return {
|
|
5982
|
-
rootCauseNode:
|
|
6004
|
+
rootCauseNode: serviceId12,
|
|
5983
6005
|
rootCauseReason: result.reason,
|
|
5984
6006
|
...result.requiredNodeVersion ? {
|
|
5985
6007
|
fixRecommendation: `Bump ${svc.name}'s engines.node to >= ${result.requiredNodeVersion}`
|
|
@@ -5994,7 +6016,7 @@ function serviceRootCauseShape(graph, _origin, walk9) {
|
|
|
5994
6016
|
const result = checkPackageConflict(conflict, declared, requiredDeclared);
|
|
5995
6017
|
if (!result.compatible && result.reason) {
|
|
5996
6018
|
return {
|
|
5997
|
-
rootCauseNode:
|
|
6019
|
+
rootCauseNode: serviceId12,
|
|
5998
6020
|
rootCauseReason: result.reason,
|
|
5999
6021
|
fixRecommendation: `Upgrade ${svc.name}'s ${conflict.requires.name} to >= ${conflict.requires.minVersion}`
|
|
6000
6022
|
};
|
|
@@ -6046,7 +6068,11 @@ function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
|
|
|
6046
6068
|
}
|
|
6047
6069
|
var INCIDENT_ROOT_CAUSE_CONFIDENCE = 0.6;
|
|
6048
6070
|
function incidentMatchesNode(ev, nodeId) {
|
|
6049
|
-
|
|
6071
|
+
if (ev.affectedNode === nodeId) return true;
|
|
6072
|
+
if (ev.service === nodeId.replace(/^service:/, "")) return true;
|
|
6073
|
+
const sym = (0, import_types8.parseSymbolId)(ev.affectedNode);
|
|
6074
|
+
if (sym && (0, import_types8.fileId)(sym.service, sym.relPath) === nodeId) return true;
|
|
6075
|
+
return false;
|
|
6050
6076
|
}
|
|
6051
6077
|
function localizeFromIncidents(nodeId, incidents, errorEvent) {
|
|
6052
6078
|
const pool = incidents && incidents.length > 0 ? incidents : errorEvent ? [errorEvent] : [];
|
|
@@ -6064,8 +6090,8 @@ function localizeFromIncidents(nodeId, incidents, errorEvent) {
|
|
|
6064
6090
|
const reasonParts = [`${latest.service}: ${latest.errorMessage}`];
|
|
6065
6091
|
if (location) reasonParts.push(`surfaced at ${location}`);
|
|
6066
6092
|
const rootCauseReason = `${reasonParts.join(" \u2014 ")}${tail}`;
|
|
6067
|
-
const
|
|
6068
|
-
const fileNode =
|
|
6093
|
+
const localizesFiner = latest.affectedNode !== nodeId && (latest.affectedNode.startsWith("file:") || latest.affectedNode.startsWith("symbol:"));
|
|
6094
|
+
const fileNode = localizesFiner ? latest.affectedNode : void 0;
|
|
6069
6095
|
const fixRecommendation = location ? `Inspect ${location}${route ? ` handling ${route}` : ""}` : route ? `Inspect ${latest.service}'s handler for ${route}` : void 0;
|
|
6070
6096
|
return {
|
|
6071
6097
|
rootCauseNode: fileNode ?? nodeId,
|
|
@@ -6091,9 +6117,9 @@ function rootCauseFromIncidents(nodeId, incidents, errorEvent) {
|
|
|
6091
6117
|
function isFailingCallEdge(e) {
|
|
6092
6118
|
return e.type === import_types8.EdgeType.CALLS && (e.signal?.errorCount ?? 0) > 0;
|
|
6093
6119
|
}
|
|
6094
|
-
function callSourcesForService(graph,
|
|
6095
|
-
const ids = [
|
|
6096
|
-
for (const edgeId of graph.outboundEdges(
|
|
6120
|
+
function callSourcesForService(graph, serviceId12) {
|
|
6121
|
+
const ids = [serviceId12];
|
|
6122
|
+
for (const edgeId of graph.outboundEdges(serviceId12)) {
|
|
6097
6123
|
const e = graph.getEdgeAttributes(edgeId);
|
|
6098
6124
|
if (e.type !== import_types8.EdgeType.CONTAINS) continue;
|
|
6099
6125
|
const tgt = graph.getNodeAttributes(e.target);
|
|
@@ -6117,9 +6143,9 @@ function failingCallDominates(e, id, curEdge, curId) {
|
|
|
6117
6143
|
}
|
|
6118
6144
|
return id < curId;
|
|
6119
6145
|
}
|
|
6120
|
-
function dominantFailingCall(graph,
|
|
6146
|
+
function dominantFailingCall(graph, serviceId12, visited) {
|
|
6121
6147
|
let best = null;
|
|
6122
|
-
for (const src of callSourcesForService(graph,
|
|
6148
|
+
for (const src of callSourcesForService(graph, serviceId12)) {
|
|
6123
6149
|
for (const edgeId of graph.outboundEdges(src)) {
|
|
6124
6150
|
const e = graph.getEdgeAttributes(edgeId);
|
|
6125
6151
|
if (!isFailingCallEdge(e)) continue;
|
|
@@ -6134,26 +6160,26 @@ function dominantFailingCall(graph, serviceId9, visited) {
|
|
|
6134
6160
|
return best;
|
|
6135
6161
|
}
|
|
6136
6162
|
function followFailingCallChain(graph, originServiceId, maxDepth) {
|
|
6137
|
-
const
|
|
6163
|
+
const path71 = [originServiceId];
|
|
6138
6164
|
const edges = [];
|
|
6139
6165
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
6140
6166
|
let current = originServiceId;
|
|
6141
6167
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
6142
6168
|
const hop = dominantFailingCall(graph, current, visited);
|
|
6143
6169
|
if (!hop) break;
|
|
6144
|
-
|
|
6170
|
+
path71.push(hop.nextService);
|
|
6145
6171
|
edges.push(hop.edge);
|
|
6146
6172
|
visited.add(hop.nextService);
|
|
6147
6173
|
current = hop.nextService;
|
|
6148
6174
|
}
|
|
6149
6175
|
if (edges.length === 0) return null;
|
|
6150
|
-
return { path:
|
|
6176
|
+
return { path: path71, edges, culprit: current };
|
|
6151
6177
|
}
|
|
6152
6178
|
function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
6153
6179
|
const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
|
|
6154
6180
|
if (!chain) return null;
|
|
6155
6181
|
const culprit = chain.culprit;
|
|
6156
|
-
const
|
|
6182
|
+
const path71 = [...chain.path];
|
|
6157
6183
|
const edgeProvenances = chain.edges.map((e) => e.provenance);
|
|
6158
6184
|
const baseConfidence = confidenceFromMix(chain.edges);
|
|
6159
6185
|
const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
|
|
@@ -6161,14 +6187,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
6161
6187
|
if (loc) {
|
|
6162
6188
|
let rootCauseNode = culprit;
|
|
6163
6189
|
if (loc.fileNode) {
|
|
6164
|
-
|
|
6190
|
+
path71.push(loc.fileNode);
|
|
6165
6191
|
edgeProvenances.push(import_types8.Provenance.OBSERVED);
|
|
6166
6192
|
rootCauseNode = loc.fileNode;
|
|
6167
6193
|
}
|
|
6168
6194
|
return import_types8.RootCauseResultSchema.parse({
|
|
6169
6195
|
rootCauseNode,
|
|
6170
6196
|
rootCauseReason: loc.rootCauseReason,
|
|
6171
|
-
traversalPath:
|
|
6197
|
+
traversalPath: path71,
|
|
6172
6198
|
edgeProvenances,
|
|
6173
6199
|
confidence,
|
|
6174
6200
|
...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
|
|
@@ -6180,7 +6206,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
6180
6206
|
return import_types8.RootCauseResultSchema.parse({
|
|
6181
6207
|
rootCauseNode: culprit,
|
|
6182
6208
|
rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
|
|
6183
|
-
traversalPath:
|
|
6209
|
+
traversalPath: path71,
|
|
6184
6210
|
edgeProvenances,
|
|
6185
6211
|
confidence,
|
|
6186
6212
|
fixRecommendation: `Inspect ${culpritName}'s failing handler`
|
|
@@ -6550,6 +6576,22 @@ function findLoadOrigin(graph, alertNodeId, incidents, now) {
|
|
|
6550
6576
|
}
|
|
6551
6577
|
return best ? { node: best.node, ctx: best.ctx } : null;
|
|
6552
6578
|
}
|
|
6579
|
+
var LOAD_ORIGIN_CONFIDENCE_CEILING = 0.9;
|
|
6580
|
+
function loadOriginConfidence(originCtx, seedCtx) {
|
|
6581
|
+
const cleanSplit = seedCtx.errorsFromCallers > 0 && seedCtx.errorsEmittedHere === 0;
|
|
6582
|
+
const partialSplit = seedCtx.errorsFromCallers > seedCtx.errorsEmittedHere;
|
|
6583
|
+
let evidence = 0;
|
|
6584
|
+
evidence += cleanSplit ? 0.45 : partialSplit ? 0.2 : 0;
|
|
6585
|
+
evidence += seedCtx.stale ? 0.2 : 0;
|
|
6586
|
+
evidence += isSaturated(seedCtx) ? 0.15 : 0;
|
|
6587
|
+
evidence += (volumeWeight(originCtx.outboundVolume) - 0.5) * 0.4;
|
|
6588
|
+
const anchor = 0.45;
|
|
6589
|
+
const confidence = anchor + Math.min(1, evidence) * (LOAD_ORIGIN_CONFIDENCE_CEILING - anchor);
|
|
6590
|
+
return Math.max(0, Math.min(LOAD_ORIGIN_CONFIDENCE_CEILING, confidence));
|
|
6591
|
+
}
|
|
6592
|
+
function displayNameOf(nodeId) {
|
|
6593
|
+
return nodeId.replace(/^[a-z]+:/, "");
|
|
6594
|
+
}
|
|
6553
6595
|
function getRootCause(graph, errorNodeId, errorEvent, incidents, opts) {
|
|
6554
6596
|
const legacy = legacyRootCause(graph, errorNodeId, errorEvent, incidents);
|
|
6555
6597
|
if (!legacy) return null;
|
|
@@ -6564,20 +6606,20 @@ function enrichWithNavigation(graph, errorNodeId, legacy, incidents, now) {
|
|
|
6564
6606
|
const candidates = [];
|
|
6565
6607
|
if (seedCtx && isVictimSeed(seedCtx)) {
|
|
6566
6608
|
const origin = findLoadOrigin(graph, errorNodeId, incidents, now);
|
|
6609
|
+
const staleNote = seedCtx.stale ? "; it has gone STALE under load" : "";
|
|
6610
|
+
const satNote = isSaturated(seedCtx) ? `; its inbound p95 ${Math.round(seedCtx.latencyP95Ms)}ms is saturated` : "";
|
|
6567
6611
|
if (origin) {
|
|
6568
|
-
const
|
|
6569
|
-
const
|
|
6612
|
+
const originName = displayNameOf(origin.node);
|
|
6613
|
+
const seedName = displayNameOf(seedNode);
|
|
6570
6614
|
candidates.push({
|
|
6571
6615
|
node: origin.node,
|
|
6572
6616
|
classification: "primary-failure",
|
|
6573
|
-
reason:
|
|
6617
|
+
reason: `${originName} is the root cause: it overloads the failing subgraph, and the alerting node ${seedName} is a downstream symptom, not the fault \u2014 errors reach ${seedName} from its callers (${seedCtx.errorsFromCallers}), none originate there${staleNote}${satNote}. ${originName} is the upstream source driving that load (${origin.ctx.outboundVolume} observed outbound calls).`,
|
|
6574
6618
|
context: origin.ctx,
|
|
6575
|
-
confidence:
|
|
6619
|
+
confidence: loadOriginConfidence(origin.ctx, seedCtx),
|
|
6576
6620
|
provenance: import_types8.Provenance.OBSERVED
|
|
6577
6621
|
});
|
|
6578
6622
|
}
|
|
6579
|
-
const staleNote = seedCtx.stale ? "; the node has gone STALE" : "";
|
|
6580
|
-
const satNote = isSaturated(seedCtx) ? `; inbound p95 ${Math.round(seedCtx.latencyP95Ms)}ms is saturated` : "";
|
|
6581
6623
|
candidates.push({
|
|
6582
6624
|
node: seedNode,
|
|
6583
6625
|
classification: "symptom-only",
|
|
@@ -6600,25 +6642,36 @@ function enrichWithNavigation(graph, errorNodeId, legacy, incidents, now) {
|
|
|
6600
6642
|
let traversalPath = legacy.traversalPath;
|
|
6601
6643
|
let edgeProvenances = legacy.edgeProvenances;
|
|
6602
6644
|
if (top.node !== seedNode) {
|
|
6603
|
-
const
|
|
6604
|
-
if (
|
|
6605
|
-
traversalPath =
|
|
6606
|
-
edgeProvenances =
|
|
6645
|
+
const path71 = findPath(graph, errorNodeId, top.node, "up", ROOT_CAUSE_MAX_DEPTH);
|
|
6646
|
+
if (path71) {
|
|
6647
|
+
traversalPath = path71.nodes;
|
|
6648
|
+
edgeProvenances = path71.edges.map((e) => e.provenance);
|
|
6607
6649
|
} else {
|
|
6608
6650
|
traversalPath = [errorNodeId, top.node];
|
|
6609
6651
|
edgeProvenances = [top.provenance ?? import_types8.Provenance.OBSERVED];
|
|
6610
6652
|
}
|
|
6611
6653
|
}
|
|
6654
|
+
const fixRecommendation = fixRecommendationForTop(top, seedNode, legacy);
|
|
6612
6655
|
return import_types8.RootCauseResultSchema.parse({
|
|
6613
6656
|
rootCauseNode: top.node,
|
|
6614
6657
|
rootCauseReason: top.reason,
|
|
6615
6658
|
traversalPath,
|
|
6616
6659
|
edgeProvenances,
|
|
6617
6660
|
confidence: top.confidence,
|
|
6618
|
-
...
|
|
6661
|
+
...fixRecommendation ? { fixRecommendation } : {},
|
|
6619
6662
|
candidates
|
|
6620
6663
|
});
|
|
6621
6664
|
}
|
|
6665
|
+
function fixRecommendationForTop(top, seedNode, legacy) {
|
|
6666
|
+
if (top.classification === "primary-failure" && top.node === seedNode) {
|
|
6667
|
+
return legacy.fixRecommendation;
|
|
6668
|
+
}
|
|
6669
|
+
const name = top.node.replace(/^service:/, "");
|
|
6670
|
+
if (top.classification === "primary-failure") {
|
|
6671
|
+
return `Reduce or throttle the load from ${name} (or scale the saturated downstream capacity it drives) \u2014 the failure originates at this overloading source, not the starved callee.`;
|
|
6672
|
+
}
|
|
6673
|
+
return `${name} is a saturated/starved downstream victim; investigate its inbound load and upstream callers, not its own handler.`;
|
|
6674
|
+
}
|
|
6622
6675
|
|
|
6623
6676
|
// src/divergences.ts
|
|
6624
6677
|
function bucketKey(source, target, type) {
|
|
@@ -7004,11 +7057,11 @@ init_cjs_shims();
|
|
|
7004
7057
|
|
|
7005
7058
|
// src/extract/services.ts
|
|
7006
7059
|
init_cjs_shims();
|
|
7007
|
-
var
|
|
7008
|
-
var
|
|
7060
|
+
var import_node_fs17 = require("fs");
|
|
7061
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
7009
7062
|
var import_ignore = __toESM(require("ignore"), 1);
|
|
7010
7063
|
var import_minimatch2 = require("minimatch");
|
|
7011
|
-
var
|
|
7064
|
+
var import_types16 = require("@neat.is/types");
|
|
7012
7065
|
|
|
7013
7066
|
// src/extract/python.ts
|
|
7014
7067
|
init_cjs_shims();
|
|
@@ -7201,19 +7254,234 @@ async function discoverPhpService(scanPath, dir) {
|
|
|
7201
7254
|
return { pkg, dir, node };
|
|
7202
7255
|
}
|
|
7203
7256
|
|
|
7204
|
-
// src/extract/
|
|
7257
|
+
// src/extract/csharp.ts
|
|
7205
7258
|
init_cjs_shims();
|
|
7206
7259
|
var import_node_fs13 = require("fs");
|
|
7207
7260
|
var import_node_path15 = __toESM(require("path"), 1);
|
|
7261
|
+
var import_types13 = require("@neat.is/types");
|
|
7262
|
+
var CSHARP_PROJECT_EXTS = /* @__PURE__ */ new Set([".csproj", ".sln"]);
|
|
7263
|
+
async function projectFiles(dir) {
|
|
7264
|
+
const entries = await import_node_fs13.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
7265
|
+
const out = [];
|
|
7266
|
+
for (const entry of entries) {
|
|
7267
|
+
if (!entry.isFile()) continue;
|
|
7268
|
+
if (CSHARP_PROJECT_EXTS.has(import_node_path15.default.extname(entry.name).toLowerCase())) out.push(entry.name);
|
|
7269
|
+
}
|
|
7270
|
+
return out.sort();
|
|
7271
|
+
}
|
|
7272
|
+
var NESTED_PROJECT_DIR = "src";
|
|
7273
|
+
async function resolveProjectDir(dir) {
|
|
7274
|
+
if ((await projectFiles(dir)).length > 0) return dir;
|
|
7275
|
+
const nested = import_node_path15.default.join(dir, NESTED_PROJECT_DIR);
|
|
7276
|
+
if ((await projectFiles(nested)).length > 0) return nested;
|
|
7277
|
+
return null;
|
|
7278
|
+
}
|
|
7279
|
+
async function hasCsharpProject(dir) {
|
|
7280
|
+
return await resolveProjectDir(dir) !== null;
|
|
7281
|
+
}
|
|
7282
|
+
function parseCsproj(source) {
|
|
7283
|
+
const dependencies = {};
|
|
7284
|
+
const re = /<PackageReference\b([^>]*?)\/?>/g;
|
|
7285
|
+
let m;
|
|
7286
|
+
while ((m = re.exec(source)) !== null) {
|
|
7287
|
+
const attrs = m[1] ?? "";
|
|
7288
|
+
const include = attrs.match(/\bInclude\s*=\s*"([^"]+)"/)?.[1];
|
|
7289
|
+
if (!include) continue;
|
|
7290
|
+
const version = attrs.match(/\bVersion\s*=\s*"([^"]+)"/)?.[1];
|
|
7291
|
+
dependencies[include] = version ?? "";
|
|
7292
|
+
}
|
|
7293
|
+
return { dependencies };
|
|
7294
|
+
}
|
|
7295
|
+
async function discoverCsharpService(scanPath, dir) {
|
|
7296
|
+
const projectDir = await resolveProjectDir(dir);
|
|
7297
|
+
if (projectDir === null) return null;
|
|
7298
|
+
const projects = await projectFiles(projectDir);
|
|
7299
|
+
const csproj = projects.find((p) => p.toLowerCase().endsWith(".csproj"));
|
|
7300
|
+
const name = csproj ? import_node_path15.default.basename(csproj, import_node_path15.default.extname(csproj)) : import_node_path15.default.basename(dir);
|
|
7301
|
+
let dependencies = {};
|
|
7302
|
+
if (csproj) {
|
|
7303
|
+
const raw = await import_node_fs13.promises.readFile(import_node_path15.default.join(projectDir, csproj), "utf8").catch(() => "");
|
|
7304
|
+
dependencies = parseCsproj(raw).dependencies;
|
|
7305
|
+
}
|
|
7306
|
+
const pkg = { name, dependencies };
|
|
7307
|
+
const node = {
|
|
7308
|
+
id: (0, import_types13.serviceId)(name),
|
|
7309
|
+
type: import_types13.NodeType.ServiceNode,
|
|
7310
|
+
name,
|
|
7311
|
+
language: "csharp",
|
|
7312
|
+
dependencies,
|
|
7313
|
+
// Anchor on the directory that holds the project and its `.cs` files, so file
|
|
7314
|
+
// attribution reaches the source whether it sits at the root or under `src/`.
|
|
7315
|
+
repoPath: import_node_path15.default.relative(scanPath, projectDir)
|
|
7316
|
+
};
|
|
7317
|
+
return { pkg, dir: projectDir, node };
|
|
7318
|
+
}
|
|
7319
|
+
|
|
7320
|
+
// src/extract/java.ts
|
|
7321
|
+
init_cjs_shims();
|
|
7322
|
+
var import_node_fs14 = require("fs");
|
|
7323
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
7324
|
+
var import_types14 = require("@neat.is/types");
|
|
7325
|
+
var JAVA_MANIFESTS = ["pom.xml", "build.gradle", "build.gradle.kts"];
|
|
7326
|
+
async function hasJavaManifest(dir) {
|
|
7327
|
+
for (const manifest of JAVA_MANIFESTS) {
|
|
7328
|
+
if (await exists2(import_node_path16.default.join(dir, manifest))) return true;
|
|
7329
|
+
}
|
|
7330
|
+
return false;
|
|
7331
|
+
}
|
|
7332
|
+
function parsePomXml(source) {
|
|
7333
|
+
const dependencies = {};
|
|
7334
|
+
const depBlock = /<dependency\b[^>]*>([\s\S]*?)<\/dependency>/g;
|
|
7335
|
+
let d;
|
|
7336
|
+
while ((d = depBlock.exec(source)) !== null) {
|
|
7337
|
+
const body = d[1] ?? "";
|
|
7338
|
+
const groupId = body.match(/<groupId>\s*([^<]+?)\s*<\/groupId>/)?.[1];
|
|
7339
|
+
const artifactId = body.match(/<artifactId>\s*([^<]+?)\s*<\/artifactId>/)?.[1];
|
|
7340
|
+
if (!groupId || !artifactId) continue;
|
|
7341
|
+
const version = body.match(/<version>\s*([^<]+?)\s*<\/version>/)?.[1];
|
|
7342
|
+
dependencies[`${groupId}:${artifactId}`] = version ?? "";
|
|
7343
|
+
}
|
|
7344
|
+
const withoutBlocks = source.replace(/<parent\b[^>]*>[\s\S]*?<\/parent>/g, "").replace(/<dependencyManagement\b[^>]*>[\s\S]*?<\/dependencyManagement>/g, "").replace(/<dependencies\b[^>]*>[\s\S]*?<\/dependencies>/g, "").replace(/<build\b[^>]*>[\s\S]*?<\/build>/g, "");
|
|
7345
|
+
const name = withoutBlocks.match(/<artifactId>\s*([^<]+?)\s*<\/artifactId>/)?.[1];
|
|
7346
|
+
return { name, dependencies };
|
|
7347
|
+
}
|
|
7348
|
+
var GRADLE_CONFIGS = "implementation|api|compileOnly|runtimeOnly|compileOnlyApi|testImplementation|testRuntimeOnly|testCompileOnly|annotationProcessor|developmentOnly|runtimeClasspath";
|
|
7349
|
+
function parseGradle(source) {
|
|
7350
|
+
const dependencies = {};
|
|
7351
|
+
const re = new RegExp(`\\b(?:${GRADLE_CONFIGS})\\s*\\(?\\s*(['"])([^'"]+)\\1`, "g");
|
|
7352
|
+
let m;
|
|
7353
|
+
while ((m = re.exec(source)) !== null) {
|
|
7354
|
+
const coord = m[2] ?? "";
|
|
7355
|
+
const parts = coord.split(":");
|
|
7356
|
+
if (parts.length < 2 || !parts[0] || !parts[1]) continue;
|
|
7357
|
+
const key = `${parts[0]}:${parts[1]}`;
|
|
7358
|
+
dependencies[key] = parts.slice(2).join(":");
|
|
7359
|
+
}
|
|
7360
|
+
return { dependencies };
|
|
7361
|
+
}
|
|
7362
|
+
async function discoverJavaService(scanPath, dir) {
|
|
7363
|
+
const pomPath = import_node_path16.default.join(dir, "pom.xml");
|
|
7364
|
+
const gradlePath = import_node_path16.default.join(dir, "build.gradle");
|
|
7365
|
+
const gradleKtsPath = import_node_path16.default.join(dir, "build.gradle.kts");
|
|
7366
|
+
let manifest = null;
|
|
7367
|
+
if (await exists2(pomPath)) {
|
|
7368
|
+
manifest = parsePomXml(await import_node_fs14.promises.readFile(pomPath, "utf8").catch(() => ""));
|
|
7369
|
+
} else if (await exists2(gradlePath)) {
|
|
7370
|
+
manifest = parseGradle(await import_node_fs14.promises.readFile(gradlePath, "utf8").catch(() => ""));
|
|
7371
|
+
} else if (await exists2(gradleKtsPath)) {
|
|
7372
|
+
manifest = parseGradle(await import_node_fs14.promises.readFile(gradleKtsPath, "utf8").catch(() => ""));
|
|
7373
|
+
}
|
|
7374
|
+
if (!manifest) return null;
|
|
7375
|
+
const name = manifest.name?.trim() || import_node_path16.default.basename(dir);
|
|
7376
|
+
const dependencies = manifest.dependencies;
|
|
7377
|
+
const pkg = { name, dependencies };
|
|
7378
|
+
const node = {
|
|
7379
|
+
id: (0, import_types14.serviceId)(name),
|
|
7380
|
+
type: import_types14.NodeType.ServiceNode,
|
|
7381
|
+
name,
|
|
7382
|
+
language: "java",
|
|
7383
|
+
dependencies,
|
|
7384
|
+
repoPath: import_node_path16.default.relative(scanPath, dir)
|
|
7385
|
+
};
|
|
7386
|
+
return { pkg, dir, node };
|
|
7387
|
+
}
|
|
7388
|
+
|
|
7389
|
+
// src/extract/dockerfile-service.ts
|
|
7390
|
+
init_cjs_shims();
|
|
7391
|
+
var import_node_fs15 = require("fs");
|
|
7392
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
7393
|
+
var import_types15 = require("@neat.is/types");
|
|
7394
|
+
function languageForSourceExt(ext) {
|
|
7395
|
+
switch (ext) {
|
|
7396
|
+
case ".py":
|
|
7397
|
+
return "python";
|
|
7398
|
+
case ".go":
|
|
7399
|
+
return "go";
|
|
7400
|
+
case ".rb":
|
|
7401
|
+
return "ruby";
|
|
7402
|
+
case ".php":
|
|
7403
|
+
return "php";
|
|
7404
|
+
case ".cs":
|
|
7405
|
+
return "csharp";
|
|
7406
|
+
case ".java":
|
|
7407
|
+
return "java";
|
|
7408
|
+
case ".ts":
|
|
7409
|
+
case ".tsx":
|
|
7410
|
+
return "typescript";
|
|
7411
|
+
case ".js":
|
|
7412
|
+
case ".mjs":
|
|
7413
|
+
case ".cjs":
|
|
7414
|
+
return "javascript";
|
|
7415
|
+
default:
|
|
7416
|
+
return null;
|
|
7417
|
+
}
|
|
7418
|
+
}
|
|
7419
|
+
var LANGUAGE_PRECEDENCE = ["typescript", "javascript", "python", "go", "ruby", "php", "csharp", "java"];
|
|
7420
|
+
async function inferServiceLanguage(dir) {
|
|
7421
|
+
const entries = await import_node_fs15.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
7422
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7423
|
+
for (const entry of entries) {
|
|
7424
|
+
if (!entry.isFile()) continue;
|
|
7425
|
+
if (isNeatAuthoredSourceFile(entry.name)) continue;
|
|
7426
|
+
const ext = import_node_path17.default.extname(entry.name).toLowerCase();
|
|
7427
|
+
if (!SERVICE_FILE_EXTENSIONS.has(ext)) continue;
|
|
7428
|
+
const lang = languageForSourceExt(ext);
|
|
7429
|
+
if (!lang) continue;
|
|
7430
|
+
counts.set(lang, (counts.get(lang) ?? 0) + 1);
|
|
7431
|
+
}
|
|
7432
|
+
if (counts.size === 0) return null;
|
|
7433
|
+
let best = null;
|
|
7434
|
+
let bestCount = -1;
|
|
7435
|
+
for (const lang of LANGUAGE_PRECEDENCE) {
|
|
7436
|
+
const c = counts.get(lang) ?? 0;
|
|
7437
|
+
if (c > bestCount) {
|
|
7438
|
+
best = lang;
|
|
7439
|
+
bestCount = c;
|
|
7440
|
+
}
|
|
7441
|
+
}
|
|
7442
|
+
return best;
|
|
7443
|
+
}
|
|
7444
|
+
async function hasLanguageManifest(dir) {
|
|
7445
|
+
return await exists2(import_node_path17.default.join(dir, "package.json")) || await exists2(import_node_path17.default.join(dir, "pyproject.toml")) || await exists2(import_node_path17.default.join(dir, "requirements.txt")) || await exists2(import_node_path17.default.join(dir, "setup.py")) || await exists2(import_node_path17.default.join(dir, "go.mod")) || await exists2(import_node_path17.default.join(dir, "Gemfile")) || await exists2(import_node_path17.default.join(dir, "composer.json")) || // C#'s marker is a glob (`*.csproj` / `*.sln`), so it reads the directory
|
|
7446
|
+
// rather than probing a fixed filename (ADR-196).
|
|
7447
|
+
await hasCsharpProject(dir) || // Java keys on a Maven / Gradle build manifest (ADR-197).
|
|
7448
|
+
await hasJavaManifest(dir);
|
|
7449
|
+
}
|
|
7450
|
+
async function hasDockerfileDeclaredService(dir) {
|
|
7451
|
+
if (!await exists2(import_node_path17.default.join(dir, "Dockerfile"))) return false;
|
|
7452
|
+
return await inferServiceLanguage(dir) !== null;
|
|
7453
|
+
}
|
|
7454
|
+
async function discoverDockerfileService(scanPath, dir) {
|
|
7455
|
+
if (!await exists2(import_node_path17.default.join(dir, "Dockerfile"))) return null;
|
|
7456
|
+
if (await hasLanguageManifest(dir)) return null;
|
|
7457
|
+
const language = await inferServiceLanguage(dir);
|
|
7458
|
+
if (!language) return null;
|
|
7459
|
+
const name = import_node_path17.default.basename(dir);
|
|
7460
|
+
const pkg = { name, dependencies: {} };
|
|
7461
|
+
const node = {
|
|
7462
|
+
id: (0, import_types15.serviceId)(name),
|
|
7463
|
+
type: import_types15.NodeType.ServiceNode,
|
|
7464
|
+
name,
|
|
7465
|
+
language,
|
|
7466
|
+
dependencies: {},
|
|
7467
|
+
repoPath: import_node_path17.default.relative(scanPath, dir)
|
|
7468
|
+
};
|
|
7469
|
+
return { pkg, dir, node };
|
|
7470
|
+
}
|
|
7471
|
+
|
|
7472
|
+
// src/extract/owners.ts
|
|
7473
|
+
init_cjs_shims();
|
|
7474
|
+
var import_node_fs16 = require("fs");
|
|
7475
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
7208
7476
|
var import_minimatch = require("minimatch");
|
|
7209
7477
|
async function loadCodeowners(scanPath) {
|
|
7210
7478
|
const candidates = [
|
|
7211
|
-
|
|
7212
|
-
|
|
7479
|
+
import_node_path18.default.join(scanPath, "CODEOWNERS"),
|
|
7480
|
+
import_node_path18.default.join(scanPath, ".github", "CODEOWNERS")
|
|
7213
7481
|
];
|
|
7214
7482
|
for (const file of candidates) {
|
|
7215
7483
|
if (await exists2(file)) {
|
|
7216
|
-
const raw = await
|
|
7484
|
+
const raw = await import_node_fs16.promises.readFile(file, "utf8");
|
|
7217
7485
|
return parseCodeowners(raw);
|
|
7218
7486
|
}
|
|
7219
7487
|
}
|
|
@@ -7231,7 +7499,7 @@ function parseCodeowners(raw) {
|
|
|
7231
7499
|
return { rules };
|
|
7232
7500
|
}
|
|
7233
7501
|
function matchOwner(file, repoPath) {
|
|
7234
|
-
const normalized = repoPath.split(
|
|
7502
|
+
const normalized = repoPath.split(import_node_path18.default.sep).join("/");
|
|
7235
7503
|
for (const rule of file.rules) {
|
|
7236
7504
|
if (matchesPattern(rule.pattern, normalized)) return rule.owners;
|
|
7237
7505
|
}
|
|
@@ -7247,7 +7515,7 @@ function matchesPattern(rawPattern, repoPath) {
|
|
|
7247
7515
|
return false;
|
|
7248
7516
|
}
|
|
7249
7517
|
async function readPackageJsonAuthor(serviceDir) {
|
|
7250
|
-
const pkgPath =
|
|
7518
|
+
const pkgPath = import_node_path18.default.join(serviceDir, "package.json");
|
|
7251
7519
|
if (!await exists2(pkgPath)) return null;
|
|
7252
7520
|
try {
|
|
7253
7521
|
const pkg = await readJson(pkgPath);
|
|
@@ -7284,33 +7552,36 @@ function workspaceGlobs(pkg) {
|
|
|
7284
7552
|
return null;
|
|
7285
7553
|
}
|
|
7286
7554
|
async function hasPythonManifest(dir) {
|
|
7287
|
-
return await exists2(
|
|
7555
|
+
return await exists2(import_node_path19.default.join(dir, "pyproject.toml")) || await exists2(import_node_path19.default.join(dir, "requirements.txt")) || await exists2(import_node_path19.default.join(dir, "setup.py"));
|
|
7288
7556
|
}
|
|
7289
7557
|
async function hasGoManifest(dir) {
|
|
7290
|
-
return exists2(
|
|
7558
|
+
return exists2(import_node_path19.default.join(dir, "go.mod"));
|
|
7291
7559
|
}
|
|
7292
7560
|
async function hasRubyManifest(dir) {
|
|
7293
|
-
return exists2(
|
|
7561
|
+
return exists2(import_node_path19.default.join(dir, "Gemfile"));
|
|
7294
7562
|
}
|
|
7295
7563
|
async function hasPhpManifest(dir) {
|
|
7296
|
-
return exists2(
|
|
7564
|
+
return exists2(import_node_path19.default.join(dir, "composer.json"));
|
|
7565
|
+
}
|
|
7566
|
+
async function hasCsharpManifest(dir) {
|
|
7567
|
+
return hasCsharpProject(dir);
|
|
7297
7568
|
}
|
|
7298
7569
|
async function loadGitignore(scanPath) {
|
|
7299
|
-
const gitignorePath =
|
|
7570
|
+
const gitignorePath = import_node_path19.default.join(scanPath, ".gitignore");
|
|
7300
7571
|
if (!await exists2(gitignorePath)) return null;
|
|
7301
|
-
const raw = await
|
|
7572
|
+
const raw = await import_node_fs17.promises.readFile(gitignorePath, "utf8");
|
|
7302
7573
|
return (0, import_ignore.default)().add(raw);
|
|
7303
7574
|
}
|
|
7304
7575
|
async function walkDirs(start, scanPath, options, visit) {
|
|
7305
7576
|
async function recurse(current, depth) {
|
|
7306
7577
|
if (depth > options.maxDepth) return;
|
|
7307
|
-
const entries = await
|
|
7578
|
+
const entries = await import_node_fs17.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
7308
7579
|
for (const entry of entries) {
|
|
7309
7580
|
if (!entry.isDirectory()) continue;
|
|
7310
7581
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
7311
|
-
const child =
|
|
7582
|
+
const child = import_node_path19.default.join(current, entry.name);
|
|
7312
7583
|
if (options.ig) {
|
|
7313
|
-
const rel =
|
|
7584
|
+
const rel = import_node_path19.default.relative(scanPath, child).split(import_node_path19.default.sep).join("/");
|
|
7314
7585
|
if (rel && options.ig.ignores(rel + "/")) continue;
|
|
7315
7586
|
}
|
|
7316
7587
|
if (await isPythonVenvDir(child)) continue;
|
|
@@ -7326,8 +7597,8 @@ async function expandWorkspaceGlobs(scanPath, globs) {
|
|
|
7326
7597
|
for (const raw of globs) {
|
|
7327
7598
|
const pattern = raw.replace(/^\.\//, "");
|
|
7328
7599
|
if (!pattern.includes("*")) {
|
|
7329
|
-
const candidate =
|
|
7330
|
-
if (await exists2(
|
|
7600
|
+
const candidate = import_node_path19.default.join(scanPath, pattern);
|
|
7601
|
+
if (await exists2(import_node_path19.default.join(candidate, "package.json"))) found.add(candidate);
|
|
7331
7602
|
continue;
|
|
7332
7603
|
}
|
|
7333
7604
|
const segments = pattern.split("/");
|
|
@@ -7336,13 +7607,13 @@ async function expandWorkspaceGlobs(scanPath, globs) {
|
|
|
7336
7607
|
if (seg.includes("*")) break;
|
|
7337
7608
|
staticSegments.push(seg);
|
|
7338
7609
|
}
|
|
7339
|
-
const start =
|
|
7610
|
+
const start = import_node_path19.default.join(scanPath, ...staticSegments);
|
|
7340
7611
|
if (!await exists2(start)) continue;
|
|
7341
7612
|
const hasDoubleStar = pattern.includes("**");
|
|
7342
7613
|
const walkDepth = hasDoubleStar ? scanDepth : Math.max(0, segments.length - staticSegments.length - 1);
|
|
7343
7614
|
await walkDirs(start, scanPath, { maxDepth: walkDepth, ig: null }, async (dir) => {
|
|
7344
|
-
const rel =
|
|
7345
|
-
if ((0, import_minimatch2.minimatch)(rel, pattern) && await exists2(
|
|
7615
|
+
const rel = import_node_path19.default.relative(scanPath, dir).split(import_node_path19.default.sep).join("/");
|
|
7616
|
+
if ((0, import_minimatch2.minimatch)(rel, pattern) && await exists2(import_node_path19.default.join(dir, "package.json"))) {
|
|
7346
7617
|
found.add(dir);
|
|
7347
7618
|
}
|
|
7348
7619
|
});
|
|
@@ -7365,31 +7636,31 @@ function detectJsFramework(pkg) {
|
|
|
7365
7636
|
async function detectJsServiceLanguage(dir, pkg) {
|
|
7366
7637
|
const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
7367
7638
|
if (deps["typescript"] !== void 0) return "typescript";
|
|
7368
|
-
const entries = await
|
|
7639
|
+
const entries = await import_node_fs17.promises.readdir(dir).catch(() => []);
|
|
7369
7640
|
if (entries.some((name) => /^tsconfig(\..+)?\.json$/.test(name))) return "typescript";
|
|
7370
7641
|
return "javascript";
|
|
7371
7642
|
}
|
|
7372
7643
|
async function discoverNodeService(scanPath, dir) {
|
|
7373
|
-
const pkgPath =
|
|
7644
|
+
const pkgPath = import_node_path19.default.join(dir, "package.json");
|
|
7374
7645
|
if (!await exists2(pkgPath)) return null;
|
|
7375
7646
|
let pkg;
|
|
7376
7647
|
try {
|
|
7377
7648
|
pkg = await readJson(pkgPath);
|
|
7378
7649
|
} catch (err) {
|
|
7379
|
-
recordExtractionError("services",
|
|
7650
|
+
recordExtractionError("services", import_node_path19.default.relative(scanPath, pkgPath), err);
|
|
7380
7651
|
return null;
|
|
7381
7652
|
}
|
|
7382
7653
|
if (!pkg.name) return null;
|
|
7383
7654
|
const framework = detectJsFramework(pkg);
|
|
7384
7655
|
const language = await detectJsServiceLanguage(dir, pkg);
|
|
7385
7656
|
const node = {
|
|
7386
|
-
id: (0,
|
|
7387
|
-
type:
|
|
7657
|
+
id: (0, import_types16.serviceId)(pkg.name),
|
|
7658
|
+
type: import_types16.NodeType.ServiceNode,
|
|
7388
7659
|
name: pkg.name,
|
|
7389
7660
|
language,
|
|
7390
7661
|
version: pkg.version,
|
|
7391
7662
|
dependencies: pkg.dependencies ?? {},
|
|
7392
|
-
repoPath:
|
|
7663
|
+
repoPath: import_node_path19.default.relative(scanPath, dir),
|
|
7393
7664
|
...pkg.engines?.node ? { nodeEngine: pkg.engines.node } : {},
|
|
7394
7665
|
...framework ? { framework } : {}
|
|
7395
7666
|
};
|
|
@@ -7400,18 +7671,18 @@ async function discoverPyService(scanPath, dir) {
|
|
|
7400
7671
|
if (!py) return null;
|
|
7401
7672
|
const pkg = pythonToPackage(py);
|
|
7402
7673
|
const node = {
|
|
7403
|
-
id: (0,
|
|
7404
|
-
type:
|
|
7674
|
+
id: (0, import_types16.serviceId)(py.name),
|
|
7675
|
+
type: import_types16.NodeType.ServiceNode,
|
|
7405
7676
|
name: py.name,
|
|
7406
7677
|
language: "python",
|
|
7407
7678
|
version: py.version,
|
|
7408
7679
|
dependencies: py.dependencies,
|
|
7409
|
-
repoPath:
|
|
7680
|
+
repoPath: import_node_path19.default.relative(scanPath, dir)
|
|
7410
7681
|
};
|
|
7411
7682
|
return { pkg, dir, node };
|
|
7412
7683
|
}
|
|
7413
7684
|
async function discoverServices(scanPath) {
|
|
7414
|
-
const rootPkgPath =
|
|
7685
|
+
const rootPkgPath = import_node_path19.default.join(scanPath, "package.json");
|
|
7415
7686
|
let rootPkg = null;
|
|
7416
7687
|
if (await exists2(rootPkgPath)) {
|
|
7417
7688
|
try {
|
|
@@ -7419,7 +7690,7 @@ async function discoverServices(scanPath) {
|
|
|
7419
7690
|
} catch (err) {
|
|
7420
7691
|
recordExtractionError(
|
|
7421
7692
|
"services workspaces",
|
|
7422
|
-
|
|
7693
|
+
import_node_path19.default.relative(scanPath, rootPkgPath),
|
|
7423
7694
|
err
|
|
7424
7695
|
);
|
|
7425
7696
|
}
|
|
@@ -7431,7 +7702,7 @@ async function discoverServices(scanPath) {
|
|
|
7431
7702
|
} else {
|
|
7432
7703
|
if (rootPkg && rootPkg.name) {
|
|
7433
7704
|
candidateDirs.push(scanPath);
|
|
7434
|
-
} else if (await hasPythonManifest(scanPath) || await hasGoManifest(scanPath) || await hasRubyManifest(scanPath) || await hasPhpManifest(scanPath)) {
|
|
7705
|
+
} else if (await hasPythonManifest(scanPath) || await hasGoManifest(scanPath) || await hasRubyManifest(scanPath) || await hasPhpManifest(scanPath) || await hasCsharpManifest(scanPath) || await hasJavaManifest(scanPath)) {
|
|
7435
7706
|
candidateDirs.push(scanPath);
|
|
7436
7707
|
}
|
|
7437
7708
|
const ig = await loadGitignore(scanPath);
|
|
@@ -7440,9 +7711,11 @@ async function discoverServices(scanPath) {
|
|
|
7440
7711
|
scanPath,
|
|
7441
7712
|
{ maxDepth: parseScanDepth(), ig },
|
|
7442
7713
|
async (dir) => {
|
|
7443
|
-
if (await exists2(
|
|
7714
|
+
if (await exists2(import_node_path19.default.join(dir, "package.json"))) {
|
|
7444
7715
|
candidateDirs.push(dir);
|
|
7445
|
-
} else if (await hasPythonManifest(dir) || await hasGoManifest(dir) || await hasRubyManifest(dir) || await hasPhpManifest(dir)) {
|
|
7716
|
+
} else if (await hasPythonManifest(dir) || await hasGoManifest(dir) || await hasRubyManifest(dir) || await hasPhpManifest(dir) || await hasCsharpManifest(dir) || await hasJavaManifest(dir)) {
|
|
7717
|
+
candidateDirs.push(dir);
|
|
7718
|
+
} else if (await hasDockerfileDeclaredService(dir)) {
|
|
7446
7719
|
candidateDirs.push(dir);
|
|
7447
7720
|
}
|
|
7448
7721
|
}
|
|
@@ -7450,14 +7723,17 @@ async function discoverServices(scanPath) {
|
|
|
7450
7723
|
}
|
|
7451
7724
|
candidateDirs.sort();
|
|
7452
7725
|
const seen = /* @__PURE__ */ new Map();
|
|
7726
|
+
const seenDirs = /* @__PURE__ */ new Set();
|
|
7453
7727
|
const out = [];
|
|
7454
7728
|
for (const dir of candidateDirs) {
|
|
7455
|
-
const service = await discoverNodeService(scanPath, dir) ?? await discoverPyService(scanPath, dir) ?? await discoverGoService(scanPath, dir) ?? await discoverRubyService(scanPath, dir) ?? await discoverPhpService(scanPath, dir);
|
|
7729
|
+
const service = await discoverNodeService(scanPath, dir) ?? await discoverPyService(scanPath, dir) ?? await discoverGoService(scanPath, dir) ?? await discoverRubyService(scanPath, dir) ?? await discoverPhpService(scanPath, dir) ?? await discoverCsharpService(scanPath, dir) ?? await discoverJavaService(scanPath, dir) ?? await discoverDockerfileService(scanPath, dir);
|
|
7456
7730
|
if (!service) continue;
|
|
7731
|
+
if (seenDirs.has(service.dir)) continue;
|
|
7732
|
+
seenDirs.add(service.dir);
|
|
7457
7733
|
const existingDir = seen.get(service.node.name);
|
|
7458
7734
|
if (existingDir !== void 0) {
|
|
7459
|
-
const a =
|
|
7460
|
-
const b =
|
|
7735
|
+
const a = import_node_path19.default.relative(scanPath, existingDir) || ".";
|
|
7736
|
+
const b = import_node_path19.default.relative(scanPath, dir) || ".";
|
|
7461
7737
|
console.warn(
|
|
7462
7738
|
`[neat] duplicate package name "${service.node.name}" \u2014 keeping ${a}, ignoring ${b}`
|
|
7463
7739
|
);
|
|
@@ -7494,20 +7770,20 @@ function addServiceNodes(graph, services) {
|
|
|
7494
7770
|
|
|
7495
7771
|
// src/extract/aliases.ts
|
|
7496
7772
|
init_cjs_shims();
|
|
7497
|
-
var
|
|
7498
|
-
var
|
|
7773
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
7774
|
+
var import_node_fs18 = require("fs");
|
|
7499
7775
|
var import_yaml2 = require("yaml");
|
|
7500
|
-
var
|
|
7776
|
+
var import_types17 = require("@neat.is/types");
|
|
7501
7777
|
var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
7502
7778
|
"Service",
|
|
7503
7779
|
"Deployment",
|
|
7504
7780
|
"StatefulSet",
|
|
7505
7781
|
"DaemonSet"
|
|
7506
7782
|
]);
|
|
7507
|
-
function addAliases(graph,
|
|
7508
|
-
if (!graph.hasNode(
|
|
7509
|
-
const node = graph.getNodeAttributes(
|
|
7510
|
-
if (node.type !==
|
|
7783
|
+
function addAliases(graph, serviceId12, candidates) {
|
|
7784
|
+
if (!graph.hasNode(serviceId12)) return;
|
|
7785
|
+
const node = graph.getNodeAttributes(serviceId12);
|
|
7786
|
+
if (node.type !== import_types17.NodeType.ServiceNode) return;
|
|
7511
7787
|
const set = new Set(node.aliases ?? []);
|
|
7512
7788
|
for (const c of candidates) {
|
|
7513
7789
|
if (!c) continue;
|
|
@@ -7516,20 +7792,20 @@ function addAliases(graph, serviceId9, candidates) {
|
|
|
7516
7792
|
}
|
|
7517
7793
|
if (set.size === 0) return;
|
|
7518
7794
|
const updated = { ...node, aliases: [...set].sort() };
|
|
7519
|
-
graph.replaceNodeAttributes(
|
|
7795
|
+
graph.replaceNodeAttributes(serviceId12, updated);
|
|
7520
7796
|
}
|
|
7521
7797
|
function indexServicesByName(services) {
|
|
7522
7798
|
const map = /* @__PURE__ */ new Map();
|
|
7523
7799
|
for (const s of services) {
|
|
7524
7800
|
map.set(s.node.name, s.node.id);
|
|
7525
|
-
map.set(
|
|
7801
|
+
map.set(import_node_path20.default.basename(s.dir), s.node.id);
|
|
7526
7802
|
}
|
|
7527
7803
|
return map;
|
|
7528
7804
|
}
|
|
7529
7805
|
async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
7530
7806
|
let composePath = null;
|
|
7531
7807
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
7532
|
-
const abs =
|
|
7808
|
+
const abs = import_node_path20.default.join(scanPath, name);
|
|
7533
7809
|
if (await exists2(abs)) {
|
|
7534
7810
|
composePath = abs;
|
|
7535
7811
|
break;
|
|
@@ -7542,19 +7818,19 @@ async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
|
7542
7818
|
} catch (err) {
|
|
7543
7819
|
recordExtractionError(
|
|
7544
7820
|
"aliases compose",
|
|
7545
|
-
|
|
7821
|
+
import_node_path20.default.relative(scanPath, composePath),
|
|
7546
7822
|
err
|
|
7547
7823
|
);
|
|
7548
7824
|
return;
|
|
7549
7825
|
}
|
|
7550
7826
|
if (!compose?.services) return;
|
|
7551
7827
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
7552
|
-
const
|
|
7553
|
-
if (!
|
|
7828
|
+
const serviceId12 = serviceIndex.get(composeName);
|
|
7829
|
+
if (!serviceId12) continue;
|
|
7554
7830
|
const aliases = /* @__PURE__ */ new Set([composeName]);
|
|
7555
7831
|
if (svc.container_name) aliases.add(svc.container_name);
|
|
7556
7832
|
if (svc.hostname) aliases.add(svc.hostname);
|
|
7557
|
-
addAliases(graph,
|
|
7833
|
+
addAliases(graph, serviceId12, aliases);
|
|
7558
7834
|
}
|
|
7559
7835
|
}
|
|
7560
7836
|
var LABEL_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -7585,11 +7861,11 @@ function parseDockerfileLabels(content) {
|
|
|
7585
7861
|
}
|
|
7586
7862
|
async function collectDockerfileAliases(graph, services) {
|
|
7587
7863
|
for (const service of services) {
|
|
7588
|
-
const dockerfilePath =
|
|
7864
|
+
const dockerfilePath = import_node_path20.default.join(service.dir, "Dockerfile");
|
|
7589
7865
|
if (!await exists2(dockerfilePath)) continue;
|
|
7590
7866
|
let content;
|
|
7591
7867
|
try {
|
|
7592
|
-
content = await
|
|
7868
|
+
content = await import_node_fs18.promises.readFile(dockerfilePath, "utf8");
|
|
7593
7869
|
} catch (err) {
|
|
7594
7870
|
recordExtractionError("aliases dockerfile", dockerfilePath, err);
|
|
7595
7871
|
continue;
|
|
@@ -7601,15 +7877,15 @@ async function collectDockerfileAliases(graph, services) {
|
|
|
7601
7877
|
async function walkYamlFiles(start, depth = 0, max = 5) {
|
|
7602
7878
|
if (depth > max) return [];
|
|
7603
7879
|
const out = [];
|
|
7604
|
-
const entries = await
|
|
7880
|
+
const entries = await import_node_fs18.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
7605
7881
|
for (const entry of entries) {
|
|
7606
7882
|
if (entry.isDirectory()) {
|
|
7607
7883
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
7608
|
-
const child =
|
|
7884
|
+
const child = import_node_path20.default.join(start, entry.name);
|
|
7609
7885
|
if (await isPythonVenvDir(child)) continue;
|
|
7610
7886
|
out.push(...await walkYamlFiles(child, depth + 1, max));
|
|
7611
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
7612
|
-
out.push(
|
|
7887
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path20.default.extname(entry.name))) {
|
|
7888
|
+
out.push(import_node_path20.default.join(start, entry.name));
|
|
7613
7889
|
}
|
|
7614
7890
|
}
|
|
7615
7891
|
return out;
|
|
@@ -7636,7 +7912,7 @@ function k8sServiceTarget(doc, byName) {
|
|
|
7636
7912
|
async function collectK8sAliases(graph, scanPath, serviceIndex) {
|
|
7637
7913
|
const files = await walkYamlFiles(scanPath);
|
|
7638
7914
|
for (const file of files) {
|
|
7639
|
-
const content = await
|
|
7915
|
+
const content = await import_node_fs18.promises.readFile(file, "utf8");
|
|
7640
7916
|
let docs;
|
|
7641
7917
|
try {
|
|
7642
7918
|
docs = (0, import_yaml2.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
@@ -7661,14 +7937,14 @@ async function addServiceAliases(graph, scanPath, services) {
|
|
|
7661
7937
|
|
|
7662
7938
|
// src/extract/files.ts
|
|
7663
7939
|
init_cjs_shims();
|
|
7664
|
-
var
|
|
7940
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
7665
7941
|
async function addFiles(graph, services) {
|
|
7666
7942
|
let nodesAdded = 0;
|
|
7667
7943
|
let edgesAdded = 0;
|
|
7668
7944
|
for (const service of services) {
|
|
7669
7945
|
const filePaths = await walkSourceFiles(service.dir);
|
|
7670
7946
|
for (const filePath of filePaths) {
|
|
7671
|
-
const relPath = toPosix(
|
|
7947
|
+
const relPath = toPosix(import_node_path21.default.relative(service.dir, filePath));
|
|
7672
7948
|
const { nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
7673
7949
|
graph,
|
|
7674
7950
|
service.pkg.name,
|
|
@@ -7684,11 +7960,17 @@ async function addFiles(graph, services) {
|
|
|
7684
7960
|
|
|
7685
7961
|
// src/extract/symbols.ts
|
|
7686
7962
|
init_cjs_shims();
|
|
7687
|
-
var
|
|
7963
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
7688
7964
|
var import_tree_sitter3 = __toESM(require("tree-sitter"), 1);
|
|
7689
7965
|
var import_tree_sitter_javascript3 = __toESM(require("tree-sitter-javascript"), 1);
|
|
7690
7966
|
var import_tree_sitter_typescript = __toESM(require("tree-sitter-typescript"), 1);
|
|
7691
|
-
var
|
|
7967
|
+
var import_tree_sitter_python3 = __toESM(require("tree-sitter-python"), 1);
|
|
7968
|
+
var import_tree_sitter_go3 = __toESM(require("tree-sitter-go"), 1);
|
|
7969
|
+
var import_tree_sitter_ruby2 = __toESM(require("tree-sitter-ruby"), 1);
|
|
7970
|
+
var import_tree_sitter_php2 = __toESM(require("tree-sitter-php"), 1);
|
|
7971
|
+
var import_tree_sitter_c_sharp = __toESM(require("tree-sitter-c-sharp"), 1);
|
|
7972
|
+
var import_tree_sitter_java = __toESM(require("tree-sitter-java"), 1);
|
|
7973
|
+
var import_types18 = require("@neat.is/types");
|
|
7692
7974
|
var PARSE_CHUNK3 = 16384;
|
|
7693
7975
|
var GRAMMAR_BY_EXT = {
|
|
7694
7976
|
".ts": import_tree_sitter_typescript.default.typescript,
|
|
@@ -7698,6 +7980,15 @@ var GRAMMAR_BY_EXT = {
|
|
|
7698
7980
|
".mjs": import_tree_sitter_javascript3.default,
|
|
7699
7981
|
".cjs": import_tree_sitter_javascript3.default
|
|
7700
7982
|
};
|
|
7983
|
+
var SYMBOL_GRAMMAR_BY_EXT = {
|
|
7984
|
+
...GRAMMAR_BY_EXT,
|
|
7985
|
+
".py": import_tree_sitter_python3.default,
|
|
7986
|
+
".go": import_tree_sitter_go3.default,
|
|
7987
|
+
".rb": import_tree_sitter_ruby2.default,
|
|
7988
|
+
".php": import_tree_sitter_php2.default.php_only,
|
|
7989
|
+
".cs": import_tree_sitter_c_sharp.default,
|
|
7990
|
+
".java": import_tree_sitter_java.default
|
|
7991
|
+
};
|
|
7701
7992
|
function parseSource3(parser, source) {
|
|
7702
7993
|
return parser.parse(
|
|
7703
7994
|
(index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK3)
|
|
@@ -7758,14 +8049,375 @@ function collectSymbolDefs(root) {
|
|
|
7758
8049
|
break;
|
|
7759
8050
|
}
|
|
7760
8051
|
}
|
|
7761
|
-
for (let i = 0; i < node.namedChildCount; i++) {
|
|
7762
|
-
const child = node.namedChild(i);
|
|
7763
|
-
if (child) visit(child, classCtx);
|
|
7764
|
-
}
|
|
8052
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
8053
|
+
const child = node.namedChild(i);
|
|
8054
|
+
if (child) visit(child, classCtx);
|
|
8055
|
+
}
|
|
8056
|
+
};
|
|
8057
|
+
visit(root, void 0);
|
|
8058
|
+
return out;
|
|
8059
|
+
}
|
|
8060
|
+
function collectPythonSymbolDefs(root) {
|
|
8061
|
+
const out = [];
|
|
8062
|
+
const push = (kind, qualname, node) => {
|
|
8063
|
+
out.push({
|
|
8064
|
+
kind,
|
|
8065
|
+
qualname,
|
|
8066
|
+
startLine: node.startPosition.row + 1,
|
|
8067
|
+
endLine: node.endPosition.row + 1
|
|
8068
|
+
});
|
|
8069
|
+
};
|
|
8070
|
+
const visit = (node, classCtx) => {
|
|
8071
|
+
switch (node.type) {
|
|
8072
|
+
case "function_definition": {
|
|
8073
|
+
const name = node.childForFieldName("name")?.text;
|
|
8074
|
+
if (name) {
|
|
8075
|
+
if (classCtx) {
|
|
8076
|
+
const kind = name === "__init__" ? "constructor" : "method";
|
|
8077
|
+
push(kind, `${classCtx}.${name}`, node);
|
|
8078
|
+
} else {
|
|
8079
|
+
push("function", name, node);
|
|
8080
|
+
}
|
|
8081
|
+
}
|
|
8082
|
+
const body = node.childForFieldName("body");
|
|
8083
|
+
if (body) {
|
|
8084
|
+
for (let i = 0; i < body.namedChildCount; i++) {
|
|
8085
|
+
const child = body.namedChild(i);
|
|
8086
|
+
if (child) visit(child, void 0);
|
|
8087
|
+
}
|
|
8088
|
+
}
|
|
8089
|
+
return;
|
|
8090
|
+
}
|
|
8091
|
+
case "class_definition": {
|
|
8092
|
+
const name = node.childForFieldName("name")?.text;
|
|
8093
|
+
if (name) push("class", name, node);
|
|
8094
|
+
const body = node.childForFieldName("body");
|
|
8095
|
+
if (body) {
|
|
8096
|
+
for (let i = 0; i < body.namedChildCount; i++) {
|
|
8097
|
+
const child = body.namedChild(i);
|
|
8098
|
+
if (child) visit(child, name ?? classCtx);
|
|
8099
|
+
}
|
|
8100
|
+
}
|
|
8101
|
+
return;
|
|
8102
|
+
}
|
|
8103
|
+
case "decorated_definition": {
|
|
8104
|
+
const def = node.childForFieldName("definition");
|
|
8105
|
+
if (def) visit(def, classCtx);
|
|
8106
|
+
return;
|
|
8107
|
+
}
|
|
8108
|
+
}
|
|
8109
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
8110
|
+
const child = node.namedChild(i);
|
|
8111
|
+
if (child) visit(child, classCtx);
|
|
8112
|
+
}
|
|
8113
|
+
};
|
|
8114
|
+
visit(root, void 0);
|
|
8115
|
+
return out;
|
|
8116
|
+
}
|
|
8117
|
+
function goReceiverType(node) {
|
|
8118
|
+
const receiver = node.childForFieldName("receiver");
|
|
8119
|
+
if (!receiver) return void 0;
|
|
8120
|
+
for (let i = 0; i < receiver.namedChildCount; i++) {
|
|
8121
|
+
const param = receiver.namedChild(i);
|
|
8122
|
+
if (param?.type !== "parameter_declaration") continue;
|
|
8123
|
+
let typeNode = param.childForFieldName("type");
|
|
8124
|
+
if (typeNode?.type === "pointer_type") typeNode = typeNode.namedChild(0) ?? typeNode;
|
|
8125
|
+
if (typeNode?.type === "generic_type") {
|
|
8126
|
+
typeNode = typeNode.childForFieldName("type") ?? typeNode.namedChild(0) ?? typeNode;
|
|
8127
|
+
}
|
|
8128
|
+
if (typeNode?.type === "type_identifier") return typeNode.text;
|
|
8129
|
+
return typeNode?.text;
|
|
8130
|
+
}
|
|
8131
|
+
return void 0;
|
|
8132
|
+
}
|
|
8133
|
+
function collectGoSymbolDefs(root) {
|
|
8134
|
+
const out = [];
|
|
8135
|
+
const push = (kind, qualname, node) => {
|
|
8136
|
+
out.push({
|
|
8137
|
+
kind,
|
|
8138
|
+
qualname,
|
|
8139
|
+
startLine: node.startPosition.row + 1,
|
|
8140
|
+
endLine: node.endPosition.row + 1
|
|
8141
|
+
});
|
|
8142
|
+
};
|
|
8143
|
+
const visit = (node) => {
|
|
8144
|
+
switch (node.type) {
|
|
8145
|
+
case "function_declaration": {
|
|
8146
|
+
const name = node.childForFieldName("name")?.text;
|
|
8147
|
+
if (name) push("function", name, node);
|
|
8148
|
+
break;
|
|
8149
|
+
}
|
|
8150
|
+
case "method_declaration": {
|
|
8151
|
+
const name = node.childForFieldName("name")?.text;
|
|
8152
|
+
if (name) {
|
|
8153
|
+
const recv = goReceiverType(node);
|
|
8154
|
+
push("method", recv ? `${recv}.${name}` : name, node);
|
|
8155
|
+
}
|
|
8156
|
+
break;
|
|
8157
|
+
}
|
|
8158
|
+
}
|
|
8159
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
8160
|
+
const child = node.namedChild(i);
|
|
8161
|
+
if (child) visit(child);
|
|
8162
|
+
}
|
|
8163
|
+
};
|
|
8164
|
+
visit(root);
|
|
8165
|
+
return out;
|
|
8166
|
+
}
|
|
8167
|
+
function collectRubySymbolDefs(root) {
|
|
8168
|
+
const out = [];
|
|
8169
|
+
const push = (kind, qualname, node) => {
|
|
8170
|
+
out.push({
|
|
8171
|
+
kind,
|
|
8172
|
+
qualname,
|
|
8173
|
+
startLine: node.startPosition.row + 1,
|
|
8174
|
+
endLine: node.endPosition.row + 1
|
|
8175
|
+
});
|
|
8176
|
+
};
|
|
8177
|
+
const nameText = (node) => node.childForFieldName("name")?.text.replace(/::/g, ".");
|
|
8178
|
+
const walkBody = (node, ctx) => {
|
|
8179
|
+
const body = node.childForFieldName("body");
|
|
8180
|
+
if (!body) return;
|
|
8181
|
+
for (let i = 0; i < body.namedChildCount; i++) {
|
|
8182
|
+
const child = body.namedChild(i);
|
|
8183
|
+
if (child) visit(child, ctx);
|
|
8184
|
+
}
|
|
8185
|
+
};
|
|
8186
|
+
const visit = (node, classCtx) => {
|
|
8187
|
+
switch (node.type) {
|
|
8188
|
+
case "method":
|
|
8189
|
+
case "singleton_method": {
|
|
8190
|
+
const name = node.childForFieldName("name")?.text;
|
|
8191
|
+
if (name) {
|
|
8192
|
+
if (classCtx) {
|
|
8193
|
+
const kind = node.type === "method" && name === "initialize" ? "constructor" : "method";
|
|
8194
|
+
push(kind, `${classCtx}.${name}`, node);
|
|
8195
|
+
} else {
|
|
8196
|
+
push("function", name, node);
|
|
8197
|
+
}
|
|
8198
|
+
}
|
|
8199
|
+
walkBody(node, void 0);
|
|
8200
|
+
return;
|
|
8201
|
+
}
|
|
8202
|
+
case "class":
|
|
8203
|
+
case "module": {
|
|
8204
|
+
const name = nameText(node);
|
|
8205
|
+
if (name) push("class", classCtx ? `${classCtx}.${name}` : name, node);
|
|
8206
|
+
walkBody(node, name ? classCtx ? `${classCtx}.${name}` : name : classCtx);
|
|
8207
|
+
return;
|
|
8208
|
+
}
|
|
8209
|
+
}
|
|
8210
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
8211
|
+
const child = node.namedChild(i);
|
|
8212
|
+
if (child) visit(child, classCtx);
|
|
8213
|
+
}
|
|
8214
|
+
};
|
|
8215
|
+
visit(root, void 0);
|
|
8216
|
+
return out;
|
|
8217
|
+
}
|
|
8218
|
+
function collectPhpSymbolDefs(root) {
|
|
8219
|
+
const out = [];
|
|
8220
|
+
const push = (kind, qualname, node) => {
|
|
8221
|
+
out.push({
|
|
8222
|
+
kind,
|
|
8223
|
+
qualname,
|
|
8224
|
+
startLine: node.startPosition.row + 1,
|
|
8225
|
+
endLine: node.endPosition.row + 1
|
|
8226
|
+
});
|
|
8227
|
+
};
|
|
8228
|
+
const dot = (s) => s.replace(/\\/g, ".").replace(/::/g, ".").replace(/^\.+/, "");
|
|
8229
|
+
const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
|
|
8230
|
+
const walkChildren = (container, nsCtx, classCtx) => {
|
|
8231
|
+
let ns = nsCtx;
|
|
8232
|
+
for (let i = 0; i < container.namedChildCount; i++) {
|
|
8233
|
+
const child = container.namedChild(i);
|
|
8234
|
+
if (!child) continue;
|
|
8235
|
+
if (child.type === "namespace_definition" && !child.childForFieldName("body")) {
|
|
8236
|
+
const nameNode = child.childForFieldName("name");
|
|
8237
|
+
if (nameNode) ns = dot(nameNode.text);
|
|
8238
|
+
continue;
|
|
8239
|
+
}
|
|
8240
|
+
visit(child, ns, classCtx);
|
|
8241
|
+
}
|
|
8242
|
+
};
|
|
8243
|
+
const walkBody = (node, nsCtx, classCtx) => {
|
|
8244
|
+
const body = node.childForFieldName("body");
|
|
8245
|
+
if (body) walkChildren(body, nsCtx, classCtx);
|
|
8246
|
+
};
|
|
8247
|
+
const visit = (node, nsCtx, classCtx) => {
|
|
8248
|
+
switch (node.type) {
|
|
8249
|
+
case "function_definition": {
|
|
8250
|
+
const name = node.childForFieldName("name")?.text;
|
|
8251
|
+
if (name) push("function", join(nsCtx, name), node);
|
|
8252
|
+
walkBody(node, nsCtx, void 0);
|
|
8253
|
+
return;
|
|
8254
|
+
}
|
|
8255
|
+
case "class_declaration":
|
|
8256
|
+
case "trait_declaration":
|
|
8257
|
+
case "interface_declaration": {
|
|
8258
|
+
const name = node.childForFieldName("name")?.text;
|
|
8259
|
+
const full = name ? join(nsCtx, name) : classCtx;
|
|
8260
|
+
if (name) push("class", full, node);
|
|
8261
|
+
walkBody(node, nsCtx, full);
|
|
8262
|
+
return;
|
|
8263
|
+
}
|
|
8264
|
+
case "method_declaration": {
|
|
8265
|
+
const name = node.childForFieldName("name")?.text;
|
|
8266
|
+
if (name) {
|
|
8267
|
+
const kind = name === "__construct" ? "constructor" : "method";
|
|
8268
|
+
push(kind, join(classCtx ?? nsCtx, name), node);
|
|
8269
|
+
}
|
|
8270
|
+
return;
|
|
8271
|
+
}
|
|
8272
|
+
case "namespace_definition": {
|
|
8273
|
+
const nameNode = node.childForFieldName("name");
|
|
8274
|
+
const ns = nameNode ? dot(nameNode.text) : nsCtx;
|
|
8275
|
+
walkBody(node, ns, classCtx);
|
|
8276
|
+
return;
|
|
8277
|
+
}
|
|
8278
|
+
}
|
|
8279
|
+
walkChildren(node, nsCtx, classCtx);
|
|
8280
|
+
};
|
|
8281
|
+
walkChildren(root, void 0, void 0);
|
|
8282
|
+
return out;
|
|
8283
|
+
}
|
|
8284
|
+
function collectCsharpSymbolDefs(root) {
|
|
8285
|
+
const out = [];
|
|
8286
|
+
const push = (kind, qualname, node) => {
|
|
8287
|
+
out.push({
|
|
8288
|
+
kind,
|
|
8289
|
+
qualname,
|
|
8290
|
+
startLine: node.startPosition.row + 1,
|
|
8291
|
+
endLine: node.endPosition.row + 1
|
|
8292
|
+
});
|
|
8293
|
+
};
|
|
8294
|
+
const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
|
|
8295
|
+
const walkChildren = (container, nsCtx, classCtx) => {
|
|
8296
|
+
let ns = nsCtx;
|
|
8297
|
+
for (let i = 0; i < container.namedChildCount; i++) {
|
|
8298
|
+
const child = container.namedChild(i);
|
|
8299
|
+
if (!child) continue;
|
|
8300
|
+
if (child.type === "file_scoped_namespace_declaration") {
|
|
8301
|
+
const nameNode = child.childForFieldName("name");
|
|
8302
|
+
if (nameNode) ns = join(nsCtx, nameNode.text);
|
|
8303
|
+
continue;
|
|
8304
|
+
}
|
|
8305
|
+
visit(child, ns, classCtx);
|
|
8306
|
+
}
|
|
8307
|
+
};
|
|
8308
|
+
const walkBody = (node, nsCtx, classCtx) => {
|
|
8309
|
+
const body = node.childForFieldName("body");
|
|
8310
|
+
if (body) walkChildren(body, nsCtx, classCtx);
|
|
8311
|
+
};
|
|
8312
|
+
const visit = (node, nsCtx, classCtx) => {
|
|
8313
|
+
switch (node.type) {
|
|
8314
|
+
case "namespace_declaration": {
|
|
8315
|
+
const nameNode = node.childForFieldName("name");
|
|
8316
|
+
const ns = nameNode ? join(nsCtx, nameNode.text) : nsCtx;
|
|
8317
|
+
walkBody(node, ns, classCtx);
|
|
8318
|
+
return;
|
|
8319
|
+
}
|
|
8320
|
+
case "class_declaration":
|
|
8321
|
+
case "interface_declaration":
|
|
8322
|
+
case "struct_declaration":
|
|
8323
|
+
case "record_declaration": {
|
|
8324
|
+
const name = node.childForFieldName("name")?.text;
|
|
8325
|
+
const full = name ? join(classCtx ?? nsCtx, name) : classCtx;
|
|
8326
|
+
if (name) push("class", full, node);
|
|
8327
|
+
walkBody(node, nsCtx, full);
|
|
8328
|
+
return;
|
|
8329
|
+
}
|
|
8330
|
+
case "method_declaration": {
|
|
8331
|
+
const name = node.childForFieldName("name")?.text;
|
|
8332
|
+
if (name) push("method", join(classCtx ?? nsCtx, name), node);
|
|
8333
|
+
return;
|
|
8334
|
+
}
|
|
8335
|
+
case "constructor_declaration": {
|
|
8336
|
+
const name = node.childForFieldName("name")?.text;
|
|
8337
|
+
if (name) push("constructor", join(classCtx ?? nsCtx, name), node);
|
|
8338
|
+
return;
|
|
8339
|
+
}
|
|
8340
|
+
}
|
|
8341
|
+
walkChildren(node, nsCtx, classCtx);
|
|
8342
|
+
};
|
|
8343
|
+
walkChildren(root, void 0, void 0);
|
|
8344
|
+
return out;
|
|
8345
|
+
}
|
|
8346
|
+
function collectJavaSymbolDefs(root) {
|
|
8347
|
+
const out = [];
|
|
8348
|
+
const push = (kind, qualname, node) => {
|
|
8349
|
+
out.push({
|
|
8350
|
+
kind,
|
|
8351
|
+
qualname,
|
|
8352
|
+
startLine: node.startPosition.row + 1,
|
|
8353
|
+
endLine: node.endPosition.row + 1
|
|
8354
|
+
});
|
|
8355
|
+
};
|
|
8356
|
+
const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
|
|
8357
|
+
let pkg;
|
|
8358
|
+
for (let i = 0; i < root.namedChildCount; i++) {
|
|
8359
|
+
const child = root.namedChild(i);
|
|
8360
|
+
if (child?.type === "package_declaration") {
|
|
8361
|
+
pkg = child.namedChild(0)?.text;
|
|
8362
|
+
break;
|
|
8363
|
+
}
|
|
8364
|
+
}
|
|
8365
|
+
const walkChildren = (container, classCtx) => {
|
|
8366
|
+
for (let i = 0; i < container.namedChildCount; i++) {
|
|
8367
|
+
const child = container.namedChild(i);
|
|
8368
|
+
if (child) visit(child, classCtx);
|
|
8369
|
+
}
|
|
8370
|
+
};
|
|
8371
|
+
const walkBody = (node, classCtx) => {
|
|
8372
|
+
const body = node.childForFieldName("body");
|
|
8373
|
+
if (body) walkChildren(body, classCtx);
|
|
8374
|
+
};
|
|
8375
|
+
const visit = (node, classCtx) => {
|
|
8376
|
+
switch (node.type) {
|
|
8377
|
+
case "class_declaration":
|
|
8378
|
+
case "interface_declaration":
|
|
8379
|
+
case "enum_declaration":
|
|
8380
|
+
case "record_declaration": {
|
|
8381
|
+
const name = node.childForFieldName("name")?.text;
|
|
8382
|
+
const full = name ? join(classCtx ?? pkg, name) : classCtx;
|
|
8383
|
+
if (name) push("class", full, node);
|
|
8384
|
+
walkBody(node, full);
|
|
8385
|
+
return;
|
|
8386
|
+
}
|
|
8387
|
+
case "method_declaration": {
|
|
8388
|
+
const name = node.childForFieldName("name")?.text;
|
|
8389
|
+
if (name) push("method", join(classCtx ?? pkg, name), node);
|
|
8390
|
+
return;
|
|
8391
|
+
}
|
|
8392
|
+
case "constructor_declaration": {
|
|
8393
|
+
const name = node.childForFieldName("name")?.text;
|
|
8394
|
+
if (name) push("constructor", join(classCtx ?? pkg, name), node);
|
|
8395
|
+
return;
|
|
8396
|
+
}
|
|
8397
|
+
}
|
|
8398
|
+
walkChildren(node, classCtx);
|
|
7765
8399
|
};
|
|
7766
|
-
|
|
8400
|
+
walkChildren(root, void 0);
|
|
7767
8401
|
return out;
|
|
7768
8402
|
}
|
|
8403
|
+
function collectSymbolDefsForExt(ext, root) {
|
|
8404
|
+
switch (ext) {
|
|
8405
|
+
case ".py":
|
|
8406
|
+
return collectPythonSymbolDefs(root);
|
|
8407
|
+
case ".go":
|
|
8408
|
+
return collectGoSymbolDefs(root);
|
|
8409
|
+
case ".rb":
|
|
8410
|
+
return collectRubySymbolDefs(root);
|
|
8411
|
+
case ".php":
|
|
8412
|
+
return collectPhpSymbolDefs(root);
|
|
8413
|
+
case ".cs":
|
|
8414
|
+
return collectCsharpSymbolDefs(root);
|
|
8415
|
+
case ".java":
|
|
8416
|
+
return collectJavaSymbolDefs(root);
|
|
8417
|
+
default:
|
|
8418
|
+
return collectSymbolDefs(root);
|
|
8419
|
+
}
|
|
8420
|
+
}
|
|
7769
8421
|
function disambiguate(defs) {
|
|
7770
8422
|
const counts = /* @__PURE__ */ new Map();
|
|
7771
8423
|
for (const def of defs) counts.set(def.qualname, (counts.get(def.qualname) ?? 0) + 1);
|
|
@@ -7780,7 +8432,7 @@ function disambiguate(defs) {
|
|
|
7780
8432
|
async function addSymbols(graph, services) {
|
|
7781
8433
|
const parsers = /* @__PURE__ */ new Map();
|
|
7782
8434
|
const parserForExt5 = (ext) => {
|
|
7783
|
-
const grammar =
|
|
8435
|
+
const grammar = SYMBOL_GRAMMAR_BY_EXT[ext];
|
|
7784
8436
|
if (!grammar) return null;
|
|
7785
8437
|
let parser = parsers.get(ext);
|
|
7786
8438
|
if (!parser) {
|
|
@@ -7795,13 +8447,14 @@ async function addSymbols(graph, services) {
|
|
|
7795
8447
|
for (const service of services) {
|
|
7796
8448
|
const files = await loadSourceFiles(service.dir);
|
|
7797
8449
|
for (const file of files) {
|
|
7798
|
-
const
|
|
8450
|
+
const ext = import_node_path22.default.extname(file.path);
|
|
8451
|
+
const parser = parserForExt5(ext);
|
|
7799
8452
|
if (!parser) continue;
|
|
7800
|
-
const relPath = toPosix(
|
|
8453
|
+
const relPath = toPosix(import_node_path22.default.relative(service.dir, file.path));
|
|
7801
8454
|
let defs;
|
|
7802
8455
|
try {
|
|
7803
8456
|
const tree = parseSource3(parser, file.content);
|
|
7804
|
-
defs =
|
|
8457
|
+
defs = collectSymbolDefsForExt(ext, tree.rootNode);
|
|
7805
8458
|
} catch (err) {
|
|
7806
8459
|
recordExtractionError("symbol extraction", file.path, err);
|
|
7807
8460
|
continue;
|
|
@@ -7816,11 +8469,11 @@ async function addSymbols(graph, services) {
|
|
|
7816
8469
|
nodesAdded += fn;
|
|
7817
8470
|
edgesAdded += fe;
|
|
7818
8471
|
for (const { def, disambiguator } of disambiguate(defs)) {
|
|
7819
|
-
const sid = (0,
|
|
8472
|
+
const sid = (0, import_types18.symbolId)(service.pkg.name, relPath, def.qualname, disambiguator);
|
|
7820
8473
|
if (!graph.hasNode(sid)) {
|
|
7821
8474
|
const node = {
|
|
7822
8475
|
id: sid,
|
|
7823
|
-
type:
|
|
8476
|
+
type: import_types18.NodeType.SymbolNode,
|
|
7824
8477
|
kind: def.kind,
|
|
7825
8478
|
qualname: def.qualname,
|
|
7826
8479
|
span: { startLine: def.startLine, endLine: def.endLine },
|
|
@@ -7831,15 +8484,15 @@ async function addSymbols(graph, services) {
|
|
|
7831
8484
|
graph.addNode(sid, node);
|
|
7832
8485
|
nodesAdded++;
|
|
7833
8486
|
}
|
|
7834
|
-
const containsId = (0,
|
|
8487
|
+
const containsId = (0, import_types18.extractedEdgeId)(fileNodeId, sid, import_types18.EdgeType.CONTAINS);
|
|
7835
8488
|
if (!graph.hasEdge(containsId)) {
|
|
7836
8489
|
const edge = {
|
|
7837
8490
|
id: containsId,
|
|
7838
8491
|
source: fileNodeId,
|
|
7839
8492
|
target: sid,
|
|
7840
|
-
type:
|
|
7841
|
-
provenance:
|
|
7842
|
-
confidence: (0,
|
|
8493
|
+
type: import_types18.EdgeType.CONTAINS,
|
|
8494
|
+
provenance: import_types18.Provenance.EXTRACTED,
|
|
8495
|
+
confidence: (0, import_types18.confidenceForExtracted)("structural"),
|
|
7843
8496
|
evidence: {
|
|
7844
8497
|
file: relPath,
|
|
7845
8498
|
line: def.startLine,
|
|
@@ -7857,9 +8510,9 @@ async function addSymbols(graph, services) {
|
|
|
7857
8510
|
|
|
7858
8511
|
// src/extract/symbol-edges.ts
|
|
7859
8512
|
init_cjs_shims();
|
|
7860
|
-
var
|
|
8513
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
7861
8514
|
var import_tree_sitter4 = __toESM(require("tree-sitter"), 1);
|
|
7862
|
-
var
|
|
8515
|
+
var import_types19 = require("@neat.is/types");
|
|
7863
8516
|
function extendsInfo(classHeritage) {
|
|
7864
8517
|
for (let i = 0; i < classHeritage.namedChildCount; i++) {
|
|
7865
8518
|
const child = classHeritage.namedChild(i);
|
|
@@ -7964,10 +8617,10 @@ async function addSymbolEdges(graph, services) {
|
|
|
7964
8617
|
const tsPaths = await loadTsPathConfig(service.dir);
|
|
7965
8618
|
const files = await loadSourceFiles(service.dir);
|
|
7966
8619
|
for (const file of files) {
|
|
7967
|
-
const parser = parserForExt5(
|
|
8620
|
+
const parser = parserForExt5(import_node_path23.default.extname(file.path));
|
|
7968
8621
|
if (!parser) continue;
|
|
7969
|
-
const relPath = toPosix(
|
|
7970
|
-
const fileDir =
|
|
8622
|
+
const relPath = toPosix(import_node_path23.default.relative(service.dir, file.path));
|
|
8623
|
+
const fileDir = import_node_path23.default.dirname(file.path);
|
|
7971
8624
|
let root;
|
|
7972
8625
|
try {
|
|
7973
8626
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -7977,7 +8630,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
7977
8630
|
}
|
|
7978
8631
|
const disambiguated = disambiguate(collectSymbolDefs(root));
|
|
7979
8632
|
const locals = disambiguated.map(({ def, disambiguator }) => ({
|
|
7980
|
-
sid: (0,
|
|
8633
|
+
sid: (0, import_types19.symbolId)(serviceName, relPath, def.qualname, disambiguator),
|
|
7981
8634
|
qualname: def.qualname,
|
|
7982
8635
|
kind: def.kind,
|
|
7983
8636
|
startLine: def.startLine,
|
|
@@ -8006,10 +8659,10 @@ async function addSymbolEdges(graph, services) {
|
|
|
8006
8659
|
if (local) return local.kind === wantKind ? local.sid : null;
|
|
8007
8660
|
const imp = resolvedImports.get(name);
|
|
8008
8661
|
if (imp) {
|
|
8009
|
-
const candidate = (0,
|
|
8662
|
+
const candidate = (0, import_types19.symbolId)(serviceName, imp.targetRelPath, imp.importedName);
|
|
8010
8663
|
if (graph.hasNode(candidate)) {
|
|
8011
8664
|
const node = graph.getNodeAttributes(candidate);
|
|
8012
|
-
if (node.type ===
|
|
8665
|
+
if (node.type === import_types19.NodeType.SymbolNode && node.kind === wantKind) return candidate;
|
|
8013
8666
|
}
|
|
8014
8667
|
}
|
|
8015
8668
|
return null;
|
|
@@ -8036,7 +8689,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
8036
8689
|
sourceSid: self.sid,
|
|
8037
8690
|
targetName: ext.name,
|
|
8038
8691
|
wantKind: "class",
|
|
8039
|
-
edgeType:
|
|
8692
|
+
edgeType: import_types19.EdgeType.INHERITS,
|
|
8040
8693
|
line: ext.line
|
|
8041
8694
|
});
|
|
8042
8695
|
}
|
|
@@ -8045,7 +8698,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
8045
8698
|
sourceSid: self.sid,
|
|
8046
8699
|
targetName: impl.name,
|
|
8047
8700
|
wantKind: "class",
|
|
8048
|
-
edgeType:
|
|
8701
|
+
edgeType: import_types19.EdgeType.IMPLEMENTS,
|
|
8049
8702
|
line: impl.line
|
|
8050
8703
|
});
|
|
8051
8704
|
}
|
|
@@ -8061,7 +8714,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
8061
8714
|
sourceSid: caller.sid,
|
|
8062
8715
|
targetName: fn.text,
|
|
8063
8716
|
wantKind: "function",
|
|
8064
|
-
edgeType:
|
|
8717
|
+
edgeType: import_types19.EdgeType.CALLS,
|
|
8065
8718
|
line
|
|
8066
8719
|
});
|
|
8067
8720
|
}
|
|
@@ -8077,15 +8730,15 @@ async function addSymbolEdges(graph, services) {
|
|
|
8077
8730
|
const targetSid = resolveTarget(req.targetName, req.wantKind);
|
|
8078
8731
|
if (!targetSid) continue;
|
|
8079
8732
|
if (targetSid === req.sourceSid) continue;
|
|
8080
|
-
const edgeId = (0,
|
|
8733
|
+
const edgeId = (0, import_types19.extractedEdgeId)(req.sourceSid, targetSid, req.edgeType);
|
|
8081
8734
|
if (graph.hasEdge(edgeId)) continue;
|
|
8082
8735
|
const edge = {
|
|
8083
8736
|
id: edgeId,
|
|
8084
8737
|
source: req.sourceSid,
|
|
8085
8738
|
target: targetSid,
|
|
8086
8739
|
type: req.edgeType,
|
|
8087
|
-
provenance:
|
|
8088
|
-
confidence: (0,
|
|
8740
|
+
provenance: import_types19.Provenance.EXTRACTED,
|
|
8741
|
+
confidence: (0, import_types19.confidenceForExtracted)("structural"),
|
|
8089
8742
|
evidence: {
|
|
8090
8743
|
file: relPath,
|
|
8091
8744
|
line: req.line,
|
|
@@ -8102,9 +8755,9 @@ async function addSymbolEdges(graph, services) {
|
|
|
8102
8755
|
|
|
8103
8756
|
// src/extract/actions.ts
|
|
8104
8757
|
init_cjs_shims();
|
|
8105
|
-
var
|
|
8758
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
8106
8759
|
var import_tree_sitter5 = __toESM(require("tree-sitter"), 1);
|
|
8107
|
-
var
|
|
8760
|
+
var import_types20 = require("@neat.is/types");
|
|
8108
8761
|
function stringLiteralText2(node) {
|
|
8109
8762
|
for (let i = 0; i < node.childCount; i++) {
|
|
8110
8763
|
const child = node.child(i);
|
|
@@ -8249,9 +8902,9 @@ async function addServerActions(graph, services) {
|
|
|
8249
8902
|
const files = await loadSourceFiles(service.dir);
|
|
8250
8903
|
for (const file of files) {
|
|
8251
8904
|
if (isTestPath(file.path)) continue;
|
|
8252
|
-
const parser = parserForExt5(
|
|
8905
|
+
const parser = parserForExt5(import_node_path24.default.extname(file.path));
|
|
8253
8906
|
if (!parser) continue;
|
|
8254
|
-
const relPath = toPosix(
|
|
8907
|
+
const relPath = toPosix(import_node_path24.default.relative(service.dir, file.path));
|
|
8255
8908
|
let root;
|
|
8256
8909
|
try {
|
|
8257
8910
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -8274,11 +8927,11 @@ async function addServerActions(graph, services) {
|
|
|
8274
8927
|
nodesAdded += fn;
|
|
8275
8928
|
edgesAdded += fe;
|
|
8276
8929
|
for (const action of actions) {
|
|
8277
|
-
const aid = (0,
|
|
8930
|
+
const aid = (0, import_types20.serverActionId)(service.pkg.name, relPath, action.exportName);
|
|
8278
8931
|
if (!graph.hasNode(aid)) {
|
|
8279
8932
|
const node = {
|
|
8280
8933
|
id: aid,
|
|
8281
|
-
type:
|
|
8934
|
+
type: import_types20.NodeType.ServerActionNode,
|
|
8282
8935
|
name: action.exportName,
|
|
8283
8936
|
service: service.pkg.name,
|
|
8284
8937
|
module: relPath,
|
|
@@ -8290,15 +8943,15 @@ async function addServerActions(graph, services) {
|
|
|
8290
8943
|
graph.addNode(aid, node);
|
|
8291
8944
|
nodesAdded++;
|
|
8292
8945
|
}
|
|
8293
|
-
const containsId = (0,
|
|
8946
|
+
const containsId = (0, import_types20.extractedEdgeId)(fileNodeId, aid, import_types20.EdgeType.CONTAINS);
|
|
8294
8947
|
if (!graph.hasEdge(containsId)) {
|
|
8295
8948
|
const edge = {
|
|
8296
8949
|
id: containsId,
|
|
8297
8950
|
source: fileNodeId,
|
|
8298
8951
|
target: aid,
|
|
8299
|
-
type:
|
|
8300
|
-
provenance:
|
|
8301
|
-
confidence: (0,
|
|
8952
|
+
type: import_types20.EdgeType.CONTAINS,
|
|
8953
|
+
provenance: import_types20.Provenance.EXTRACTED,
|
|
8954
|
+
confidence: (0, import_types20.confidenceForExtracted)("structural"),
|
|
8302
8955
|
evidence: {
|
|
8303
8956
|
file: relPath,
|
|
8304
8957
|
line: action.line,
|
|
@@ -8312,10 +8965,10 @@ async function addServerActions(graph, services) {
|
|
|
8312
8965
|
}
|
|
8313
8966
|
for (const file of files) {
|
|
8314
8967
|
if (isTestPath(file.path)) continue;
|
|
8315
|
-
const parser = parserForExt5(
|
|
8968
|
+
const parser = parserForExt5(import_node_path24.default.extname(file.path));
|
|
8316
8969
|
if (!parser) continue;
|
|
8317
|
-
const relPath = toPosix(
|
|
8318
|
-
const fileDir =
|
|
8970
|
+
const relPath = toPosix(import_node_path24.default.relative(service.dir, file.path));
|
|
8971
|
+
const fileDir = import_node_path24.default.dirname(file.path);
|
|
8319
8972
|
let root;
|
|
8320
8973
|
try {
|
|
8321
8974
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -8328,7 +8981,7 @@ async function addServerActions(graph, services) {
|
|
|
8328
8981
|
for (const [local, binding] of bindings) {
|
|
8329
8982
|
const target = await resolveJsImport(binding.specifier, fileDir, service.dir, tsPaths);
|
|
8330
8983
|
if (!target) continue;
|
|
8331
|
-
const aid = (0,
|
|
8984
|
+
const aid = (0, import_types20.serverActionId)(service.pkg.name, target, binding.importedName);
|
|
8332
8985
|
if (graph.hasNode(aid)) actionBindings.set(local, aid);
|
|
8333
8986
|
}
|
|
8334
8987
|
if (actionBindings.size === 0) continue;
|
|
@@ -8343,15 +8996,15 @@ async function addServerActions(graph, services) {
|
|
|
8343
8996
|
nodesAdded += ensured.nodesAdded;
|
|
8344
8997
|
edgesAdded += ensured.edgesAdded;
|
|
8345
8998
|
}
|
|
8346
|
-
const callsId = (0,
|
|
8999
|
+
const callsId = (0, import_types20.extractedEdgeId)(clientFileId, aid, import_types20.EdgeType.CALLS);
|
|
8347
9000
|
if (graph.hasEdge(callsId)) continue;
|
|
8348
9001
|
const edge = {
|
|
8349
9002
|
id: callsId,
|
|
8350
9003
|
source: clientFileId,
|
|
8351
9004
|
target: aid,
|
|
8352
|
-
type:
|
|
8353
|
-
provenance:
|
|
8354
|
-
confidence: (0,
|
|
9005
|
+
type: import_types20.EdgeType.CALLS,
|
|
9006
|
+
provenance: import_types20.Provenance.EXTRACTED,
|
|
9007
|
+
confidence: (0, import_types20.confidenceForExtracted)("structural"),
|
|
8355
9008
|
evidence: {
|
|
8356
9009
|
file: relPath,
|
|
8357
9010
|
line,
|
|
@@ -8368,14 +9021,14 @@ async function addServerActions(graph, services) {
|
|
|
8368
9021
|
|
|
8369
9022
|
// src/extract/databases/index.ts
|
|
8370
9023
|
init_cjs_shims();
|
|
8371
|
-
var
|
|
8372
|
-
var
|
|
9024
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
9025
|
+
var import_types21 = require("@neat.is/types");
|
|
8373
9026
|
|
|
8374
9027
|
// src/extract/databases/db-config-yaml.ts
|
|
8375
9028
|
init_cjs_shims();
|
|
8376
|
-
var
|
|
9029
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
8377
9030
|
async function parse(serviceDir) {
|
|
8378
|
-
const yamlPath =
|
|
9031
|
+
const yamlPath = import_node_path25.default.join(serviceDir, "db-config.yaml");
|
|
8379
9032
|
if (!await exists2(yamlPath)) return [];
|
|
8380
9033
|
const raw = await readYaml(yamlPath);
|
|
8381
9034
|
return [
|
|
@@ -8393,13 +9046,13 @@ var dbConfigYamlParser = { name: "db-config.yaml", parse };
|
|
|
8393
9046
|
|
|
8394
9047
|
// src/extract/databases/dotenv.ts
|
|
8395
9048
|
init_cjs_shims();
|
|
8396
|
-
var
|
|
8397
|
-
var
|
|
9049
|
+
var import_node_fs20 = require("fs");
|
|
9050
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
8398
9051
|
|
|
8399
9052
|
// src/extract/databases/shared.ts
|
|
8400
9053
|
init_cjs_shims();
|
|
8401
|
-
var
|
|
8402
|
-
var
|
|
9054
|
+
var import_node_fs19 = require("fs");
|
|
9055
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
8403
9056
|
function schemeToEngine(scheme) {
|
|
8404
9057
|
const s = scheme.toLowerCase().split("+")[0];
|
|
8405
9058
|
switch (s) {
|
|
@@ -8438,18 +9091,18 @@ function parseConnectionString(url) {
|
|
|
8438
9091
|
}
|
|
8439
9092
|
async function readIfExists(filePath) {
|
|
8440
9093
|
try {
|
|
8441
|
-
return await
|
|
9094
|
+
return await import_node_fs19.promises.readFile(filePath, "utf8");
|
|
8442
9095
|
} catch {
|
|
8443
9096
|
return null;
|
|
8444
9097
|
}
|
|
8445
9098
|
}
|
|
8446
9099
|
async function resolveEnvVar(serviceDir, name) {
|
|
8447
|
-
const entries = await
|
|
9100
|
+
const entries = await import_node_fs19.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
8448
9101
|
const envNames = entries.filter((e) => e.isFile() && (e.name === ".env" || e.name.startsWith(".env."))).map((e) => e.name);
|
|
8449
9102
|
const rank = (n) => n === ".env.local" ? 0 : n === ".env" ? 1 : 2;
|
|
8450
9103
|
envNames.sort((a, b) => rank(a) - rank(b) || a.localeCompare(b));
|
|
8451
9104
|
for (const fileName of envNames) {
|
|
8452
|
-
const content = await readIfExists(
|
|
9105
|
+
const content = await readIfExists(import_node_path26.default.join(serviceDir, fileName));
|
|
8453
9106
|
if (!content) continue;
|
|
8454
9107
|
for (const line of content.split("\n")) {
|
|
8455
9108
|
const trimmed = line.trim();
|
|
@@ -8468,7 +9121,7 @@ async function resolveEnvVar(serviceDir, name) {
|
|
|
8468
9121
|
}
|
|
8469
9122
|
async function findFirst(serviceDir, candidates) {
|
|
8470
9123
|
for (const rel of candidates) {
|
|
8471
|
-
const abs =
|
|
9124
|
+
const abs = import_node_path26.default.join(serviceDir, rel);
|
|
8472
9125
|
const content = await readIfExists(abs);
|
|
8473
9126
|
if (content !== null) return abs;
|
|
8474
9127
|
}
|
|
@@ -8526,15 +9179,15 @@ function parseDotenvLine(line) {
|
|
|
8526
9179
|
return { key, value };
|
|
8527
9180
|
}
|
|
8528
9181
|
async function parse2(serviceDir) {
|
|
8529
|
-
const entries = await
|
|
9182
|
+
const entries = await import_node_fs20.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
8530
9183
|
const configs = [];
|
|
8531
9184
|
const seen = /* @__PURE__ */ new Set();
|
|
8532
9185
|
for (const entry of entries) {
|
|
8533
9186
|
if (!entry.isFile()) continue;
|
|
8534
9187
|
const match = isConfigFile(entry.name);
|
|
8535
9188
|
if (!match.match || match.fileType !== "env") continue;
|
|
8536
|
-
const filePath =
|
|
8537
|
-
const content = await
|
|
9189
|
+
const filePath = import_node_path27.default.join(serviceDir, entry.name);
|
|
9190
|
+
const content = await import_node_fs20.promises.readFile(filePath, "utf8");
|
|
8538
9191
|
for (const line of content.split("\n")) {
|
|
8539
9192
|
const parsed = parseDotenvLine(line);
|
|
8540
9193
|
if (!parsed) continue;
|
|
@@ -8553,9 +9206,9 @@ var dotenvParser = { name: ".env", parse: parse2 };
|
|
|
8553
9206
|
|
|
8554
9207
|
// src/extract/databases/prisma.ts
|
|
8555
9208
|
init_cjs_shims();
|
|
8556
|
-
var
|
|
9209
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
8557
9210
|
async function parse3(serviceDir) {
|
|
8558
|
-
const schemaPath =
|
|
9211
|
+
const schemaPath = import_node_path28.default.join(serviceDir, "prisma", "schema.prisma");
|
|
8559
9212
|
const content = await readIfExists(schemaPath);
|
|
8560
9213
|
if (!content) return [];
|
|
8561
9214
|
const block = content.match(/datasource\s+\w+\s*\{([^}]*)\}/s);
|
|
@@ -8713,10 +9366,10 @@ var knexParser = { name: "knex", parse: parse5 };
|
|
|
8713
9366
|
|
|
8714
9367
|
// src/extract/databases/ormconfig.ts
|
|
8715
9368
|
init_cjs_shims();
|
|
8716
|
-
var
|
|
9369
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
8717
9370
|
async function parse6(serviceDir) {
|
|
8718
9371
|
for (const candidate of ["ormconfig.json", "ormconfig.yaml", "ormconfig.yml"]) {
|
|
8719
|
-
const abs =
|
|
9372
|
+
const abs = import_node_path29.default.join(serviceDir, candidate);
|
|
8720
9373
|
if (!await exists2(abs)) continue;
|
|
8721
9374
|
const raw = candidate.endsWith(".json") ? await readJson(abs) : await readYaml(abs);
|
|
8722
9375
|
const entries = Array.isArray(raw) ? raw : [raw];
|
|
@@ -8776,9 +9429,9 @@ var typeormParser = { name: "typeorm", parse: parse7 };
|
|
|
8776
9429
|
|
|
8777
9430
|
// src/extract/databases/sequelize.ts
|
|
8778
9431
|
init_cjs_shims();
|
|
8779
|
-
var
|
|
9432
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
8780
9433
|
async function parse8(serviceDir) {
|
|
8781
|
-
const configPath =
|
|
9434
|
+
const configPath = import_node_path30.default.join(serviceDir, "config", "config.json");
|
|
8782
9435
|
if (!await exists2(configPath)) return [];
|
|
8783
9436
|
const raw = await readJson(configPath);
|
|
8784
9437
|
const out = [];
|
|
@@ -8805,7 +9458,7 @@ var sequelizeParser = { name: "sequelize", parse: parse8 };
|
|
|
8805
9458
|
|
|
8806
9459
|
// src/extract/databases/docker-compose.ts
|
|
8807
9460
|
init_cjs_shims();
|
|
8808
|
-
var
|
|
9461
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
8809
9462
|
function portFromService(svc) {
|
|
8810
9463
|
for (const raw of svc.ports ?? []) {
|
|
8811
9464
|
const str = String(raw);
|
|
@@ -8832,7 +9485,7 @@ function databaseFromEnv(svc) {
|
|
|
8832
9485
|
}
|
|
8833
9486
|
async function parse9(serviceDir) {
|
|
8834
9487
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
8835
|
-
const abs =
|
|
9488
|
+
const abs = import_node_path31.default.join(serviceDir, name);
|
|
8836
9489
|
if (!await exists2(abs)) continue;
|
|
8837
9490
|
const raw = await readYaml(abs);
|
|
8838
9491
|
if (!raw?.services) return [];
|
|
@@ -8873,8 +9526,8 @@ function compatibleDriversFor(engine) {
|
|
|
8873
9526
|
}
|
|
8874
9527
|
function toDatabaseNode(config) {
|
|
8875
9528
|
return {
|
|
8876
|
-
id: (0,
|
|
8877
|
-
type:
|
|
9529
|
+
id: (0, import_types21.databaseId)(config.host),
|
|
9530
|
+
type: import_types21.NodeType.DatabaseNode,
|
|
8878
9531
|
name: config.database || config.host,
|
|
8879
9532
|
engine: config.engine,
|
|
8880
9533
|
engineVersion: config.engineVersion,
|
|
@@ -9004,7 +9657,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
9004
9657
|
discoveredVia: mergedDiscoveredVia
|
|
9005
9658
|
});
|
|
9006
9659
|
}
|
|
9007
|
-
const relConfigFile = toPosix(
|
|
9660
|
+
const relConfigFile = toPosix(import_node_path32.default.relative(service.dir, config.sourceFile));
|
|
9008
9661
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
9009
9662
|
graph,
|
|
9010
9663
|
service.pkg.name,
|
|
@@ -9013,14 +9666,14 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
9013
9666
|
);
|
|
9014
9667
|
nodesAdded += fn;
|
|
9015
9668
|
edgesAdded += fe;
|
|
9016
|
-
const evidenceFile = toPosix(
|
|
9669
|
+
const evidenceFile = toPosix(import_node_path32.default.relative(scanPath, config.sourceFile));
|
|
9017
9670
|
const edge = {
|
|
9018
|
-
id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id,
|
|
9671
|
+
id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id, import_types21.EdgeType.CONNECTS_TO),
|
|
9019
9672
|
source: fileNodeId,
|
|
9020
9673
|
target: dbNode.id,
|
|
9021
|
-
type:
|
|
9022
|
-
provenance:
|
|
9023
|
-
confidence: (0,
|
|
9674
|
+
type: import_types21.EdgeType.CONNECTS_TO,
|
|
9675
|
+
provenance: import_types21.Provenance.EXTRACTED,
|
|
9676
|
+
confidence: (0, import_types21.confidenceForExtracted)("structural"),
|
|
9024
9677
|
evidence: { file: evidenceFile }
|
|
9025
9678
|
};
|
|
9026
9679
|
if (!graph.hasEdge(edge.id)) {
|
|
@@ -9031,26 +9684,26 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
9031
9684
|
if (allConfigs.length === 1) {
|
|
9032
9685
|
const primary = allConfigs[0];
|
|
9033
9686
|
service.node.dbConnectionTarget = primary.port ? `${primary.host}:${primary.port}` : primary.host;
|
|
9034
|
-
const relPath =
|
|
9035
|
-
const cfgId = (0,
|
|
9687
|
+
const relPath = import_node_path32.default.relative(scanPath, primary.sourceFile);
|
|
9688
|
+
const cfgId = (0, import_types21.configId)(relPath);
|
|
9036
9689
|
if (!graph.hasNode(cfgId)) {
|
|
9037
9690
|
const cfgNode = {
|
|
9038
9691
|
id: cfgId,
|
|
9039
|
-
type:
|
|
9040
|
-
name:
|
|
9692
|
+
type: import_types21.NodeType.ConfigNode,
|
|
9693
|
+
name: import_node_path32.default.basename(primary.sourceFile),
|
|
9041
9694
|
path: relPath,
|
|
9042
|
-
fileType: isConfigFile(
|
|
9695
|
+
fileType: isConfigFile(import_node_path32.default.basename(primary.sourceFile)).fileType || "config"
|
|
9043
9696
|
};
|
|
9044
9697
|
graph.addNode(cfgId, cfgNode);
|
|
9045
9698
|
nodesAdded++;
|
|
9046
9699
|
}
|
|
9047
9700
|
const cfgEdge = {
|
|
9048
|
-
id: (0, import_types3.extractedEdgeId)(service.node.id, cfgId,
|
|
9701
|
+
id: (0, import_types3.extractedEdgeId)(service.node.id, cfgId, import_types21.EdgeType.CONFIGURED_BY),
|
|
9049
9702
|
source: service.node.id,
|
|
9050
9703
|
target: cfgId,
|
|
9051
|
-
type:
|
|
9052
|
-
provenance:
|
|
9053
|
-
confidence: (0,
|
|
9704
|
+
type: import_types21.EdgeType.CONFIGURED_BY,
|
|
9705
|
+
provenance: import_types21.Provenance.EXTRACTED,
|
|
9706
|
+
confidence: (0, import_types21.confidenceForExtracted)("structural"),
|
|
9054
9707
|
evidence: { file: toPosix(relPath) }
|
|
9055
9708
|
};
|
|
9056
9709
|
if (!graph.hasEdge(cfgEdge.id)) {
|
|
@@ -9080,15 +9733,15 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
9080
9733
|
|
|
9081
9734
|
// src/extract/configs.ts
|
|
9082
9735
|
init_cjs_shims();
|
|
9083
|
-
var
|
|
9084
|
-
var
|
|
9085
|
-
var
|
|
9736
|
+
var import_node_fs21 = require("fs");
|
|
9737
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
9738
|
+
var import_types22 = require("@neat.is/types");
|
|
9086
9739
|
async function walkConfigFiles(dir) {
|
|
9087
9740
|
const out = [];
|
|
9088
9741
|
async function walk9(current) {
|
|
9089
|
-
const entries = await
|
|
9742
|
+
const entries = await import_node_fs21.promises.readdir(current, { withFileTypes: true });
|
|
9090
9743
|
for (const entry of entries) {
|
|
9091
|
-
const full =
|
|
9744
|
+
const full = import_node_path33.default.join(current, entry.name);
|
|
9092
9745
|
if (entry.isDirectory()) {
|
|
9093
9746
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
9094
9747
|
if (await isPythonVenvDir(full)) continue;
|
|
@@ -9107,19 +9760,19 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
9107
9760
|
for (const service of services) {
|
|
9108
9761
|
const configFiles = await walkConfigFiles(service.dir);
|
|
9109
9762
|
for (const file of configFiles) {
|
|
9110
|
-
const relPath =
|
|
9763
|
+
const relPath = import_node_path33.default.relative(scanPath, file);
|
|
9111
9764
|
const node = {
|
|
9112
|
-
id: (0,
|
|
9113
|
-
type:
|
|
9114
|
-
name:
|
|
9765
|
+
id: (0, import_types22.configId)(relPath),
|
|
9766
|
+
type: import_types22.NodeType.ConfigNode,
|
|
9767
|
+
name: import_node_path33.default.basename(file),
|
|
9115
9768
|
path: relPath,
|
|
9116
|
-
fileType: isConfigFile(
|
|
9769
|
+
fileType: isConfigFile(import_node_path33.default.basename(file)).fileType
|
|
9117
9770
|
};
|
|
9118
9771
|
if (!graph.hasNode(node.id)) {
|
|
9119
9772
|
graph.addNode(node.id, node);
|
|
9120
9773
|
nodesAdded++;
|
|
9121
9774
|
}
|
|
9122
|
-
const relToService = toPosix(
|
|
9775
|
+
const relToService = toPosix(import_node_path33.default.relative(service.dir, file));
|
|
9123
9776
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
9124
9777
|
graph,
|
|
9125
9778
|
service.pkg.name,
|
|
@@ -9129,13 +9782,13 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
9129
9782
|
nodesAdded += fn;
|
|
9130
9783
|
edgesAdded += fe;
|
|
9131
9784
|
const edge = {
|
|
9132
|
-
id: (0, import_types3.extractedEdgeId)(fileNodeId, node.id,
|
|
9785
|
+
id: (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types22.EdgeType.CONFIGURED_BY),
|
|
9133
9786
|
source: fileNodeId,
|
|
9134
9787
|
target: node.id,
|
|
9135
|
-
type:
|
|
9136
|
-
provenance:
|
|
9137
|
-
confidence: (0,
|
|
9138
|
-
evidence: { file: relPath.split(
|
|
9788
|
+
type: import_types22.EdgeType.CONFIGURED_BY,
|
|
9789
|
+
provenance: import_types22.Provenance.EXTRACTED,
|
|
9790
|
+
confidence: (0, import_types22.confidenceForExtracted)("structural"),
|
|
9791
|
+
evidence: { file: relPath.split(import_node_path33.default.sep).join("/") }
|
|
9139
9792
|
};
|
|
9140
9793
|
if (!graph.hasEdge(edge.id)) {
|
|
9141
9794
|
graph.addEdgeWithKey(edge.id, edge.source, edge.target, edge);
|
|
@@ -9148,9 +9801,9 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
9148
9801
|
|
|
9149
9802
|
// src/extract/proto.ts
|
|
9150
9803
|
init_cjs_shims();
|
|
9151
|
-
var
|
|
9152
|
-
var
|
|
9153
|
-
var
|
|
9804
|
+
var import_node_fs22 = require("fs");
|
|
9805
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
9806
|
+
var import_types23 = require("@neat.is/types");
|
|
9154
9807
|
var PROTO_EXTENSION = ".proto";
|
|
9155
9808
|
function packageOf(content) {
|
|
9156
9809
|
const m = content.match(/^\s*package\s+([A-Za-z_][A-Za-z0-9_.]*)\s*;/m);
|
|
@@ -9189,14 +9842,14 @@ function grpcMethodsFromProto(content, fqPackage) {
|
|
|
9189
9842
|
async function walkProtoFiles(dir) {
|
|
9190
9843
|
const out = [];
|
|
9191
9844
|
async function walk9(current) {
|
|
9192
|
-
const entries = await
|
|
9845
|
+
const entries = await import_node_fs22.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
9193
9846
|
for (const entry of entries) {
|
|
9194
|
-
const full =
|
|
9847
|
+
const full = import_node_path34.default.join(current, entry.name);
|
|
9195
9848
|
if (entry.isDirectory()) {
|
|
9196
9849
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
9197
9850
|
if (await isPythonVenvDir(full)) continue;
|
|
9198
9851
|
await walk9(full);
|
|
9199
|
-
} else if (entry.isFile() &&
|
|
9852
|
+
} else if (entry.isFile() && import_node_path34.default.extname(entry.name) === PROTO_EXTENSION) {
|
|
9200
9853
|
out.push(full);
|
|
9201
9854
|
}
|
|
9202
9855
|
}
|
|
@@ -9211,10 +9864,10 @@ async function addGrpcMethods(graph, services) {
|
|
|
9211
9864
|
const protoPaths = await walkProtoFiles(service.dir);
|
|
9212
9865
|
for (const protoPath of protoPaths) {
|
|
9213
9866
|
if (isTestPath(protoPath)) continue;
|
|
9214
|
-
const relFile = toPosix(
|
|
9867
|
+
const relFile = toPosix(import_node_path34.default.relative(service.dir, protoPath));
|
|
9215
9868
|
let content;
|
|
9216
9869
|
try {
|
|
9217
|
-
content = await
|
|
9870
|
+
content = await import_node_fs22.promises.readFile(protoPath, "utf8");
|
|
9218
9871
|
} catch (err) {
|
|
9219
9872
|
recordExtractionError("proto extraction", protoPath, err);
|
|
9220
9873
|
continue;
|
|
@@ -9228,11 +9881,11 @@ async function addGrpcMethods(graph, services) {
|
|
|
9228
9881
|
}
|
|
9229
9882
|
if (methods.length === 0) continue;
|
|
9230
9883
|
for (const method of methods) {
|
|
9231
|
-
const mid = (0,
|
|
9884
|
+
const mid = (0, import_types23.grpcMethodId)(method.rpcService, method.rpcMethod);
|
|
9232
9885
|
if (!graph.hasNode(mid)) {
|
|
9233
9886
|
const node = {
|
|
9234
9887
|
id: mid,
|
|
9235
|
-
type:
|
|
9888
|
+
type: import_types23.NodeType.GrpcMethodNode,
|
|
9236
9889
|
name: `${method.rpcService}/${method.rpcMethod}`,
|
|
9237
9890
|
rpcService: method.rpcService,
|
|
9238
9891
|
rpcMethod: method.rpcMethod,
|
|
@@ -9243,15 +9896,15 @@ async function addGrpcMethods(graph, services) {
|
|
|
9243
9896
|
graph.addNode(mid, node);
|
|
9244
9897
|
nodesAdded++;
|
|
9245
9898
|
}
|
|
9246
|
-
const containsId = (0,
|
|
9899
|
+
const containsId = (0, import_types23.extractedEdgeId)(service.node.id, mid, import_types23.EdgeType.CONTAINS);
|
|
9247
9900
|
if (!graph.hasEdge(containsId)) {
|
|
9248
9901
|
const edge = {
|
|
9249
9902
|
id: containsId,
|
|
9250
9903
|
source: service.node.id,
|
|
9251
9904
|
target: mid,
|
|
9252
|
-
type:
|
|
9253
|
-
provenance:
|
|
9254
|
-
confidence: (0,
|
|
9905
|
+
type: import_types23.EdgeType.CONTAINS,
|
|
9906
|
+
provenance: import_types23.Provenance.EXTRACTED,
|
|
9907
|
+
confidence: (0, import_types23.confidenceForExtracted)("structural"),
|
|
9255
9908
|
evidence: {
|
|
9256
9909
|
file: relFile,
|
|
9257
9910
|
line: method.line,
|
|
@@ -9269,16 +9922,16 @@ async function addGrpcMethods(graph, services) {
|
|
|
9269
9922
|
|
|
9270
9923
|
// src/extract/calls/index.ts
|
|
9271
9924
|
init_cjs_shims();
|
|
9272
|
-
var
|
|
9925
|
+
var import_types41 = require("@neat.is/types");
|
|
9273
9926
|
|
|
9274
9927
|
// src/extract/calls/http.ts
|
|
9275
9928
|
init_cjs_shims();
|
|
9276
|
-
var
|
|
9929
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
9277
9930
|
var import_tree_sitter6 = __toESM(require("tree-sitter"), 1);
|
|
9278
9931
|
var import_tree_sitter_javascript4 = __toESM(require("tree-sitter-javascript"), 1);
|
|
9279
9932
|
var import_tree_sitter_typescript2 = __toESM(require("tree-sitter-typescript"), 1);
|
|
9280
|
-
var
|
|
9281
|
-
var
|
|
9933
|
+
var import_tree_sitter_python4 = __toESM(require("tree-sitter-python"), 1);
|
|
9934
|
+
var import_types24 = require("@neat.is/types");
|
|
9282
9935
|
var STRING_LITERAL_NODE_TYPES = /* @__PURE__ */ new Set(["string_fragment", "string_content"]);
|
|
9283
9936
|
var JSX_EXTERNAL_LINK_TAGS = /* @__PURE__ */ new Set(["a", "Link", "NavLink", "ExternalLink", "Anchor"]);
|
|
9284
9937
|
function isInsideJsxExternalLink(node) {
|
|
@@ -9334,7 +9987,7 @@ var GRAMMAR_BY_EXT2 = {
|
|
|
9334
9987
|
".jsx": import_tree_sitter_javascript4.default,
|
|
9335
9988
|
".mjs": import_tree_sitter_javascript4.default,
|
|
9336
9989
|
".cjs": import_tree_sitter_javascript4.default,
|
|
9337
|
-
".py":
|
|
9990
|
+
".py": import_tree_sitter_python4.default
|
|
9338
9991
|
};
|
|
9339
9992
|
function parserForExt(ext, cache) {
|
|
9340
9993
|
const grammar = GRAMMAR_BY_EXT2[ext] ?? import_tree_sitter_javascript4.default;
|
|
@@ -9356,7 +10009,7 @@ async function addHttpCallEdges(graph, services) {
|
|
|
9356
10009
|
const seen = /* @__PURE__ */ new Set();
|
|
9357
10010
|
for (const file of files) {
|
|
9358
10011
|
if (isTestPath(file.path)) continue;
|
|
9359
|
-
const parser = parserForExt(
|
|
10012
|
+
const parser = parserForExt(import_node_path35.default.extname(file.path), parserCache);
|
|
9360
10013
|
let sites;
|
|
9361
10014
|
try {
|
|
9362
10015
|
sites = callsFromSource(file.content, parser, knownHosts);
|
|
@@ -9365,14 +10018,14 @@ async function addHttpCallEdges(graph, services) {
|
|
|
9365
10018
|
continue;
|
|
9366
10019
|
}
|
|
9367
10020
|
if (sites.length === 0) continue;
|
|
9368
|
-
const relFile = toPosix(
|
|
10021
|
+
const relFile = toPosix(import_node_path35.default.relative(service.dir, file.path));
|
|
9369
10022
|
for (const site of sites) {
|
|
9370
10023
|
const targetId = hostToNodeId.get(site.host);
|
|
9371
10024
|
if (!targetId || targetId === service.node.id) continue;
|
|
9372
10025
|
const dedupKey = `${relFile}|${targetId}`;
|
|
9373
10026
|
if (seen.has(dedupKey)) continue;
|
|
9374
10027
|
seen.add(dedupKey);
|
|
9375
|
-
const confidence = (0,
|
|
10028
|
+
const confidence = (0, import_types24.confidenceForExtracted)("url-literal-service-target");
|
|
9376
10029
|
const ev = {
|
|
9377
10030
|
file: relFile,
|
|
9378
10031
|
line: site.line,
|
|
@@ -9386,25 +10039,25 @@ async function addHttpCallEdges(graph, services) {
|
|
|
9386
10039
|
);
|
|
9387
10040
|
nodesAdded += n;
|
|
9388
10041
|
edgesAdded += e;
|
|
9389
|
-
if (!(0,
|
|
10042
|
+
if (!(0, import_types24.passesExtractedFloor)(confidence)) {
|
|
9390
10043
|
noteExtractedDropped({
|
|
9391
10044
|
source: fileNodeId,
|
|
9392
10045
|
target: targetId,
|
|
9393
|
-
type:
|
|
10046
|
+
type: import_types24.EdgeType.CALLS,
|
|
9394
10047
|
confidence,
|
|
9395
10048
|
confidenceKind: "url-literal-service-target",
|
|
9396
10049
|
evidence: ev
|
|
9397
10050
|
});
|
|
9398
10051
|
continue;
|
|
9399
10052
|
}
|
|
9400
|
-
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, targetId,
|
|
10053
|
+
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, targetId, import_types24.EdgeType.CALLS);
|
|
9401
10054
|
if (!graph.hasEdge(edgeId)) {
|
|
9402
10055
|
const edge = {
|
|
9403
10056
|
id: edgeId,
|
|
9404
10057
|
source: fileNodeId,
|
|
9405
10058
|
target: targetId,
|
|
9406
|
-
type:
|
|
9407
|
-
provenance:
|
|
10059
|
+
type: import_types24.EdgeType.CALLS,
|
|
10060
|
+
provenance: import_types24.Provenance.EXTRACTED,
|
|
9408
10061
|
confidence,
|
|
9409
10062
|
evidence: ev
|
|
9410
10063
|
};
|
|
@@ -9419,10 +10072,10 @@ async function addHttpCallEdges(graph, services) {
|
|
|
9419
10072
|
|
|
9420
10073
|
// src/extract/calls/route-match.ts
|
|
9421
10074
|
init_cjs_shims();
|
|
9422
|
-
var
|
|
10075
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
9423
10076
|
var import_tree_sitter7 = __toESM(require("tree-sitter"), 1);
|
|
9424
10077
|
var import_tree_sitter_javascript5 = __toESM(require("tree-sitter-javascript"), 1);
|
|
9425
|
-
var
|
|
10078
|
+
var import_types25 = require("@neat.is/types");
|
|
9426
10079
|
var PARSE_CHUNK5 = 16384;
|
|
9427
10080
|
function parseSource5(parser, source) {
|
|
9428
10081
|
return parser.parse(
|
|
@@ -9587,9 +10240,9 @@ function buildRouteIndex(graph) {
|
|
|
9587
10240
|
const index = /* @__PURE__ */ new Map();
|
|
9588
10241
|
graph.forEachNode((_id, attrs) => {
|
|
9589
10242
|
const node = attrs;
|
|
9590
|
-
if (node.type !==
|
|
10243
|
+
if (node.type !== import_types25.NodeType.RouteNode) return;
|
|
9591
10244
|
const route = attrs;
|
|
9592
|
-
const owner = (0,
|
|
10245
|
+
const owner = (0, import_types25.serviceId)(route.service);
|
|
9593
10246
|
const entry = {
|
|
9594
10247
|
method: route.method.toUpperCase(),
|
|
9595
10248
|
normalizedPath: normalizePathTemplate(route.pathTemplate),
|
|
@@ -9618,7 +10271,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
9618
10271
|
const seen = /* @__PURE__ */ new Set();
|
|
9619
10272
|
for (const file of files) {
|
|
9620
10273
|
if (isTestPath(file.path)) continue;
|
|
9621
|
-
if (!JS_CLIENT_EXTENSIONS.has(
|
|
10274
|
+
if (!JS_CLIENT_EXTENSIONS.has(import_node_path36.default.extname(file.path))) continue;
|
|
9622
10275
|
let sites;
|
|
9623
10276
|
try {
|
|
9624
10277
|
sites = clientCallSitesFromSource(file.content, jsParser, knownHosts);
|
|
@@ -9627,7 +10280,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
9627
10280
|
continue;
|
|
9628
10281
|
}
|
|
9629
10282
|
if (sites.length === 0) continue;
|
|
9630
|
-
const relFile = toPosix(
|
|
10283
|
+
const relFile = toPosix(import_node_path36.default.relative(service.dir, file.path));
|
|
9631
10284
|
for (const site of sites) {
|
|
9632
10285
|
const serverServiceId = hostToNodeId.get(site.host);
|
|
9633
10286
|
if (!serverServiceId || serverServiceId === service.node.id) continue;
|
|
@@ -9647,7 +10300,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
9647
10300
|
);
|
|
9648
10301
|
nodesAdded += n;
|
|
9649
10302
|
edgesAdded += e;
|
|
9650
|
-
const confidence = (0,
|
|
10303
|
+
const confidence = (0, import_types25.confidenceForExtracted)("verified-call-site");
|
|
9651
10304
|
const ev = {
|
|
9652
10305
|
file: relFile,
|
|
9653
10306
|
line: site.line,
|
|
@@ -9655,25 +10308,25 @@ async function addRouteCallEdges(graph, services) {
|
|
|
9655
10308
|
method: site.method ?? match.method,
|
|
9656
10309
|
pathTemplate: site.pathTemplate
|
|
9657
10310
|
};
|
|
9658
|
-
if (!(0,
|
|
10311
|
+
if (!(0, import_types25.passesExtractedFloor)(confidence)) {
|
|
9659
10312
|
noteExtractedDropped({
|
|
9660
10313
|
source: fileNodeId,
|
|
9661
10314
|
target: match.routeNodeId,
|
|
9662
|
-
type:
|
|
10315
|
+
type: import_types25.EdgeType.CALLS,
|
|
9663
10316
|
confidence,
|
|
9664
10317
|
confidenceKind: "verified-call-site",
|
|
9665
10318
|
evidence: ev
|
|
9666
10319
|
});
|
|
9667
10320
|
continue;
|
|
9668
10321
|
}
|
|
9669
|
-
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, match.routeNodeId,
|
|
10322
|
+
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, match.routeNodeId, import_types25.EdgeType.CALLS);
|
|
9670
10323
|
if (!graph.hasEdge(edgeId)) {
|
|
9671
10324
|
const edge = {
|
|
9672
10325
|
id: edgeId,
|
|
9673
10326
|
source: fileNodeId,
|
|
9674
10327
|
target: match.routeNodeId,
|
|
9675
|
-
type:
|
|
9676
|
-
provenance:
|
|
10328
|
+
type: import_types25.EdgeType.CALLS,
|
|
10329
|
+
provenance: import_types25.Provenance.EXTRACTED,
|
|
9677
10330
|
confidence,
|
|
9678
10331
|
evidence: ev
|
|
9679
10332
|
};
|
|
@@ -9688,8 +10341,8 @@ async function addRouteCallEdges(graph, services) {
|
|
|
9688
10341
|
|
|
9689
10342
|
// src/extract/calls/kafka.ts
|
|
9690
10343
|
init_cjs_shims();
|
|
9691
|
-
var
|
|
9692
|
-
var
|
|
10344
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
10345
|
+
var import_types26 = require("@neat.is/types");
|
|
9693
10346
|
var PRODUCER_TOPIC_RE = /(?:producer|kafkaProducer)[\s\S]{0,40}?\.send\s*\(\s*\{[\s\S]{0,200}?topic\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
9694
10347
|
var CONSUMER_TOPIC_RE = /(?:consumer|kafkaConsumer)[\s\S]{0,40}?\.(?:subscribe|run)\s*\(\s*\{[\s\S]{0,200}?topic[s]?\s*:\s*(?:\[\s*)?['"`]([^'"`]+)['"`]/g;
|
|
9695
10348
|
function findAll(re, text) {
|
|
@@ -9710,7 +10363,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
9710
10363
|
seen.add(key);
|
|
9711
10364
|
const line = lineOf(file.content, topic);
|
|
9712
10365
|
out.push({
|
|
9713
|
-
infraId: (0,
|
|
10366
|
+
infraId: (0, import_types26.infraId)("kafka-topic", topic),
|
|
9714
10367
|
name: topic,
|
|
9715
10368
|
kind: "kafka-topic",
|
|
9716
10369
|
edgeType,
|
|
@@ -9719,7 +10372,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
9719
10372
|
// tier (ADR-066).
|
|
9720
10373
|
confidenceKind: "verified-call-site",
|
|
9721
10374
|
evidence: {
|
|
9722
|
-
file:
|
|
10375
|
+
file: import_node_path37.default.relative(serviceDir, file.path),
|
|
9723
10376
|
line,
|
|
9724
10377
|
snippet: snippet(file.content, line)
|
|
9725
10378
|
}
|
|
@@ -9732,8 +10385,8 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
9732
10385
|
|
|
9733
10386
|
// src/extract/calls/redis.ts
|
|
9734
10387
|
init_cjs_shims();
|
|
9735
|
-
var
|
|
9736
|
-
var
|
|
10388
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
10389
|
+
var import_types27 = require("@neat.is/types");
|
|
9737
10390
|
var REDIS_URL_RE = /redis(?:s)?:\/\/(?:[^@'"`\s]+@)?([^:/'"`\s]+)(?::(\d+))?/g;
|
|
9738
10391
|
function redisEndpointsFromFile(file, serviceDir) {
|
|
9739
10392
|
const out = [];
|
|
@@ -9746,7 +10399,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
9746
10399
|
seen.add(host);
|
|
9747
10400
|
const line = lineOf(file.content, host);
|
|
9748
10401
|
out.push({
|
|
9749
|
-
infraId: (0,
|
|
10402
|
+
infraId: (0, import_types27.infraId)("redis", host),
|
|
9750
10403
|
name: host,
|
|
9751
10404
|
kind: "redis",
|
|
9752
10405
|
edgeType: "CALLS",
|
|
@@ -9755,7 +10408,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
9755
10408
|
// support tier (ADR-066).
|
|
9756
10409
|
confidenceKind: "url-with-structural-support",
|
|
9757
10410
|
evidence: {
|
|
9758
|
-
file:
|
|
10411
|
+
file: import_node_path38.default.relative(serviceDir, file.path),
|
|
9759
10412
|
line,
|
|
9760
10413
|
snippet: snippet(file.content, line)
|
|
9761
10414
|
}
|
|
@@ -9766,8 +10419,8 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
9766
10419
|
|
|
9767
10420
|
// src/extract/calls/aws.ts
|
|
9768
10421
|
init_cjs_shims();
|
|
9769
|
-
var
|
|
9770
|
-
var
|
|
10422
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
10423
|
+
var import_types28 = require("@neat.is/types");
|
|
9771
10424
|
var S3_BUCKET_RE = /Bucket\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
9772
10425
|
var DYNAMO_TABLE_RE = /TableName\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
9773
10426
|
function hasMarker(text, markers) {
|
|
@@ -9791,7 +10444,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
9791
10444
|
seen.add(key);
|
|
9792
10445
|
const line = lineOf(file.content, name);
|
|
9793
10446
|
out.push({
|
|
9794
|
-
infraId: (0,
|
|
10447
|
+
infraId: (0, import_types28.infraId)(kind, name),
|
|
9795
10448
|
name,
|
|
9796
10449
|
kind,
|
|
9797
10450
|
edgeType: "CALLS",
|
|
@@ -9800,7 +10453,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
9800
10453
|
// (ADR-066).
|
|
9801
10454
|
confidenceKind: "verified-call-site",
|
|
9802
10455
|
evidence: {
|
|
9803
|
-
file:
|
|
10456
|
+
file: import_node_path39.default.relative(serviceDir, file.path),
|
|
9804
10457
|
line,
|
|
9805
10458
|
snippet: snippet(file.content, line)
|
|
9806
10459
|
}
|
|
@@ -9825,8 +10478,8 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
9825
10478
|
|
|
9826
10479
|
// src/extract/calls/grpc.ts
|
|
9827
10480
|
init_cjs_shims();
|
|
9828
|
-
var
|
|
9829
|
-
var
|
|
10481
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
10482
|
+
var import_types29 = require("@neat.is/types");
|
|
9830
10483
|
var GRPC_CLIENT_RE = /new\s+([A-Z][A-Za-z0-9_]*)Client\s*\(\s*['"`]?([^,'"`)]+)?/g;
|
|
9831
10484
|
var AWS_SDK_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@aws-sdk\/client-([a-z0-9-]+)['"`]/g;
|
|
9832
10485
|
var GRPC_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@grpc\/grpc-js['"`]|_grpc_pb['"`]/;
|
|
@@ -9875,7 +10528,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
9875
10528
|
const { kind } = classified;
|
|
9876
10529
|
const line = lineOf(file.content, m[0]);
|
|
9877
10530
|
out.push({
|
|
9878
|
-
infraId: (0,
|
|
10531
|
+
infraId: (0, import_types29.infraId)(kind, name),
|
|
9879
10532
|
name,
|
|
9880
10533
|
kind,
|
|
9881
10534
|
edgeType: "CALLS",
|
|
@@ -9884,7 +10537,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
9884
10537
|
// tier (ADR-066).
|
|
9885
10538
|
confidenceKind: "verified-call-site",
|
|
9886
10539
|
evidence: {
|
|
9887
|
-
file:
|
|
10540
|
+
file: import_node_path40.default.relative(serviceDir, file.path),
|
|
9888
10541
|
line,
|
|
9889
10542
|
snippet: snippet(file.content, line)
|
|
9890
10543
|
}
|
|
@@ -9895,8 +10548,8 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
9895
10548
|
|
|
9896
10549
|
// src/extract/calls/supabase.ts
|
|
9897
10550
|
init_cjs_shims();
|
|
9898
|
-
var
|
|
9899
|
-
var
|
|
10551
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
10552
|
+
var import_types30 = require("@neat.is/types");
|
|
9900
10553
|
var SUPABASE_JS_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/supabase-js['"`]/;
|
|
9901
10554
|
var SUPABASE_SSR_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/ssr['"`]/;
|
|
9902
10555
|
var SUPABASE_CLIENT_RE = /\b(createClient|createServerClient|createBrowserClient)\s*\(\s*(?:['"`]([^'"`]*)['"`])?/g;
|
|
@@ -9944,7 +10597,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
9944
10597
|
seen.add(name);
|
|
9945
10598
|
const line = lineOf(file.content, m[0]);
|
|
9946
10599
|
out.push({
|
|
9947
|
-
infraId: (0,
|
|
10600
|
+
infraId: (0, import_types30.infraId)("supabase", name),
|
|
9948
10601
|
name,
|
|
9949
10602
|
kind: "supabase",
|
|
9950
10603
|
edgeType: "CALLS",
|
|
@@ -9954,7 +10607,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
9954
10607
|
// tier (ADR-066), the same grade aws.ts / grpc.ts emit at.
|
|
9955
10608
|
confidenceKind: "verified-call-site",
|
|
9956
10609
|
evidence: {
|
|
9957
|
-
file:
|
|
10610
|
+
file: import_node_path41.default.relative(serviceDir, file.path),
|
|
9958
10611
|
line,
|
|
9959
10612
|
snippet: snippet(file.content, line)
|
|
9960
10613
|
}
|
|
@@ -9975,13 +10628,13 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
9975
10628
|
seen.add(key);
|
|
9976
10629
|
const line = lineOf(file.content, am[0]);
|
|
9977
10630
|
out.push({
|
|
9978
|
-
infraId: (0,
|
|
10631
|
+
infraId: (0, import_types30.infraId)(kind, resource),
|
|
9979
10632
|
name: resource,
|
|
9980
10633
|
kind,
|
|
9981
10634
|
edgeType: "CALLS",
|
|
9982
10635
|
confidenceKind: "verified-call-site",
|
|
9983
10636
|
evidence: {
|
|
9984
|
-
file:
|
|
10637
|
+
file: import_node_path41.default.relative(serviceDir, file.path),
|
|
9985
10638
|
line,
|
|
9986
10639
|
snippet: snippet(file.content, line)
|
|
9987
10640
|
}
|
|
@@ -9993,10 +10646,10 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
9993
10646
|
|
|
9994
10647
|
// src/extract/calls/firestore.ts
|
|
9995
10648
|
init_cjs_shims();
|
|
9996
|
-
var
|
|
10649
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
9997
10650
|
var import_tree_sitter8 = __toESM(require("tree-sitter"), 1);
|
|
9998
10651
|
var import_tree_sitter_javascript6 = __toESM(require("tree-sitter-javascript"), 1);
|
|
9999
|
-
var
|
|
10652
|
+
var import_types31 = require("@neat.is/types");
|
|
10000
10653
|
var FIRESTORE_CLIENT_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase\/firestore['"`]/;
|
|
10001
10654
|
var FIRESTORE_ADMIN_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase-admin(?:\/firestore)?['"`]/;
|
|
10002
10655
|
function parserForExt2(ext) {
|
|
@@ -10164,7 +10817,7 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
10164
10817
|
const hasAdmin = FIRESTORE_ADMIN_IMPORT_RE.test(file.content);
|
|
10165
10818
|
if (!hasClient && !hasAdmin) return [];
|
|
10166
10819
|
const fileSdk = hasClient && !hasAdmin ? "client" : hasAdmin && !hasClient ? "admin" : null;
|
|
10167
|
-
const tree = parseSource3(parserForExt2(
|
|
10820
|
+
const tree = parseSource3(parserForExt2(import_node_path42.default.extname(file.path)), file.content);
|
|
10168
10821
|
const clientVars = firestoreClientVars(tree.rootNode);
|
|
10169
10822
|
const collLine = /* @__PURE__ */ new Map();
|
|
10170
10823
|
const writes = /* @__PURE__ */ new Map();
|
|
@@ -10257,7 +10910,7 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
10257
10910
|
}
|
|
10258
10911
|
}
|
|
10259
10912
|
out.push({
|
|
10260
|
-
infraId: (0,
|
|
10913
|
+
infraId: (0, import_types31.infraId)("firestore-collection", collPath),
|
|
10261
10914
|
name: collPath,
|
|
10262
10915
|
kind: "firestore-collection",
|
|
10263
10916
|
edgeType: "CALLS",
|
|
@@ -10268,7 +10921,7 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
10268
10921
|
...columnSet.size > 0 ? { columns: [...columnSet] } : {},
|
|
10269
10922
|
...sdkWrites ? { sdkWrites } : {},
|
|
10270
10923
|
evidence: {
|
|
10271
|
-
file:
|
|
10924
|
+
file: import_node_path42.default.relative(serviceDir, file.path),
|
|
10272
10925
|
line,
|
|
10273
10926
|
snippet: snippet(file.content, line)
|
|
10274
10927
|
}
|
|
@@ -10279,8 +10932,8 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
10279
10932
|
|
|
10280
10933
|
// src/extract/calls/mongoose.ts
|
|
10281
10934
|
init_cjs_shims();
|
|
10282
|
-
var
|
|
10283
|
-
var
|
|
10935
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
10936
|
+
var import_types32 = require("@neat.is/types");
|
|
10284
10937
|
var MONGOOSE_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongoose['"`]/;
|
|
10285
10938
|
var MONGODB_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongodb['"`]/;
|
|
10286
10939
|
var PLURALIZE_DISABLED_RE = /\bpluralize\s*\(\s*(?:null|false)\s*\)/;
|
|
@@ -10425,12 +11078,12 @@ function collectModelDefs(content, pluralizeOn) {
|
|
|
10425
11078
|
function endpoint(r, file, serviceDir, matchText) {
|
|
10426
11079
|
const line = lineOf(file.content, matchText);
|
|
10427
11080
|
return {
|
|
10428
|
-
infraId: (0,
|
|
11081
|
+
infraId: (0, import_types32.infraId)(r.kind, r.name),
|
|
10429
11082
|
name: r.name,
|
|
10430
11083
|
kind: r.kind,
|
|
10431
11084
|
edgeType: "CALLS",
|
|
10432
11085
|
confidenceKind: "verified-call-site",
|
|
10433
|
-
evidence: { file:
|
|
11086
|
+
evidence: { file: import_node_path43.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
10434
11087
|
};
|
|
10435
11088
|
}
|
|
10436
11089
|
function mongooseEndpointsFromFile(file, serviceDir) {
|
|
@@ -10520,7 +11173,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
10520
11173
|
const registry = /* @__PURE__ */ new Map();
|
|
10521
11174
|
for (const f of mongooseFiles) {
|
|
10522
11175
|
const fx = fileExportsOf(f.content, pluralizeOn);
|
|
10523
|
-
if (fx) registry.set(toPosix(
|
|
11176
|
+
if (fx) registry.set(toPosix(import_node_path43.default.relative(serviceDir, f.path)), fx);
|
|
10524
11177
|
}
|
|
10525
11178
|
if (registry.size === 0) return [];
|
|
10526
11179
|
const out = [];
|
|
@@ -10531,7 +11184,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
10531
11184
|
const directColl = /* @__PURE__ */ new Map();
|
|
10532
11185
|
const nsExports = /* @__PURE__ */ new Map();
|
|
10533
11186
|
for (const b of bindings) {
|
|
10534
|
-
const resolvedRel = await resolveJsImport(b.specifier,
|
|
11187
|
+
const resolvedRel = await resolveJsImport(b.specifier, import_node_path43.default.dirname(f.path), serviceDir, null);
|
|
10535
11188
|
if (!resolvedRel) continue;
|
|
10536
11189
|
const fx = registry.get(resolvedRel);
|
|
10537
11190
|
if (!fx) continue;
|
|
@@ -10575,15 +11228,15 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
10575
11228
|
|
|
10576
11229
|
// src/extract/calls/sqlalchemy.ts
|
|
10577
11230
|
init_cjs_shims();
|
|
10578
|
-
var
|
|
11231
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
10579
11232
|
var import_tree_sitter9 = __toESM(require("tree-sitter"), 1);
|
|
10580
|
-
var
|
|
10581
|
-
var
|
|
11233
|
+
var import_tree_sitter_python5 = __toESM(require("tree-sitter-python"), 1);
|
|
11234
|
+
var import_types33 = require("@neat.is/types");
|
|
10582
11235
|
var SQLALCHEMY_IMPORT_RE = /(?:from|import)\s+(?:flask_sqlalchemy|sqlalchemy)\b/;
|
|
10583
11236
|
var PARSE_CHUNK6 = 16384;
|
|
10584
11237
|
function makePyParser3() {
|
|
10585
11238
|
const p = new import_tree_sitter9.default();
|
|
10586
|
-
p.setLanguage(
|
|
11239
|
+
p.setLanguage(import_tree_sitter_python5.default);
|
|
10587
11240
|
return p;
|
|
10588
11241
|
}
|
|
10589
11242
|
function parseSource6(parser, source) {
|
|
@@ -10714,7 +11367,7 @@ function sqlalchemyForeignKeys(file, serviceDir) {
|
|
|
10714
11367
|
childTable,
|
|
10715
11368
|
parentTable,
|
|
10716
11369
|
evidence: {
|
|
10717
|
-
file:
|
|
11370
|
+
file: import_node_path44.default.relative(serviceDir, file.path),
|
|
10718
11371
|
line,
|
|
10719
11372
|
snippet: snippet(file.content, line)
|
|
10720
11373
|
}
|
|
@@ -10732,14 +11385,14 @@ function sqlalchemyEndpointsFromFile(file, serviceDir) {
|
|
|
10732
11385
|
if (seen.has(name)) return;
|
|
10733
11386
|
seen.add(name);
|
|
10734
11387
|
out.push({
|
|
10735
|
-
infraId: (0,
|
|
11388
|
+
infraId: (0, import_types33.infraId)("sql-table", name),
|
|
10736
11389
|
name,
|
|
10737
11390
|
kind: "sql-table",
|
|
10738
11391
|
edgeType: "CALLS",
|
|
10739
11392
|
confidenceKind: "verified-call-site",
|
|
10740
11393
|
...columns && columns.length > 0 ? { columns } : {},
|
|
10741
11394
|
evidence: {
|
|
10742
|
-
file:
|
|
11395
|
+
file: import_node_path44.default.relative(serviceDir, file.path),
|
|
10743
11396
|
line,
|
|
10744
11397
|
snippet: snippet(file.content, line)
|
|
10745
11398
|
}
|
|
@@ -10840,13 +11493,13 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
|
|
|
10840
11493
|
if (seen.has(key)) continue;
|
|
10841
11494
|
seen.add(key);
|
|
10842
11495
|
out.push({
|
|
10843
|
-
infraId: (0,
|
|
11496
|
+
infraId: (0, import_types33.infraId)("sql-table", t),
|
|
10844
11497
|
name: t,
|
|
10845
11498
|
kind: "sql-table",
|
|
10846
11499
|
edgeType: "CALLS",
|
|
10847
11500
|
confidenceKind: "verified-call-site",
|
|
10848
11501
|
evidence: {
|
|
10849
|
-
file:
|
|
11502
|
+
file: import_node_path44.default.relative(serviceDir, file.path),
|
|
10850
11503
|
line,
|
|
10851
11504
|
snippet: snippet(file.content, line)
|
|
10852
11505
|
}
|
|
@@ -10858,15 +11511,15 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
|
|
|
10858
11511
|
|
|
10859
11512
|
// src/extract/calls/django-orm.ts
|
|
10860
11513
|
init_cjs_shims();
|
|
10861
|
-
var
|
|
11514
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
10862
11515
|
var import_tree_sitter10 = __toESM(require("tree-sitter"), 1);
|
|
10863
|
-
var
|
|
10864
|
-
var
|
|
11516
|
+
var import_tree_sitter_python6 = __toESM(require("tree-sitter-python"), 1);
|
|
11517
|
+
var import_types34 = require("@neat.is/types");
|
|
10865
11518
|
var DJANGO_IMPORT_RE = /(?:from|import)\s+django\b/;
|
|
10866
11519
|
var PARSE_CHUNK7 = 16384;
|
|
10867
11520
|
function makePyParser4() {
|
|
10868
11521
|
const p = new import_tree_sitter10.default();
|
|
10869
|
-
p.setLanguage(
|
|
11522
|
+
p.setLanguage(import_tree_sitter_python6.default);
|
|
10870
11523
|
return p;
|
|
10871
11524
|
}
|
|
10872
11525
|
function parseSource7(parser, source) {
|
|
@@ -10928,7 +11581,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
10928
11581
|
const tree = parseSource7(makePyParser4(), file.content);
|
|
10929
11582
|
const out = [];
|
|
10930
11583
|
const seen = /* @__PURE__ */ new Set();
|
|
10931
|
-
const defaultAppLabel =
|
|
11584
|
+
const defaultAppLabel = import_node_path45.default.basename(import_node_path45.default.dirname(file.path));
|
|
10932
11585
|
walk4(tree.rootNode, (node) => {
|
|
10933
11586
|
if (node.type !== "class_definition") return;
|
|
10934
11587
|
if (!extendsDjangoModel(node)) return;
|
|
@@ -10941,12 +11594,12 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
10941
11594
|
seen.add(table);
|
|
10942
11595
|
const line = node.startPosition.row + 1;
|
|
10943
11596
|
out.push({
|
|
10944
|
-
infraId: (0,
|
|
11597
|
+
infraId: (0, import_types34.infraId)("sql-table", table),
|
|
10945
11598
|
name: table,
|
|
10946
11599
|
kind: "sql-table",
|
|
10947
11600
|
edgeType: "CALLS",
|
|
10948
11601
|
confidenceKind: "verified-call-site",
|
|
10949
|
-
evidence: { file:
|
|
11602
|
+
evidence: { file: import_node_path45.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
10950
11603
|
});
|
|
10951
11604
|
});
|
|
10952
11605
|
return out;
|
|
@@ -10954,10 +11607,10 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
10954
11607
|
|
|
10955
11608
|
// src/extract/calls/drizzle.ts
|
|
10956
11609
|
init_cjs_shims();
|
|
10957
|
-
var
|
|
11610
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
10958
11611
|
var import_tree_sitter11 = __toESM(require("tree-sitter"), 1);
|
|
10959
11612
|
var import_tree_sitter_javascript7 = __toESM(require("tree-sitter-javascript"), 1);
|
|
10960
|
-
var
|
|
11613
|
+
var import_types35 = require("@neat.is/types");
|
|
10961
11614
|
var DRIZZLE_IMPORT_RE = /drizzle-orm/;
|
|
10962
11615
|
var TABLE_BUILDERS = /* @__PURE__ */ new Set(["pgTable", "mysqlTable", "sqliteTable"]);
|
|
10963
11616
|
function parserForExt3(ext) {
|
|
@@ -11032,7 +11685,7 @@ function columnsFromObject(obj) {
|
|
|
11032
11685
|
}
|
|
11033
11686
|
function drizzleEndpointsFromFile(file, serviceDir) {
|
|
11034
11687
|
if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
|
|
11035
|
-
const tree = parseSource3(parserForExt3(
|
|
11688
|
+
const tree = parseSource3(parserForExt3(import_node_path46.default.extname(file.path)), file.content);
|
|
11036
11689
|
const out = [];
|
|
11037
11690
|
const seen = /* @__PURE__ */ new Set();
|
|
11038
11691
|
const walk9 = (node) => {
|
|
@@ -11048,14 +11701,14 @@ function drizzleEndpointsFromFile(file, serviceDir) {
|
|
|
11048
11701
|
const columns = columnsFromObject(obj);
|
|
11049
11702
|
const line = node.startPosition.row + 1;
|
|
11050
11703
|
out.push({
|
|
11051
|
-
infraId: (0,
|
|
11704
|
+
infraId: (0, import_types35.infraId)("sql-table", tableName),
|
|
11052
11705
|
name: tableName,
|
|
11053
11706
|
kind: "sql-table",
|
|
11054
11707
|
edgeType: "CALLS",
|
|
11055
11708
|
confidenceKind: "structural",
|
|
11056
11709
|
columns,
|
|
11057
11710
|
evidence: {
|
|
11058
|
-
file:
|
|
11711
|
+
file: import_node_path46.default.relative(serviceDir, file.path),
|
|
11059
11712
|
line,
|
|
11060
11713
|
snippet: snippet(file.content, line)
|
|
11061
11714
|
}
|
|
@@ -11121,7 +11774,7 @@ function referencesTargetVar(call) {
|
|
|
11121
11774
|
}
|
|
11122
11775
|
function drizzleForeignKeys(file, serviceDir) {
|
|
11123
11776
|
if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
|
|
11124
|
-
const tree = parseSource3(parserForExt3(
|
|
11777
|
+
const tree = parseSource3(parserForExt3(import_node_path46.default.extname(file.path)), file.content);
|
|
11125
11778
|
const { tables, varToTable } = collectDrizzleTables(tree.rootNode);
|
|
11126
11779
|
const out = [];
|
|
11127
11780
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -11140,7 +11793,7 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
11140
11793
|
childTable: table.tableName,
|
|
11141
11794
|
parentTable,
|
|
11142
11795
|
evidence: {
|
|
11143
|
-
file:
|
|
11796
|
+
file: import_node_path46.default.relative(serviceDir, file.path),
|
|
11144
11797
|
line,
|
|
11145
11798
|
snippet: snippet(file.content, line)
|
|
11146
11799
|
}
|
|
@@ -11157,8 +11810,8 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
11157
11810
|
|
|
11158
11811
|
// src/extract/calls/prisma.ts
|
|
11159
11812
|
init_cjs_shims();
|
|
11160
|
-
var
|
|
11161
|
-
var
|
|
11813
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
11814
|
+
var import_types36 = require("@neat.is/types");
|
|
11162
11815
|
var SCALAR_TYPES = /* @__PURE__ */ new Set([
|
|
11163
11816
|
"Int",
|
|
11164
11817
|
"String",
|
|
@@ -11206,14 +11859,14 @@ function prismaColumnsFromSchema(file, serviceDir) {
|
|
|
11206
11859
|
if (seenTable.has(b.tableName)) return;
|
|
11207
11860
|
seenTable.add(b.tableName);
|
|
11208
11861
|
out.push({
|
|
11209
|
-
infraId: (0,
|
|
11862
|
+
infraId: (0, import_types36.infraId)("sql-table", b.tableName),
|
|
11210
11863
|
name: b.tableName,
|
|
11211
11864
|
kind: "sql-table",
|
|
11212
11865
|
edgeType: "CALLS",
|
|
11213
11866
|
confidenceKind: "structural",
|
|
11214
11867
|
columns: b.columns,
|
|
11215
11868
|
evidence: {
|
|
11216
|
-
file:
|
|
11869
|
+
file: import_node_path47.default.relative(serviceDir, file.path),
|
|
11217
11870
|
line: b.startLine,
|
|
11218
11871
|
snippet: snippet(content, b.startLine)
|
|
11219
11872
|
}
|
|
@@ -11274,7 +11927,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
|
|
|
11274
11927
|
}
|
|
11275
11928
|
async function prismaColumnEndpoints(serviceDir) {
|
|
11276
11929
|
const schemaPath = await findFirst(serviceDir, [
|
|
11277
|
-
|
|
11930
|
+
import_node_path47.default.join("prisma", "schema.prisma"),
|
|
11278
11931
|
"schema.prisma"
|
|
11279
11932
|
]);
|
|
11280
11933
|
if (!schemaPath) return [];
|
|
@@ -11349,7 +12002,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
|
|
|
11349
12002
|
childTable: current.table,
|
|
11350
12003
|
parentTable,
|
|
11351
12004
|
evidence: {
|
|
11352
|
-
file:
|
|
12005
|
+
file: import_node_path47.default.relative(serviceDir, file.path),
|
|
11353
12006
|
line: lineNo,
|
|
11354
12007
|
snippet: snippet(content, lineNo)
|
|
11355
12008
|
}
|
|
@@ -11364,7 +12017,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
|
|
|
11364
12017
|
}
|
|
11365
12018
|
async function prismaForeignKeys(serviceDir) {
|
|
11366
12019
|
const schemaPath = await findFirst(serviceDir, [
|
|
11367
|
-
|
|
12020
|
+
import_node_path47.default.join("prisma", "schema.prisma"),
|
|
11368
12021
|
"schema.prisma"
|
|
11369
12022
|
]);
|
|
11370
12023
|
if (!schemaPath) return [];
|
|
@@ -11375,15 +12028,15 @@ async function prismaForeignKeys(serviceDir) {
|
|
|
11375
12028
|
|
|
11376
12029
|
// src/extract/calls/activerecord.ts
|
|
11377
12030
|
init_cjs_shims();
|
|
11378
|
-
var
|
|
12031
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
11379
12032
|
var import_tree_sitter12 = __toESM(require("tree-sitter"), 1);
|
|
11380
|
-
var
|
|
11381
|
-
var
|
|
12033
|
+
var import_tree_sitter_ruby3 = __toESM(require("tree-sitter-ruby"), 1);
|
|
12034
|
+
var import_types37 = require("@neat.is/types");
|
|
11382
12035
|
var AR_SCHEMA_RE = /ActiveRecord::Schema/;
|
|
11383
12036
|
var PARSE_CHUNK8 = 16384;
|
|
11384
12037
|
function makeRubyParser2() {
|
|
11385
12038
|
const p = new import_tree_sitter12.default();
|
|
11386
|
-
p.setLanguage(
|
|
12039
|
+
p.setLanguage(import_tree_sitter_ruby3.default);
|
|
11387
12040
|
return p;
|
|
11388
12041
|
}
|
|
11389
12042
|
function parseSource8(parser, source) {
|
|
@@ -11576,14 +12229,14 @@ function railsSchemaEndpointsFromFile(file, serviceDir) {
|
|
|
11576
12229
|
if (!table || seen.has(table.name)) return;
|
|
11577
12230
|
seen.add(table.name);
|
|
11578
12231
|
out.push({
|
|
11579
|
-
infraId: (0,
|
|
12232
|
+
infraId: (0, import_types37.infraId)("sql-table", table.name),
|
|
11580
12233
|
name: table.name,
|
|
11581
12234
|
kind: "sql-table",
|
|
11582
12235
|
edgeType: "CALLS",
|
|
11583
12236
|
confidenceKind: "structural",
|
|
11584
12237
|
...table.columns.length > 0 ? { columns: table.columns } : {},
|
|
11585
12238
|
evidence: {
|
|
11586
|
-
file:
|
|
12239
|
+
file: import_node_path48.default.relative(serviceDir, file.path),
|
|
11587
12240
|
line: table.line,
|
|
11588
12241
|
snippet: snippet(file.content, table.line)
|
|
11589
12242
|
}
|
|
@@ -11605,7 +12258,7 @@ function railsSchemaForeignKeys(file, serviceDir) {
|
|
|
11605
12258
|
childTable,
|
|
11606
12259
|
parentTable,
|
|
11607
12260
|
evidence: {
|
|
11608
|
-
file:
|
|
12261
|
+
file: import_node_path48.default.relative(serviceDir, file.path),
|
|
11609
12262
|
line,
|
|
11610
12263
|
snippet: snippet(file.content, line)
|
|
11611
12264
|
}
|
|
@@ -11682,13 +12335,13 @@ function railsModelEndpointsFromFile(file, serviceDir) {
|
|
|
11682
12335
|
seen.add(table);
|
|
11683
12336
|
const line = node.startPosition.row + 1;
|
|
11684
12337
|
out.push({
|
|
11685
|
-
infraId: (0,
|
|
12338
|
+
infraId: (0, import_types37.infraId)("sql-table", table),
|
|
11686
12339
|
name: table,
|
|
11687
12340
|
kind: "sql-table",
|
|
11688
12341
|
edgeType: "CALLS",
|
|
11689
12342
|
confidenceKind: "verified-call-site",
|
|
11690
12343
|
evidence: {
|
|
11691
|
-
file:
|
|
12344
|
+
file: import_node_path48.default.relative(serviceDir, file.path),
|
|
11692
12345
|
line,
|
|
11693
12346
|
snippet: snippet(file.content, line)
|
|
11694
12347
|
}
|
|
@@ -11725,7 +12378,7 @@ function railsModelForeignKeys(file, serviceDir) {
|
|
|
11725
12378
|
childTable,
|
|
11726
12379
|
parentTable,
|
|
11727
12380
|
evidence: {
|
|
11728
|
-
file:
|
|
12381
|
+
file: import_node_path48.default.relative(serviceDir, file.path),
|
|
11729
12382
|
line,
|
|
11730
12383
|
snippet: snippet(file.content, line)
|
|
11731
12384
|
}
|
|
@@ -11737,15 +12390,15 @@ function railsModelForeignKeys(file, serviceDir) {
|
|
|
11737
12390
|
|
|
11738
12391
|
// src/extract/calls/eloquent.ts
|
|
11739
12392
|
init_cjs_shims();
|
|
11740
|
-
var
|
|
12393
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
11741
12394
|
var import_tree_sitter13 = __toESM(require("tree-sitter"), 1);
|
|
11742
|
-
var
|
|
11743
|
-
var
|
|
12395
|
+
var import_tree_sitter_php3 = __toESM(require("tree-sitter-php"), 1);
|
|
12396
|
+
var import_types38 = require("@neat.is/types");
|
|
11744
12397
|
var LARAVEL_SCHEMA_RE = /\bSchema::(create|createIfNotExists|table)\b/;
|
|
11745
12398
|
var PARSE_CHUNK9 = 16384;
|
|
11746
12399
|
function makePhpParser2() {
|
|
11747
12400
|
const p = new import_tree_sitter13.default();
|
|
11748
|
-
p.setLanguage(
|
|
12401
|
+
p.setLanguage(import_tree_sitter_php3.default.php_only);
|
|
11749
12402
|
return p;
|
|
11750
12403
|
}
|
|
11751
12404
|
function parseSource9(parser, source) {
|
|
@@ -11987,14 +12640,14 @@ function laravelMigrationEndpointsFromFile(file, serviceDir) {
|
|
|
11987
12640
|
}
|
|
11988
12641
|
}
|
|
11989
12642
|
out.push({
|
|
11990
|
-
infraId: (0,
|
|
12643
|
+
infraId: (0, import_types38.infraId)("sql-table", bp.table),
|
|
11991
12644
|
name: bp.table,
|
|
11992
12645
|
kind: "sql-table",
|
|
11993
12646
|
edgeType: "CALLS",
|
|
11994
12647
|
confidenceKind: "structural",
|
|
11995
12648
|
...columns.length > 0 ? { columns } : {},
|
|
11996
12649
|
evidence: {
|
|
11997
|
-
file:
|
|
12650
|
+
file: import_node_path49.default.relative(serviceDir, file.path),
|
|
11998
12651
|
line: bp.line,
|
|
11999
12652
|
snippet: snippet(file.content, bp.line)
|
|
12000
12653
|
}
|
|
@@ -12016,7 +12669,7 @@ function laravelMigrationForeignKeys(file, serviceDir) {
|
|
|
12016
12669
|
childTable,
|
|
12017
12670
|
parentTable,
|
|
12018
12671
|
evidence: {
|
|
12019
|
-
file:
|
|
12672
|
+
file: import_node_path49.default.relative(serviceDir, file.path),
|
|
12020
12673
|
line,
|
|
12021
12674
|
snippet: snippet(file.content, line)
|
|
12022
12675
|
}
|
|
@@ -12130,13 +12783,13 @@ function laravelModelEndpointsFromFile(file, serviceDir) {
|
|
|
12130
12783
|
seen.add(table);
|
|
12131
12784
|
const line = node.startPosition.row + 1;
|
|
12132
12785
|
out.push({
|
|
12133
|
-
infraId: (0,
|
|
12786
|
+
infraId: (0, import_types38.infraId)("sql-table", table),
|
|
12134
12787
|
name: table,
|
|
12135
12788
|
kind: "sql-table",
|
|
12136
12789
|
edgeType: "CALLS",
|
|
12137
12790
|
confidenceKind: "verified-call-site",
|
|
12138
12791
|
evidence: {
|
|
12139
|
-
file:
|
|
12792
|
+
file: import_node_path49.default.relative(serviceDir, file.path),
|
|
12140
12793
|
line,
|
|
12141
12794
|
snippet: snippet(file.content, line)
|
|
12142
12795
|
}
|
|
@@ -12172,7 +12825,7 @@ function laravelModelForeignKeys(file, serviceDir) {
|
|
|
12172
12825
|
childTable,
|
|
12173
12826
|
parentTable,
|
|
12174
12827
|
evidence: {
|
|
12175
|
-
file:
|
|
12828
|
+
file: import_node_path49.default.relative(serviceDir, file.path),
|
|
12176
12829
|
line,
|
|
12177
12830
|
snippet: snippet(file.content, line)
|
|
12178
12831
|
}
|
|
@@ -12184,10 +12837,10 @@ function laravelModelForeignKeys(file, serviceDir) {
|
|
|
12184
12837
|
|
|
12185
12838
|
// src/extract/calls/go.ts
|
|
12186
12839
|
init_cjs_shims();
|
|
12187
|
-
var
|
|
12840
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
12188
12841
|
var import_tree_sitter14 = __toESM(require("tree-sitter"), 1);
|
|
12189
|
-
var
|
|
12190
|
-
var
|
|
12842
|
+
var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
|
|
12843
|
+
var import_types39 = require("@neat.is/types");
|
|
12191
12844
|
init_otel();
|
|
12192
12845
|
var PARSE_CHUNK10 = 16384;
|
|
12193
12846
|
var DATABASE_SQL_METHODS = /* @__PURE__ */ new Set([
|
|
@@ -12216,7 +12869,7 @@ var DATABASE_SQL_IMPORT = "database/sql";
|
|
|
12216
12869
|
var SQLX_IMPORT = "github.com/jmoiron/sqlx";
|
|
12217
12870
|
function makeGoParser3() {
|
|
12218
12871
|
const p = new import_tree_sitter14.default();
|
|
12219
|
-
p.setLanguage(
|
|
12872
|
+
p.setLanguage(import_tree_sitter_go4.default);
|
|
12220
12873
|
return p;
|
|
12221
12874
|
}
|
|
12222
12875
|
function parseSource10(parser, source) {
|
|
@@ -12259,7 +12912,7 @@ function firstStringLiteralArg(argsNode) {
|
|
|
12259
12912
|
return null;
|
|
12260
12913
|
}
|
|
12261
12914
|
function goSqlEndpointsFromFile(file, serviceDir) {
|
|
12262
|
-
if (
|
|
12915
|
+
if (import_node_path52.default.extname(file.path) !== ".go") return [];
|
|
12263
12916
|
if (!file.content.includes(DATABASE_SQL_IMPORT) && !file.content.includes(SQLX_IMPORT)) return [];
|
|
12264
12917
|
const tree = parseSource10(makeGoParser3(), file.content);
|
|
12265
12918
|
const importsDatabaseSql = goImportsAny(tree.rootNode, /* @__PURE__ */ new Set([DATABASE_SQL_IMPORT]));
|
|
@@ -12281,14 +12934,14 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
12281
12934
|
const columns = columnsFromSqlStatement(sql);
|
|
12282
12935
|
const line = node.startPosition.row + 1;
|
|
12283
12936
|
out.push({
|
|
12284
|
-
infraId: (0,
|
|
12937
|
+
infraId: (0, import_types39.infraId)("sql-table", table),
|
|
12285
12938
|
name: table,
|
|
12286
12939
|
kind: "sql-table",
|
|
12287
12940
|
edgeType: "CALLS",
|
|
12288
12941
|
confidenceKind: "verified-call-site",
|
|
12289
12942
|
...columns.length > 0 ? { columns } : {},
|
|
12290
12943
|
evidence: {
|
|
12291
|
-
file: toPosix(
|
|
12944
|
+
file: toPosix(import_node_path52.default.relative(serviceDir, file.path)),
|
|
12292
12945
|
line,
|
|
12293
12946
|
snippet: snippet(file.content, line)
|
|
12294
12947
|
}
|
|
@@ -12299,15 +12952,15 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
12299
12952
|
|
|
12300
12953
|
// src/extract/calls/gorm.ts
|
|
12301
12954
|
init_cjs_shims();
|
|
12302
|
-
var
|
|
12955
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
12303
12956
|
var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
|
|
12304
|
-
var
|
|
12305
|
-
var
|
|
12957
|
+
var import_tree_sitter_go5 = __toESM(require("tree-sitter-go"), 1);
|
|
12958
|
+
var import_types40 = require("@neat.is/types");
|
|
12306
12959
|
var GORM_IMPORT_RE = /gorm\.io\/gorm/;
|
|
12307
12960
|
var PARSE_CHUNK11 = 16384;
|
|
12308
12961
|
function makeGoParser4() {
|
|
12309
12962
|
const p = new import_tree_sitter15.default();
|
|
12310
|
-
p.setLanguage(
|
|
12963
|
+
p.setLanguage(import_tree_sitter_go5.default);
|
|
12311
12964
|
return p;
|
|
12312
12965
|
}
|
|
12313
12966
|
function parseSource11(parser, source) {
|
|
@@ -12732,7 +13385,7 @@ function collectColumns(struct, structs, seen, prefix, out, emitted) {
|
|
|
12732
13385
|
seen.delete(struct.name);
|
|
12733
13386
|
}
|
|
12734
13387
|
function gormEndpointsFromFile(file, serviceDir) {
|
|
12735
|
-
if (
|
|
13388
|
+
if (import_node_path53.default.extname(file.path) !== ".go") return [];
|
|
12736
13389
|
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
12737
13390
|
const tree = parseSource11(makeGoParser4(), file.content);
|
|
12738
13391
|
const { structs, models, tableFor } = analyze(tree);
|
|
@@ -12747,14 +13400,14 @@ function gormEndpointsFromFile(file, serviceDir) {
|
|
|
12747
13400
|
const columns = [];
|
|
12748
13401
|
collectColumns(struct, structs, /* @__PURE__ */ new Set(), "", columns, /* @__PURE__ */ new Set());
|
|
12749
13402
|
out.push({
|
|
12750
|
-
infraId: (0,
|
|
13403
|
+
infraId: (0, import_types40.infraId)("sql-table", table),
|
|
12751
13404
|
name: table,
|
|
12752
13405
|
kind: "sql-table",
|
|
12753
13406
|
edgeType: "CALLS",
|
|
12754
13407
|
confidenceKind: "structural",
|
|
12755
13408
|
...columns.length > 0 ? { columns } : {},
|
|
12756
13409
|
evidence: {
|
|
12757
|
-
file: toPosix(
|
|
13410
|
+
file: toPosix(import_node_path53.default.relative(serviceDir, file.path)),
|
|
12758
13411
|
line: struct.line,
|
|
12759
13412
|
snippet: snippet(file.content, struct.line)
|
|
12760
13413
|
}
|
|
@@ -12763,7 +13416,7 @@ function gormEndpointsFromFile(file, serviceDir) {
|
|
|
12763
13416
|
return out;
|
|
12764
13417
|
}
|
|
12765
13418
|
function gormForeignKeys(file, serviceDir) {
|
|
12766
|
-
if (
|
|
13419
|
+
if (import_node_path53.default.extname(file.path) !== ".go") return [];
|
|
12767
13420
|
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
12768
13421
|
const tree = parseSource11(makeGoParser4(), file.content);
|
|
12769
13422
|
const { structs, models, tableFor } = analyze(tree);
|
|
@@ -12778,7 +13431,7 @@ function gormForeignKeys(file, serviceDir) {
|
|
|
12778
13431
|
childTable,
|
|
12779
13432
|
parentTable,
|
|
12780
13433
|
evidence: {
|
|
12781
|
-
file: toPosix(
|
|
13434
|
+
file: toPosix(import_node_path53.default.relative(serviceDir, file.path)),
|
|
12782
13435
|
line,
|
|
12783
13436
|
snippet: snippet(file.content, line)
|
|
12784
13437
|
}
|
|
@@ -12817,11 +13470,11 @@ function gormForeignKeys(file, serviceDir) {
|
|
|
12817
13470
|
function edgeTypeFromEndpoint(ep) {
|
|
12818
13471
|
switch (ep.edgeType) {
|
|
12819
13472
|
case "PUBLISHES_TO":
|
|
12820
|
-
return
|
|
13473
|
+
return import_types41.EdgeType.PUBLISHES_TO;
|
|
12821
13474
|
case "CONSUMES_FROM":
|
|
12822
|
-
return
|
|
13475
|
+
return import_types41.EdgeType.CONSUMES_FROM;
|
|
12823
13476
|
default:
|
|
12824
|
-
return
|
|
13477
|
+
return import_types41.EdgeType.CALLS;
|
|
12825
13478
|
}
|
|
12826
13479
|
}
|
|
12827
13480
|
function isAwsKind(kind) {
|
|
@@ -12881,7 +13534,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
12881
13534
|
if (!graph.hasNode(ep.infraId)) {
|
|
12882
13535
|
const node = {
|
|
12883
13536
|
id: ep.infraId,
|
|
12884
|
-
type:
|
|
13537
|
+
type: import_types41.NodeType.InfraNode,
|
|
12885
13538
|
name: ep.name,
|
|
12886
13539
|
// #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
|
|
12887
13540
|
// aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
|
|
@@ -12894,21 +13547,21 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
12894
13547
|
}
|
|
12895
13548
|
if (ep.columns && ep.columns.length > 0) {
|
|
12896
13549
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
12897
|
-
if (node.type ===
|
|
13550
|
+
if (node.type === import_types41.NodeType.InfraNode) {
|
|
12898
13551
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
12899
13552
|
...node,
|
|
12900
13553
|
columns: foldColumns(
|
|
12901
13554
|
node.columns,
|
|
12902
13555
|
ep.columns,
|
|
12903
|
-
|
|
12904
|
-
(0,
|
|
13556
|
+
import_types41.Provenance.EXTRACTED,
|
|
13557
|
+
(0, import_types41.confidenceForExtracted)(ep.confidenceKind)
|
|
12905
13558
|
)
|
|
12906
13559
|
});
|
|
12907
13560
|
}
|
|
12908
13561
|
}
|
|
12909
13562
|
if (ep.sdkWrites && Object.keys(ep.sdkWrites).length > 0) {
|
|
12910
13563
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
12911
|
-
if (node.type ===
|
|
13564
|
+
if (node.type === import_types41.NodeType.InfraNode) {
|
|
12912
13565
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
12913
13566
|
...node,
|
|
12914
13567
|
columns: foldSdkWrites(node.columns, ep.sdkWrites)
|
|
@@ -12916,7 +13569,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
12916
13569
|
}
|
|
12917
13570
|
}
|
|
12918
13571
|
const edgeType = edgeTypeFromEndpoint(ep);
|
|
12919
|
-
const confidence = (0,
|
|
13572
|
+
const confidence = (0, import_types41.confidenceForExtracted)(ep.confidenceKind);
|
|
12920
13573
|
const relFile = toPosix(ep.evidence.file);
|
|
12921
13574
|
const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
12922
13575
|
graph,
|
|
@@ -12926,7 +13579,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
12926
13579
|
);
|
|
12927
13580
|
nodesAdded += n;
|
|
12928
13581
|
edgesAdded += e;
|
|
12929
|
-
if (!(0,
|
|
13582
|
+
if (!(0, import_types41.passesExtractedFloor)(confidence)) {
|
|
12930
13583
|
noteExtractedDropped({
|
|
12931
13584
|
source: fileNodeId,
|
|
12932
13585
|
target: ep.infraId,
|
|
@@ -12946,7 +13599,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
12946
13599
|
source: fileNodeId,
|
|
12947
13600
|
target: ep.infraId,
|
|
12948
13601
|
type: edgeType,
|
|
12949
|
-
provenance:
|
|
13602
|
+
provenance: import_types41.Provenance.EXTRACTED,
|
|
12950
13603
|
confidence,
|
|
12951
13604
|
evidence: ep.evidence
|
|
12952
13605
|
};
|
|
@@ -12969,7 +13622,7 @@ async function addCallEdges(graph, services) {
|
|
|
12969
13622
|
|
|
12970
13623
|
// src/extract/table-edges.ts
|
|
12971
13624
|
init_cjs_shims();
|
|
12972
|
-
var
|
|
13625
|
+
var import_types42 = require("@neat.is/types");
|
|
12973
13626
|
async function addTableEdges(graph, services) {
|
|
12974
13627
|
let nodesAdded = 0;
|
|
12975
13628
|
let edgesAdded = 0;
|
|
@@ -12997,20 +13650,20 @@ async function addTableEdges(graph, services) {
|
|
|
12997
13650
|
}
|
|
12998
13651
|
refs.push(...modelRefs);
|
|
12999
13652
|
for (const ref of refs) {
|
|
13000
|
-
const childId = (0,
|
|
13001
|
-
const parentId = (0,
|
|
13653
|
+
const childId = (0, import_types42.infraId)("sql-table", ref.childTable);
|
|
13654
|
+
const parentId = (0, import_types42.infraId)("sql-table", ref.parentTable);
|
|
13002
13655
|
if (childId === parentId) continue;
|
|
13003
13656
|
nodesAdded += ensureTableNode(graph, childId, ref.childTable);
|
|
13004
13657
|
nodesAdded += ensureTableNode(graph, parentId, ref.parentTable);
|
|
13005
|
-
const edgeId = (0,
|
|
13658
|
+
const edgeId = (0, import_types42.extractedEdgeId)(childId, parentId, import_types42.EdgeType.REFERENCES);
|
|
13006
13659
|
if (graph.hasEdge(edgeId)) continue;
|
|
13007
13660
|
const edge = {
|
|
13008
13661
|
id: edgeId,
|
|
13009
13662
|
source: childId,
|
|
13010
13663
|
target: parentId,
|
|
13011
|
-
type:
|
|
13012
|
-
provenance:
|
|
13013
|
-
confidence: (0,
|
|
13664
|
+
type: import_types42.EdgeType.REFERENCES,
|
|
13665
|
+
provenance: import_types42.Provenance.EXTRACTED,
|
|
13666
|
+
confidence: (0, import_types42.confidenceForExtracted)("structural"),
|
|
13014
13667
|
evidence: ref.evidence
|
|
13015
13668
|
};
|
|
13016
13669
|
graph.addEdgeWithKey(edgeId, childId, parentId, edge);
|
|
@@ -13023,7 +13676,7 @@ function ensureTableNode(graph, id, name) {
|
|
|
13023
13676
|
if (graph.hasNode(id)) return 0;
|
|
13024
13677
|
const node = {
|
|
13025
13678
|
id,
|
|
13026
|
-
type:
|
|
13679
|
+
type: import_types42.NodeType.InfraNode,
|
|
13027
13680
|
name,
|
|
13028
13681
|
provider: "self",
|
|
13029
13682
|
kind: "sql-table"
|
|
@@ -13037,16 +13690,16 @@ init_cjs_shims();
|
|
|
13037
13690
|
|
|
13038
13691
|
// src/extract/infra/docker-compose.ts
|
|
13039
13692
|
init_cjs_shims();
|
|
13040
|
-
var
|
|
13041
|
-
var
|
|
13693
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
13694
|
+
var import_types44 = require("@neat.is/types");
|
|
13042
13695
|
|
|
13043
13696
|
// src/extract/infra/shared.ts
|
|
13044
13697
|
init_cjs_shims();
|
|
13045
|
-
var
|
|
13698
|
+
var import_types43 = require("@neat.is/types");
|
|
13046
13699
|
function makeInfraNode(kind, name, provider = "self", extras) {
|
|
13047
13700
|
return {
|
|
13048
|
-
id: (0,
|
|
13049
|
-
type:
|
|
13701
|
+
id: (0, import_types43.infraId)(kind, name),
|
|
13702
|
+
type: import_types43.NodeType.InfraNode,
|
|
13050
13703
|
name,
|
|
13051
13704
|
provider,
|
|
13052
13705
|
kind,
|
|
@@ -13090,8 +13743,8 @@ function emitPlatformResourceEdge(graph, anchorId, edgeType, kind, name, provide
|
|
|
13090
13743
|
source: anchorId,
|
|
13091
13744
|
target: node.id,
|
|
13092
13745
|
type: edgeType,
|
|
13093
|
-
provenance:
|
|
13094
|
-
confidence: (0,
|
|
13746
|
+
provenance: import_types43.Provenance.EXTRACTED,
|
|
13747
|
+
confidence: (0, import_types43.confidenceForExtracted)("structural"),
|
|
13095
13748
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
13096
13749
|
};
|
|
13097
13750
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -13108,7 +13761,7 @@ function dependsOnList(value) {
|
|
|
13108
13761
|
}
|
|
13109
13762
|
function serviceNameToServiceNode(name, services) {
|
|
13110
13763
|
for (const s of services) {
|
|
13111
|
-
if (s.node.name === name ||
|
|
13764
|
+
if (s.node.name === name || import_node_path54.default.basename(s.dir) === name) return s.node.id;
|
|
13112
13765
|
}
|
|
13113
13766
|
return null;
|
|
13114
13767
|
}
|
|
@@ -13117,7 +13770,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
13117
13770
|
let edgesAdded = 0;
|
|
13118
13771
|
let composePath = null;
|
|
13119
13772
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
13120
|
-
const abs =
|
|
13773
|
+
const abs = import_node_path54.default.join(scanPath, name);
|
|
13121
13774
|
if (await exists2(abs)) {
|
|
13122
13775
|
composePath = abs;
|
|
13123
13776
|
break;
|
|
@@ -13130,13 +13783,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
13130
13783
|
} catch (err) {
|
|
13131
13784
|
recordExtractionError(
|
|
13132
13785
|
"infra docker-compose",
|
|
13133
|
-
|
|
13786
|
+
import_node_path54.default.relative(scanPath, composePath),
|
|
13134
13787
|
err
|
|
13135
13788
|
);
|
|
13136
13789
|
return { nodesAdded, edgesAdded };
|
|
13137
13790
|
}
|
|
13138
13791
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
13139
|
-
const evidenceFile =
|
|
13792
|
+
const evidenceFile = import_node_path54.default.relative(scanPath, composePath).split(import_node_path54.default.sep).join("/");
|
|
13140
13793
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
13141
13794
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
13142
13795
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -13158,15 +13811,15 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
13158
13811
|
for (const dep of dependsOnList(svc.depends_on)) {
|
|
13159
13812
|
const targetId = composeNameToNodeId.get(dep);
|
|
13160
13813
|
if (!targetId) continue;
|
|
13161
|
-
const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId,
|
|
13814
|
+
const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types44.EdgeType.DEPENDS_ON);
|
|
13162
13815
|
if (graph.hasEdge(edgeId)) continue;
|
|
13163
13816
|
const edge = {
|
|
13164
13817
|
id: edgeId,
|
|
13165
13818
|
source: sourceId,
|
|
13166
13819
|
target: targetId,
|
|
13167
|
-
type:
|
|
13168
|
-
provenance:
|
|
13169
|
-
confidence: (0,
|
|
13820
|
+
type: import_types44.EdgeType.DEPENDS_ON,
|
|
13821
|
+
provenance: import_types44.Provenance.EXTRACTED,
|
|
13822
|
+
confidence: (0, import_types44.confidenceForExtracted)("structural"),
|
|
13170
13823
|
evidence: { file: evidenceFile }
|
|
13171
13824
|
};
|
|
13172
13825
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -13178,9 +13831,9 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
13178
13831
|
|
|
13179
13832
|
// src/extract/infra/dockerfile.ts
|
|
13180
13833
|
init_cjs_shims();
|
|
13181
|
-
var
|
|
13182
|
-
var
|
|
13183
|
-
var
|
|
13834
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
13835
|
+
var import_node_fs23 = require("fs");
|
|
13836
|
+
var import_types45 = require("@neat.is/types");
|
|
13184
13837
|
function readDockerfile(content) {
|
|
13185
13838
|
let image = null;
|
|
13186
13839
|
const ports = [];
|
|
@@ -13209,15 +13862,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13209
13862
|
let nodesAdded = 0;
|
|
13210
13863
|
let edgesAdded = 0;
|
|
13211
13864
|
for (const service of services) {
|
|
13212
|
-
const dockerfilePath =
|
|
13865
|
+
const dockerfilePath = import_node_path55.default.join(service.dir, "Dockerfile");
|
|
13213
13866
|
if (!await exists2(dockerfilePath)) continue;
|
|
13214
13867
|
let content;
|
|
13215
13868
|
try {
|
|
13216
|
-
content = await
|
|
13869
|
+
content = await import_node_fs23.promises.readFile(dockerfilePath, "utf8");
|
|
13217
13870
|
} catch (err) {
|
|
13218
13871
|
recordExtractionError(
|
|
13219
13872
|
"infra dockerfile",
|
|
13220
|
-
|
|
13873
|
+
import_node_path55.default.relative(scanPath, dockerfilePath),
|
|
13221
13874
|
err
|
|
13222
13875
|
);
|
|
13223
13876
|
continue;
|
|
@@ -13229,8 +13882,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13229
13882
|
graph.addNode(node.id, node);
|
|
13230
13883
|
nodesAdded++;
|
|
13231
13884
|
}
|
|
13232
|
-
const relDockerfile = toPosix(
|
|
13233
|
-
const evidenceFile = toPosix(
|
|
13885
|
+
const relDockerfile = toPosix(import_node_path55.default.relative(service.dir, dockerfilePath));
|
|
13886
|
+
const evidenceFile = toPosix(import_node_path55.default.relative(scanPath, dockerfilePath));
|
|
13234
13887
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
13235
13888
|
graph,
|
|
13236
13889
|
service.pkg.name,
|
|
@@ -13239,15 +13892,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13239
13892
|
);
|
|
13240
13893
|
nodesAdded += fn;
|
|
13241
13894
|
edgesAdded += fe;
|
|
13242
|
-
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id,
|
|
13895
|
+
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types45.EdgeType.RUNS_ON);
|
|
13243
13896
|
if (!graph.hasEdge(edgeId)) {
|
|
13244
13897
|
const edge = {
|
|
13245
13898
|
id: edgeId,
|
|
13246
13899
|
source: fileNodeId,
|
|
13247
13900
|
target: node.id,
|
|
13248
|
-
type:
|
|
13249
|
-
provenance:
|
|
13250
|
-
confidence: (0,
|
|
13901
|
+
type: import_types45.EdgeType.RUNS_ON,
|
|
13902
|
+
provenance: import_types45.Provenance.EXTRACTED,
|
|
13903
|
+
confidence: (0, import_types45.confidenceForExtracted)("structural"),
|
|
13251
13904
|
evidence: {
|
|
13252
13905
|
file: evidenceFile,
|
|
13253
13906
|
...facts.entrypoint ? { snippet: facts.entrypoint.slice(0, 120) } : {}
|
|
@@ -13262,15 +13915,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13262
13915
|
graph.addNode(portNode.id, portNode);
|
|
13263
13916
|
nodesAdded++;
|
|
13264
13917
|
}
|
|
13265
|
-
const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id,
|
|
13918
|
+
const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types45.EdgeType.CONNECTS_TO);
|
|
13266
13919
|
if (graph.hasEdge(portEdgeId)) continue;
|
|
13267
13920
|
const portEdge = {
|
|
13268
13921
|
id: portEdgeId,
|
|
13269
13922
|
source: fileNodeId,
|
|
13270
13923
|
target: portNode.id,
|
|
13271
|
-
type:
|
|
13272
|
-
provenance:
|
|
13273
|
-
confidence: (0,
|
|
13924
|
+
type: import_types45.EdgeType.CONNECTS_TO,
|
|
13925
|
+
provenance: import_types45.Provenance.EXTRACTED,
|
|
13926
|
+
confidence: (0, import_types45.confidenceForExtracted)("structural"),
|
|
13274
13927
|
evidence: { file: evidenceFile, snippet: `EXPOSE ${port}` }
|
|
13275
13928
|
};
|
|
13276
13929
|
graph.addEdgeWithKey(portEdgeId, portEdge.source, portEdge.target, portEdge);
|
|
@@ -13282,23 +13935,23 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13282
13935
|
|
|
13283
13936
|
// src/extract/infra/terraform.ts
|
|
13284
13937
|
init_cjs_shims();
|
|
13285
|
-
var
|
|
13286
|
-
var
|
|
13287
|
-
var
|
|
13938
|
+
var import_node_fs24 = require("fs");
|
|
13939
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
13940
|
+
var import_types46 = require("@neat.is/types");
|
|
13288
13941
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
13289
13942
|
var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
|
|
13290
13943
|
async function walkTfFiles(start, depth = 0, max = 5) {
|
|
13291
13944
|
if (depth > max) return [];
|
|
13292
13945
|
const out = [];
|
|
13293
|
-
const entries = await
|
|
13946
|
+
const entries = await import_node_fs24.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
13294
13947
|
for (const entry of entries) {
|
|
13295
13948
|
if (entry.isDirectory()) {
|
|
13296
13949
|
if (IGNORED_DIRS.has(entry.name) || entry.name === ".terraform") continue;
|
|
13297
|
-
const child =
|
|
13950
|
+
const child = import_node_path56.default.join(start, entry.name);
|
|
13298
13951
|
if (await isPythonVenvDir(child)) continue;
|
|
13299
13952
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
13300
13953
|
} else if (entry.isFile() && entry.name.endsWith(".tf")) {
|
|
13301
|
-
out.push(
|
|
13954
|
+
out.push(import_node_path56.default.join(start, entry.name));
|
|
13302
13955
|
}
|
|
13303
13956
|
}
|
|
13304
13957
|
return out;
|
|
@@ -13329,8 +13982,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
13329
13982
|
let edgesAdded = 0;
|
|
13330
13983
|
const files = await walkTfFiles(scanPath);
|
|
13331
13984
|
for (const file of files) {
|
|
13332
|
-
const content = await
|
|
13333
|
-
const evidenceFile = toPosix(
|
|
13985
|
+
const content = await import_node_fs24.promises.readFile(file, "utf8");
|
|
13986
|
+
const evidenceFile = toPosix(import_node_path56.default.relative(scanPath, file));
|
|
13334
13987
|
const resources = [];
|
|
13335
13988
|
const byKey = /* @__PURE__ */ new Map();
|
|
13336
13989
|
RESOURCE_RE.lastIndex = 0;
|
|
@@ -13365,16 +14018,16 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
13365
14018
|
if (!target) continue;
|
|
13366
14019
|
if (seen.has(target.nodeId)) continue;
|
|
13367
14020
|
seen.add(target.nodeId);
|
|
13368
|
-
const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId,
|
|
14021
|
+
const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types46.EdgeType.DEPENDS_ON);
|
|
13369
14022
|
if (graph.hasEdge(edgeId)) continue;
|
|
13370
14023
|
const line = lineAt2(content, resource.bodyOffset + ref.index);
|
|
13371
14024
|
const edge = {
|
|
13372
14025
|
id: edgeId,
|
|
13373
14026
|
source: resource.nodeId,
|
|
13374
14027
|
target: target.nodeId,
|
|
13375
|
-
type:
|
|
13376
|
-
provenance:
|
|
13377
|
-
confidence: (0,
|
|
14028
|
+
type: import_types46.EdgeType.DEPENDS_ON,
|
|
14029
|
+
provenance: import_types46.Provenance.EXTRACTED,
|
|
14030
|
+
confidence: (0, import_types46.confidenceForExtracted)("structural"),
|
|
13378
14031
|
evidence: { file: evidenceFile, line, snippet: key }
|
|
13379
14032
|
};
|
|
13380
14033
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -13387,8 +14040,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
13387
14040
|
|
|
13388
14041
|
// src/extract/infra/k8s.ts
|
|
13389
14042
|
init_cjs_shims();
|
|
13390
|
-
var
|
|
13391
|
-
var
|
|
14043
|
+
var import_node_fs25 = require("fs");
|
|
14044
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
13392
14045
|
var import_yaml3 = require("yaml");
|
|
13393
14046
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
13394
14047
|
Service: "k8s-service",
|
|
@@ -13402,15 +14055,15 @@ var K8S_KIND_TO_INFRA_KIND = {
|
|
|
13402
14055
|
async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
13403
14056
|
if (depth > max) return [];
|
|
13404
14057
|
const out = [];
|
|
13405
|
-
const entries = await
|
|
14058
|
+
const entries = await import_node_fs25.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
13406
14059
|
for (const entry of entries) {
|
|
13407
14060
|
if (entry.isDirectory()) {
|
|
13408
14061
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
13409
|
-
const child =
|
|
14062
|
+
const child = import_node_path57.default.join(start, entry.name);
|
|
13410
14063
|
if (await isPythonVenvDir(child)) continue;
|
|
13411
14064
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
13412
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
13413
|
-
out.push(
|
|
14065
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path57.default.extname(entry.name))) {
|
|
14066
|
+
out.push(import_node_path57.default.join(start, entry.name));
|
|
13414
14067
|
}
|
|
13415
14068
|
}
|
|
13416
14069
|
return out;
|
|
@@ -13419,7 +14072,7 @@ async function addK8sResources(graph, scanPath) {
|
|
|
13419
14072
|
let nodesAdded = 0;
|
|
13420
14073
|
const files = await walkYamlFiles2(scanPath);
|
|
13421
14074
|
for (const file of files) {
|
|
13422
|
-
const content = await
|
|
14075
|
+
const content = await import_node_fs25.promises.readFile(file, "utf8");
|
|
13423
14076
|
let docs;
|
|
13424
14077
|
try {
|
|
13425
14078
|
docs = (0, import_yaml3.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
@@ -13443,16 +14096,16 @@ async function addK8sResources(graph, scanPath) {
|
|
|
13443
14096
|
|
|
13444
14097
|
// src/extract/infra/cloudflare.ts
|
|
13445
14098
|
init_cjs_shims();
|
|
13446
|
-
var
|
|
13447
|
-
var
|
|
14099
|
+
var import_node_fs26 = require("fs");
|
|
14100
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
13448
14101
|
var import_smol_toml2 = require("smol-toml");
|
|
13449
|
-
var
|
|
14102
|
+
var import_types47 = require("@neat.is/types");
|
|
13450
14103
|
var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
|
|
13451
14104
|
async function readWranglerConfig(dir) {
|
|
13452
14105
|
for (const filename of WRANGLER_FILENAMES) {
|
|
13453
|
-
const abs =
|
|
14106
|
+
const abs = import_node_path58.default.join(dir, filename);
|
|
13454
14107
|
if (!await exists2(abs)) continue;
|
|
13455
|
-
const raw = await
|
|
14108
|
+
const raw = await import_node_fs26.promises.readFile(abs, "utf8");
|
|
13456
14109
|
const config = filename === "wrangler.toml" ? (0, import_smol_toml2.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
13457
14110
|
return { config, relFile: filename, raw };
|
|
13458
14111
|
}
|
|
@@ -13494,8 +14147,8 @@ function addResourceEdge(graph, anchorId, edgeType, kind, name, evidenceFile, li
|
|
|
13494
14147
|
source: anchorId,
|
|
13495
14148
|
target: node.id,
|
|
13496
14149
|
type: edgeType,
|
|
13497
|
-
provenance:
|
|
13498
|
-
confidence: (0,
|
|
14150
|
+
provenance: import_types47.Provenance.EXTRACTED,
|
|
14151
|
+
confidence: (0, import_types47.confidenceForExtracted)("structural"),
|
|
13499
14152
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
13500
14153
|
};
|
|
13501
14154
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -13513,11 +14166,11 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13513
14166
|
try {
|
|
13514
14167
|
read = await readWranglerConfig(service.dir);
|
|
13515
14168
|
} catch (err) {
|
|
13516
|
-
recordExtractionError("infra cloudflare",
|
|
14169
|
+
recordExtractionError("infra cloudflare", import_node_path58.default.relative(scanPath, service.dir), err);
|
|
13517
14170
|
continue;
|
|
13518
14171
|
}
|
|
13519
14172
|
if (!read || !read.config.name) continue;
|
|
13520
|
-
const evidenceFile = toPosix(
|
|
14173
|
+
const evidenceFile = toPosix(import_node_path58.default.relative(scanPath, import_node_path58.default.join(service.dir, read.relFile)));
|
|
13521
14174
|
discovered.push({ service, config: read.config, relFile: read.relFile, raw: read.raw, evidenceFile });
|
|
13522
14175
|
}
|
|
13523
14176
|
for (const worker of discovered) {
|
|
@@ -13529,7 +14182,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13529
14182
|
}
|
|
13530
14183
|
let anchorId = service.node.id;
|
|
13531
14184
|
if (config.main) {
|
|
13532
|
-
const entryRelPath = toPosix(
|
|
14185
|
+
const entryRelPath = toPosix(import_node_path58.default.normalize(config.main));
|
|
13533
14186
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
13534
14187
|
graph,
|
|
13535
14188
|
service.pkg.name,
|
|
@@ -13556,15 +14209,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13556
14209
|
nodesAdded++;
|
|
13557
14210
|
}
|
|
13558
14211
|
if (runtimeNode.id !== anchorId) {
|
|
13559
|
-
const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id,
|
|
14212
|
+
const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types47.EdgeType.RUNS_ON);
|
|
13560
14213
|
if (!graph.hasEdge(runsOnId)) {
|
|
13561
14214
|
const edge = {
|
|
13562
14215
|
id: runsOnId,
|
|
13563
14216
|
source: anchorId,
|
|
13564
14217
|
target: runtimeNode.id,
|
|
13565
|
-
type:
|
|
13566
|
-
provenance:
|
|
13567
|
-
confidence: (0,
|
|
14218
|
+
type: import_types47.EdgeType.RUNS_ON,
|
|
14219
|
+
provenance: import_types47.Provenance.EXTRACTED,
|
|
14220
|
+
confidence: (0, import_types47.confidenceForExtracted)("structural"),
|
|
13568
14221
|
evidence: {
|
|
13569
14222
|
file: evidenceFile,
|
|
13570
14223
|
...config.compatibility_date ? { snippet: `compatibility_date = ${config.compatibility_date}`.slice(0, 120) } : {}
|
|
@@ -13578,7 +14231,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13578
14231
|
const result = addResourceEdge(
|
|
13579
14232
|
graph,
|
|
13580
14233
|
anchorId,
|
|
13581
|
-
|
|
14234
|
+
import_types47.EdgeType.CONNECTS_TO,
|
|
13582
14235
|
"cloudflare-route",
|
|
13583
14236
|
route,
|
|
13584
14237
|
evidenceFile,
|
|
@@ -13602,7 +14255,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13602
14255
|
const result = addResourceEdge(
|
|
13603
14256
|
graph,
|
|
13604
14257
|
anchorId,
|
|
13605
|
-
|
|
14258
|
+
import_types47.EdgeType.DEPENDS_ON,
|
|
13606
14259
|
group.kind,
|
|
13607
14260
|
name,
|
|
13608
14261
|
evidenceFile,
|
|
@@ -13616,7 +14269,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13616
14269
|
const result = addResourceEdge(
|
|
13617
14270
|
graph,
|
|
13618
14271
|
anchorId,
|
|
13619
|
-
|
|
14272
|
+
import_types47.EdgeType.DEPENDS_ON,
|
|
13620
14273
|
"cloudflare-cron",
|
|
13621
14274
|
cron,
|
|
13622
14275
|
evidenceFile,
|
|
@@ -13629,7 +14282,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13629
14282
|
const result = addResourceEdge(
|
|
13630
14283
|
graph,
|
|
13631
14284
|
anchorId,
|
|
13632
|
-
|
|
14285
|
+
import_types47.EdgeType.DEPENDS_ON,
|
|
13633
14286
|
"cloudflare-env-var",
|
|
13634
14287
|
varName,
|
|
13635
14288
|
evidenceFile,
|
|
@@ -13642,15 +14295,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13642
14295
|
if (!svc.service) continue;
|
|
13643
14296
|
const target = workerIndex.get(svc.service);
|
|
13644
14297
|
if (target && target.anchorId !== anchorId) {
|
|
13645
|
-
const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId,
|
|
14298
|
+
const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types47.EdgeType.CALLS);
|
|
13646
14299
|
if (!graph.hasEdge(edgeId)) {
|
|
13647
14300
|
const edge = {
|
|
13648
14301
|
id: edgeId,
|
|
13649
14302
|
source: anchorId,
|
|
13650
14303
|
target: target.anchorId,
|
|
13651
|
-
type:
|
|
13652
|
-
provenance:
|
|
13653
|
-
confidence: (0,
|
|
14304
|
+
type: import_types47.EdgeType.CALLS,
|
|
14305
|
+
provenance: import_types47.Provenance.EXTRACTED,
|
|
14306
|
+
confidence: (0, import_types47.confidenceForExtracted)("structural"),
|
|
13654
14307
|
evidence: { file: evidenceFile, line: lineContaining2(raw, svc.service) }
|
|
13655
14308
|
};
|
|
13656
14309
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -13661,7 +14314,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13661
14314
|
const result = addResourceEdge(
|
|
13662
14315
|
graph,
|
|
13663
14316
|
anchorId,
|
|
13664
|
-
|
|
14317
|
+
import_types47.EdgeType.DEPENDS_ON,
|
|
13665
14318
|
"cloudflare-service-binding",
|
|
13666
14319
|
svc.service,
|
|
13667
14320
|
evidenceFile,
|
|
@@ -13676,24 +14329,24 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
13676
14329
|
|
|
13677
14330
|
// src/extract/infra/vercel.ts
|
|
13678
14331
|
init_cjs_shims();
|
|
13679
|
-
var
|
|
13680
|
-
var
|
|
13681
|
-
var
|
|
14332
|
+
var import_node_fs27 = require("fs");
|
|
14333
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
14334
|
+
var import_types48 = require("@neat.is/types");
|
|
13682
14335
|
var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
|
|
13683
14336
|
async function readVercelConfig(dir) {
|
|
13684
14337
|
for (const filename of VERCEL_CONFIG_FILENAMES) {
|
|
13685
|
-
const abs =
|
|
14338
|
+
const abs = import_node_path59.default.join(dir, filename);
|
|
13686
14339
|
if (!await exists2(abs)) continue;
|
|
13687
|
-
const raw = await
|
|
14340
|
+
const raw = await import_node_fs27.promises.readFile(abs, "utf8");
|
|
13688
14341
|
const config = JSON.parse(maskCommentsInSource(raw));
|
|
13689
14342
|
return { config, relFile: filename, raw };
|
|
13690
14343
|
}
|
|
13691
14344
|
return null;
|
|
13692
14345
|
}
|
|
13693
14346
|
async function readLinkedProjectName(dir) {
|
|
13694
|
-
const abs =
|
|
14347
|
+
const abs = import_node_path59.default.join(dir, ".vercel", "project.json");
|
|
13695
14348
|
if (!await exists2(abs)) return void 0;
|
|
13696
|
-
const parsed = JSON.parse(await
|
|
14349
|
+
const parsed = JSON.parse(await import_node_fs27.promises.readFile(abs, "utf8"));
|
|
13697
14350
|
return typeof parsed.projectName === "string" ? parsed.projectName : void 0;
|
|
13698
14351
|
}
|
|
13699
14352
|
function routeSource(route) {
|
|
@@ -13709,7 +14362,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
13709
14362
|
read = await readVercelConfig(service.dir);
|
|
13710
14363
|
projectName = await readLinkedProjectName(service.dir);
|
|
13711
14364
|
} catch (err) {
|
|
13712
|
-
recordExtractionError("infra vercel",
|
|
14365
|
+
recordExtractionError("infra vercel", import_node_path59.default.relative(scanPath, service.dir), err);
|
|
13713
14366
|
continue;
|
|
13714
14367
|
}
|
|
13715
14368
|
if (!read && !projectName) continue;
|
|
@@ -13725,7 +14378,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
13725
14378
|
const anchorId = service.node.id;
|
|
13726
14379
|
if (!read) continue;
|
|
13727
14380
|
const { config, relFile, raw } = read;
|
|
13728
|
-
const evidenceFile = toPosix(
|
|
14381
|
+
const evidenceFile = toPosix(import_node_path59.default.relative(scanPath, import_node_path59.default.join(service.dir, relFile)));
|
|
13729
14382
|
const add = (edgeType, kind, name) => {
|
|
13730
14383
|
if (!name) return;
|
|
13731
14384
|
const result = emitPlatformResourceEdge(
|
|
@@ -13741,12 +14394,12 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
13741
14394
|
nodesAdded += result.nodesAdded;
|
|
13742
14395
|
edgesAdded += result.edgesAdded;
|
|
13743
14396
|
};
|
|
13744
|
-
add(
|
|
13745
|
-
for (const cron of config.crons ?? []) add(
|
|
13746
|
-
for (const varName of Object.keys(config.env ?? {})) add(
|
|
13747
|
-
for (const varName of Object.keys(config.build?.env ?? {})) add(
|
|
14397
|
+
add(import_types48.EdgeType.RUNS_ON, "vercel", "vercel");
|
|
14398
|
+
for (const cron of config.crons ?? []) add(import_types48.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
|
|
14399
|
+
for (const varName of Object.keys(config.env ?? {})) add(import_types48.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
14400
|
+
for (const varName of Object.keys(config.build?.env ?? {})) add(import_types48.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
13748
14401
|
for (const route of [...config.rewrites ?? [], ...config.redirects ?? [], ...config.routes ?? []]) {
|
|
13749
|
-
add(
|
|
14402
|
+
add(import_types48.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
|
|
13750
14403
|
}
|
|
13751
14404
|
}
|
|
13752
14405
|
return { nodesAdded, edgesAdded };
|
|
@@ -13754,16 +14407,16 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
13754
14407
|
|
|
13755
14408
|
// src/extract/infra/railway.ts
|
|
13756
14409
|
init_cjs_shims();
|
|
13757
|
-
var
|
|
13758
|
-
var
|
|
14410
|
+
var import_node_fs28 = require("fs");
|
|
14411
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
13759
14412
|
var import_smol_toml3 = require("smol-toml");
|
|
13760
|
-
var
|
|
14413
|
+
var import_types49 = require("@neat.is/types");
|
|
13761
14414
|
var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
|
|
13762
14415
|
async function readRailwayConfig(dir) {
|
|
13763
14416
|
for (const filename of RAILWAY_FILENAMES) {
|
|
13764
|
-
const abs =
|
|
14417
|
+
const abs = import_node_path60.default.join(dir, filename);
|
|
13765
14418
|
if (!await exists2(abs)) continue;
|
|
13766
|
-
const raw = await
|
|
14419
|
+
const raw = await import_node_fs28.promises.readFile(abs, "utf8");
|
|
13767
14420
|
const config = filename === "railway.toml" ? (0, import_smol_toml3.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
13768
14421
|
return { config, relFile: filename, raw };
|
|
13769
14422
|
}
|
|
@@ -13777,7 +14430,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
13777
14430
|
try {
|
|
13778
14431
|
read = await readRailwayConfig(service.dir);
|
|
13779
14432
|
} catch (err) {
|
|
13780
|
-
recordExtractionError("infra railway",
|
|
14433
|
+
recordExtractionError("infra railway", import_node_path60.default.relative(scanPath, service.dir), err);
|
|
13781
14434
|
continue;
|
|
13782
14435
|
}
|
|
13783
14436
|
if (!read) continue;
|
|
@@ -13787,7 +14440,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
13787
14440
|
}
|
|
13788
14441
|
const anchorId = service.node.id;
|
|
13789
14442
|
const { config, relFile, raw } = read;
|
|
13790
|
-
const evidenceFile = toPosix(
|
|
14443
|
+
const evidenceFile = toPosix(import_node_path60.default.relative(scanPath, import_node_path60.default.join(service.dir, relFile)));
|
|
13791
14444
|
const add = (edgeType, kind, name) => {
|
|
13792
14445
|
if (!name) return;
|
|
13793
14446
|
const result = emitPlatformResourceEdge(
|
|
@@ -13803,24 +14456,24 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
13803
14456
|
nodesAdded += result.nodesAdded;
|
|
13804
14457
|
edgesAdded += result.edgesAdded;
|
|
13805
14458
|
};
|
|
13806
|
-
add(
|
|
13807
|
-
add(
|
|
13808
|
-
add(
|
|
14459
|
+
add(import_types49.EdgeType.RUNS_ON, "railway", "railway");
|
|
14460
|
+
add(import_types49.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
|
|
14461
|
+
add(import_types49.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
|
|
13809
14462
|
}
|
|
13810
14463
|
return { nodesAdded, edgesAdded };
|
|
13811
14464
|
}
|
|
13812
14465
|
|
|
13813
14466
|
// src/extract/infra/supabase.ts
|
|
13814
14467
|
init_cjs_shims();
|
|
13815
|
-
var
|
|
13816
|
-
var
|
|
14468
|
+
var import_node_fs29 = require("fs");
|
|
14469
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
13817
14470
|
var import_smol_toml4 = require("smol-toml");
|
|
13818
|
-
var
|
|
14471
|
+
var import_types50 = require("@neat.is/types");
|
|
13819
14472
|
async function readSupabaseConfig(dir) {
|
|
13820
|
-
const relFile =
|
|
13821
|
-
const abs =
|
|
14473
|
+
const relFile = import_node_path61.default.join("supabase", "config.toml");
|
|
14474
|
+
const abs = import_node_path61.default.join(dir, relFile);
|
|
13822
14475
|
if (!await exists2(abs)) return null;
|
|
13823
|
-
const raw = await
|
|
14476
|
+
const raw = await import_node_fs29.promises.readFile(abs, "utf8");
|
|
13824
14477
|
const config = (0, import_smol_toml4.parse)(raw);
|
|
13825
14478
|
return { config, relFile, raw };
|
|
13826
14479
|
}
|
|
@@ -13832,7 +14485,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
13832
14485
|
try {
|
|
13833
14486
|
read = await readSupabaseConfig(service.dir);
|
|
13834
14487
|
} catch (err) {
|
|
13835
|
-
recordExtractionError("infra supabase",
|
|
14488
|
+
recordExtractionError("infra supabase", import_node_path61.default.relative(scanPath, service.dir), err);
|
|
13836
14489
|
continue;
|
|
13837
14490
|
}
|
|
13838
14491
|
if (!read) continue;
|
|
@@ -13847,7 +14500,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
13847
14500
|
});
|
|
13848
14501
|
}
|
|
13849
14502
|
const anchorId = service.node.id;
|
|
13850
|
-
const evidenceFile = toPosix(
|
|
14503
|
+
const evidenceFile = toPosix(import_node_path61.default.relative(scanPath, import_node_path61.default.join(service.dir, relFile)));
|
|
13851
14504
|
const add = (edgeType, kind, name) => {
|
|
13852
14505
|
if (!name) return;
|
|
13853
14506
|
const result = emitPlatformResourceEdge(
|
|
@@ -13863,10 +14516,10 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
13863
14516
|
nodesAdded += result.nodesAdded;
|
|
13864
14517
|
edgesAdded += result.edgesAdded;
|
|
13865
14518
|
};
|
|
13866
|
-
add(
|
|
13867
|
-
for (const fn of Object.keys(config.functions ?? {})) add(
|
|
13868
|
-
if (config.storage) add(
|
|
13869
|
-
if (config.auth) add(
|
|
14519
|
+
add(import_types50.EdgeType.RUNS_ON, "supabase", "supabase");
|
|
14520
|
+
for (const fn of Object.keys(config.functions ?? {})) add(import_types50.EdgeType.DEPENDS_ON, "supabase-function", fn);
|
|
14521
|
+
if (config.storage) add(import_types50.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
|
|
14522
|
+
if (config.auth) add(import_types50.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
|
|
13870
14523
|
}
|
|
13871
14524
|
return { nodesAdded, edgesAdded };
|
|
13872
14525
|
}
|
|
@@ -13889,10 +14542,10 @@ async function addInfra(graph, scanPath, services) {
|
|
|
13889
14542
|
|
|
13890
14543
|
// src/extract/zod-shapes.ts
|
|
13891
14544
|
init_cjs_shims();
|
|
13892
|
-
var
|
|
14545
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
13893
14546
|
var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
|
|
13894
14547
|
var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
|
|
13895
|
-
var
|
|
14548
|
+
var import_types51 = require("@neat.is/types");
|
|
13896
14549
|
var ZOD_IMPORT_RE = /\bzod\b/;
|
|
13897
14550
|
var ZOD_OBJECTS = /* @__PURE__ */ new Set(["z", "zod"]);
|
|
13898
14551
|
function parserForExt4(ext) {
|
|
@@ -13984,7 +14637,7 @@ function topLevelSchemas(root) {
|
|
|
13984
14637
|
}
|
|
13985
14638
|
function zodShapesFromFile(file, serviceDir) {
|
|
13986
14639
|
if (!ZOD_IMPORT_RE.test(file.content)) return [];
|
|
13987
|
-
const tree = parseSource3(parserForExt4(
|
|
14640
|
+
const tree = parseSource3(parserForExt4(import_node_path62.default.extname(file.path)), file.content);
|
|
13988
14641
|
const out = [];
|
|
13989
14642
|
const seen = /* @__PURE__ */ new Set();
|
|
13990
14643
|
for (const { name, call } of topLevelSchemas(tree.rootNode)) {
|
|
@@ -13998,11 +14651,11 @@ function zodShapesFromFile(file, serviceDir) {
|
|
|
13998
14651
|
seen.add(name);
|
|
13999
14652
|
const line = call.startPosition.row + 1;
|
|
14000
14653
|
out.push({
|
|
14001
|
-
infraId: (0,
|
|
14654
|
+
infraId: (0, import_types51.infraId)("zod-schema", name),
|
|
14002
14655
|
name,
|
|
14003
14656
|
fields,
|
|
14004
14657
|
evidence: {
|
|
14005
|
-
file:
|
|
14658
|
+
file: import_node_path62.default.relative(serviceDir, file.path),
|
|
14006
14659
|
line,
|
|
14007
14660
|
snippet: snippet(file.content, line)
|
|
14008
14661
|
}
|
|
@@ -14033,7 +14686,7 @@ async function addZodShapes(graph, services) {
|
|
|
14033
14686
|
if (!graph.hasNode(shape.infraId)) {
|
|
14034
14687
|
const node = {
|
|
14035
14688
|
id: shape.infraId,
|
|
14036
|
-
type:
|
|
14689
|
+
type: import_types51.NodeType.InfraNode,
|
|
14037
14690
|
name: shape.name,
|
|
14038
14691
|
provider: "self",
|
|
14039
14692
|
kind: "zod-schema"
|
|
@@ -14043,14 +14696,14 @@ async function addZodShapes(graph, services) {
|
|
|
14043
14696
|
}
|
|
14044
14697
|
if (shape.fields.length > 0) {
|
|
14045
14698
|
const node = graph.getNodeAttributes(shape.infraId);
|
|
14046
|
-
if (node.type ===
|
|
14699
|
+
if (node.type === import_types51.NodeType.InfraNode) {
|
|
14047
14700
|
graph.replaceNodeAttributes(shape.infraId, {
|
|
14048
14701
|
...node,
|
|
14049
14702
|
columns: foldColumns(
|
|
14050
14703
|
node.columns,
|
|
14051
14704
|
shape.fields,
|
|
14052
|
-
|
|
14053
|
-
(0,
|
|
14705
|
+
import_types51.Provenance.EXTRACTED,
|
|
14706
|
+
(0, import_types51.confidenceForExtracted)("structural")
|
|
14054
14707
|
)
|
|
14055
14708
|
});
|
|
14056
14709
|
}
|
|
@@ -14064,15 +14717,15 @@ async function addZodShapes(graph, services) {
|
|
|
14064
14717
|
);
|
|
14065
14718
|
nodesAdded += n;
|
|
14066
14719
|
edgesAdded += e;
|
|
14067
|
-
const edgeId = (0,
|
|
14720
|
+
const edgeId = (0, import_types51.extractedEdgeId)(fileNodeId, shape.infraId, import_types51.EdgeType.CONTAINS);
|
|
14068
14721
|
if (!graph.hasEdge(edgeId)) {
|
|
14069
14722
|
const edge = {
|
|
14070
14723
|
id: edgeId,
|
|
14071
14724
|
source: fileNodeId,
|
|
14072
14725
|
target: shape.infraId,
|
|
14073
|
-
type:
|
|
14074
|
-
provenance:
|
|
14075
|
-
confidence: (0,
|
|
14726
|
+
type: import_types51.EdgeType.CONTAINS,
|
|
14727
|
+
provenance: import_types51.Provenance.EXTRACTED,
|
|
14728
|
+
confidence: (0, import_types51.confidenceForExtracted)("structural"),
|
|
14076
14729
|
evidence: shape.evidence
|
|
14077
14730
|
};
|
|
14078
14731
|
graph.addEdgeWithKey(edgeId, fileNodeId, shape.infraId, edge);
|
|
@@ -14086,7 +14739,7 @@ async function addZodShapes(graph, services) {
|
|
|
14086
14739
|
|
|
14087
14740
|
// src/extract/firestore-rules.ts
|
|
14088
14741
|
init_cjs_shims();
|
|
14089
|
-
var
|
|
14742
|
+
var import_types52 = require("@neat.is/types");
|
|
14090
14743
|
var FIRESTORE_COLLECTION_KIND = "firestore-collection";
|
|
14091
14744
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["write", "create", "update"]);
|
|
14092
14745
|
function stripComments(src) {
|
|
@@ -14226,7 +14879,7 @@ async function addFirestoreRules(graph, services) {
|
|
|
14226
14879
|
if (guards.size === 0) return { nodesAdded: 0, edgesAdded: 0 };
|
|
14227
14880
|
graph.forEachNode((id, attrs) => {
|
|
14228
14881
|
const node = attrs;
|
|
14229
|
-
if (node.type !==
|
|
14882
|
+
if (node.type !== import_types52.NodeType.InfraNode) return;
|
|
14230
14883
|
if (node.kind !== FIRESTORE_COLLECTION_KIND) return;
|
|
14231
14884
|
const fields = guards.get(collectionKeyFromName(node.name));
|
|
14232
14885
|
if (!fields || fields.size === 0) return;
|
|
@@ -14239,17 +14892,17 @@ async function addFirestoreRules(graph, services) {
|
|
|
14239
14892
|
}
|
|
14240
14893
|
|
|
14241
14894
|
// src/extract/index.ts
|
|
14242
|
-
var
|
|
14895
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
14243
14896
|
|
|
14244
14897
|
// src/extract/retire.ts
|
|
14245
14898
|
init_cjs_shims();
|
|
14246
|
-
var
|
|
14247
|
-
var
|
|
14248
|
-
var
|
|
14899
|
+
var import_node_fs30 = require("fs");
|
|
14900
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
14901
|
+
var import_types53 = require("@neat.is/types");
|
|
14249
14902
|
function dropOrphanedFileNodes(graph) {
|
|
14250
14903
|
const orphans = [];
|
|
14251
14904
|
graph.forEachNode((id, attrs) => {
|
|
14252
|
-
if (attrs.type !==
|
|
14905
|
+
if (attrs.type !== import_types53.NodeType.FileNode) return;
|
|
14253
14906
|
if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
|
|
14254
14907
|
orphans.push(id);
|
|
14255
14908
|
}
|
|
@@ -14262,14 +14915,14 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
14262
14915
|
const bases = [scanPath, ...serviceDirs];
|
|
14263
14916
|
graph.forEachEdge((id, attrs) => {
|
|
14264
14917
|
const edge = attrs;
|
|
14265
|
-
if (edge.provenance !==
|
|
14918
|
+
if (edge.provenance !== import_types53.Provenance.EXTRACTED) return;
|
|
14266
14919
|
const evidenceFile = edge.evidence?.file;
|
|
14267
14920
|
if (!evidenceFile) return;
|
|
14268
|
-
if (
|
|
14269
|
-
if (!(0,
|
|
14921
|
+
if (import_node_path63.default.isAbsolute(evidenceFile)) {
|
|
14922
|
+
if (!(0, import_node_fs30.existsSync)(evidenceFile)) toDrop.push(id);
|
|
14270
14923
|
return;
|
|
14271
14924
|
}
|
|
14272
|
-
const found = bases.some((base) => (0,
|
|
14925
|
+
const found = bases.some((base) => (0, import_node_fs30.existsSync)(import_node_path63.default.join(base, evidenceFile)));
|
|
14273
14926
|
if (!found) toDrop.push(id);
|
|
14274
14927
|
});
|
|
14275
14928
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -14326,7 +14979,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
14326
14979
|
}
|
|
14327
14980
|
const droppedEntries = drainDroppedExtracted();
|
|
14328
14981
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
14329
|
-
const rejectedPath =
|
|
14982
|
+
const rejectedPath = import_node_path64.default.join(import_node_path64.default.dirname(opts.errorsPath), "rejected.ndjson");
|
|
14330
14983
|
try {
|
|
14331
14984
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
14332
14985
|
} catch (err) {
|
|
@@ -14360,7 +15013,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
14360
15013
|
|
|
14361
15014
|
// src/diff.ts
|
|
14362
15015
|
init_cjs_shims();
|
|
14363
|
-
var
|
|
15016
|
+
var import_node_fs31 = require("fs");
|
|
14364
15017
|
async function loadSnapshotForDiff(target) {
|
|
14365
15018
|
if (/^https?:\/\//i.test(target)) {
|
|
14366
15019
|
const res = await fetch(target);
|
|
@@ -14369,7 +15022,7 @@ async function loadSnapshotForDiff(target) {
|
|
|
14369
15022
|
}
|
|
14370
15023
|
return await res.json();
|
|
14371
15024
|
}
|
|
14372
|
-
const raw = await
|
|
15025
|
+
const raw = await import_node_fs31.promises.readFile(target, "utf8");
|
|
14373
15026
|
return JSON.parse(raw);
|
|
14374
15027
|
}
|
|
14375
15028
|
function indexEntries(entries) {
|
|
@@ -14437,9 +15090,9 @@ function canonicalJson(value) {
|
|
|
14437
15090
|
|
|
14438
15091
|
// src/persist.ts
|
|
14439
15092
|
init_cjs_shims();
|
|
14440
|
-
var
|
|
14441
|
-
var
|
|
14442
|
-
var
|
|
15093
|
+
var import_node_fs32 = require("fs");
|
|
15094
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
15095
|
+
var import_types54 = require("@neat.is/types");
|
|
14443
15096
|
var SCHEMA_VERSION = 7;
|
|
14444
15097
|
function migrateV1ToV2(payload) {
|
|
14445
15098
|
const nodes = payload.graph.nodes;
|
|
@@ -14463,7 +15116,7 @@ function migrateV5ToV6(payload) {
|
|
|
14463
15116
|
if (Array.isArray(nodes)) {
|
|
14464
15117
|
for (const node of nodes) {
|
|
14465
15118
|
const attrs = node.attributes;
|
|
14466
|
-
if (!attrs || attrs.type !==
|
|
15119
|
+
if (!attrs || attrs.type !== import_types54.NodeType.InfraNode) continue;
|
|
14467
15120
|
if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
|
|
14468
15121
|
if (!Array.isArray(attrs.columns)) attrs.columns = [];
|
|
14469
15122
|
}
|
|
@@ -14479,12 +15132,12 @@ function migrateV2ToV3(payload) {
|
|
|
14479
15132
|
for (const edge of edges) {
|
|
14480
15133
|
const attrs = edge.attributes;
|
|
14481
15134
|
if (!attrs || attrs.provenance !== "FRONTIER") continue;
|
|
14482
|
-
attrs.provenance =
|
|
15135
|
+
attrs.provenance = import_types54.Provenance.OBSERVED;
|
|
14483
15136
|
const type = typeof attrs.type === "string" ? attrs.type : void 0;
|
|
14484
15137
|
const source = typeof attrs.source === "string" ? attrs.source : void 0;
|
|
14485
15138
|
const target = typeof attrs.target === "string" ? attrs.target : void 0;
|
|
14486
15139
|
if (type && source && target) {
|
|
14487
|
-
const newId = (0,
|
|
15140
|
+
const newId = (0, import_types54.observedEdgeId)(source, target, type);
|
|
14488
15141
|
attrs.id = newId;
|
|
14489
15142
|
if (edge.key) edge.key = newId;
|
|
14490
15143
|
}
|
|
@@ -14493,7 +15146,7 @@ function migrateV2ToV3(payload) {
|
|
|
14493
15146
|
return { ...payload, schemaVersion: 3 };
|
|
14494
15147
|
}
|
|
14495
15148
|
async function ensureDir(filePath) {
|
|
14496
|
-
await
|
|
15149
|
+
await import_node_fs32.promises.mkdir(import_node_path65.default.dirname(filePath), { recursive: true });
|
|
14497
15150
|
}
|
|
14498
15151
|
async function saveGraphToDisk(graph, outPath) {
|
|
14499
15152
|
await ensureDir(outPath);
|
|
@@ -14503,13 +15156,13 @@ async function saveGraphToDisk(graph, outPath) {
|
|
|
14503
15156
|
graph: graph.export()
|
|
14504
15157
|
};
|
|
14505
15158
|
const tmp = `${outPath}.tmp`;
|
|
14506
|
-
await
|
|
14507
|
-
await
|
|
15159
|
+
await import_node_fs32.promises.writeFile(tmp, JSON.stringify(payload), "utf8");
|
|
15160
|
+
await import_node_fs32.promises.rename(tmp, outPath);
|
|
14508
15161
|
}
|
|
14509
15162
|
async function loadGraphFromDisk(graph, outPath) {
|
|
14510
15163
|
let raw;
|
|
14511
15164
|
try {
|
|
14512
|
-
raw = await
|
|
15165
|
+
raw = await import_node_fs32.promises.readFile(outPath, "utf8");
|
|
14513
15166
|
} catch (err) {
|
|
14514
15167
|
if (err.code === "ENOENT") return;
|
|
14515
15168
|
throw err;
|
|
@@ -14583,23 +15236,23 @@ function startPersistLoop(graph, outPath, opts = {}) {
|
|
|
14583
15236
|
|
|
14584
15237
|
// src/projects.ts
|
|
14585
15238
|
init_cjs_shims();
|
|
14586
|
-
var
|
|
15239
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
14587
15240
|
function pathsForProject(project, baseDir) {
|
|
14588
15241
|
if (project === DEFAULT_PROJECT) {
|
|
14589
15242
|
return {
|
|
14590
|
-
snapshotPath:
|
|
14591
|
-
errorsPath:
|
|
14592
|
-
staleEventsPath:
|
|
14593
|
-
embeddingsCachePath:
|
|
14594
|
-
policyViolationsPath:
|
|
15243
|
+
snapshotPath: import_node_path66.default.join(baseDir, "graph.json"),
|
|
15244
|
+
errorsPath: import_node_path66.default.join(baseDir, "errors.ndjson"),
|
|
15245
|
+
staleEventsPath: import_node_path66.default.join(baseDir, "stale-events.ndjson"),
|
|
15246
|
+
embeddingsCachePath: import_node_path66.default.join(baseDir, "embeddings.json"),
|
|
15247
|
+
policyViolationsPath: import_node_path66.default.join(baseDir, "policy-violations.ndjson")
|
|
14595
15248
|
};
|
|
14596
15249
|
}
|
|
14597
15250
|
return {
|
|
14598
|
-
snapshotPath:
|
|
14599
|
-
errorsPath:
|
|
14600
|
-
staleEventsPath:
|
|
14601
|
-
embeddingsCachePath:
|
|
14602
|
-
policyViolationsPath:
|
|
15251
|
+
snapshotPath: import_node_path66.default.join(baseDir, `${project}.json`),
|
|
15252
|
+
errorsPath: import_node_path66.default.join(baseDir, `errors.${project}.ndjson`),
|
|
15253
|
+
staleEventsPath: import_node_path66.default.join(baseDir, `stale-events.${project}.ndjson`),
|
|
15254
|
+
embeddingsCachePath: import_node_path66.default.join(baseDir, `embeddings.${project}.json`),
|
|
15255
|
+
policyViolationsPath: import_node_path66.default.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
14603
15256
|
};
|
|
14604
15257
|
}
|
|
14605
15258
|
var Projects = class {
|
|
@@ -14639,20 +15292,20 @@ function parseExtraProjects(raw) {
|
|
|
14639
15292
|
|
|
14640
15293
|
// src/registry.ts
|
|
14641
15294
|
init_cjs_shims();
|
|
14642
|
-
var
|
|
15295
|
+
var import_node_fs33 = require("fs");
|
|
14643
15296
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
14644
|
-
var
|
|
14645
|
-
var
|
|
15297
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
15298
|
+
var import_types55 = require("@neat.is/types");
|
|
14646
15299
|
function neatHome() {
|
|
14647
15300
|
const override = process.env.NEAT_HOME;
|
|
14648
|
-
if (override && override.length > 0) return
|
|
14649
|
-
return
|
|
15301
|
+
if (override && override.length > 0) return import_node_path67.default.resolve(override);
|
|
15302
|
+
return import_node_path67.default.join(import_node_os3.default.homedir(), ".neat");
|
|
14650
15303
|
}
|
|
14651
15304
|
function registryPath() {
|
|
14652
|
-
return
|
|
15305
|
+
return import_node_path67.default.join(neatHome(), "projects.json");
|
|
14653
15306
|
}
|
|
14654
15307
|
function daemonsDir() {
|
|
14655
|
-
return
|
|
15308
|
+
return import_node_path67.default.join(neatHome(), "daemons");
|
|
14656
15309
|
}
|
|
14657
15310
|
function isFiniteInt(v) {
|
|
14658
15311
|
return typeof v === "number" && Number.isFinite(v);
|
|
@@ -14685,7 +15338,7 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
14685
15338
|
const dir = daemonsDir();
|
|
14686
15339
|
let names;
|
|
14687
15340
|
try {
|
|
14688
|
-
names = await
|
|
15341
|
+
names = await import_node_fs33.promises.readdir(dir);
|
|
14689
15342
|
} catch (err) {
|
|
14690
15343
|
if (err.code === "ENOENT") return [];
|
|
14691
15344
|
throw err;
|
|
@@ -14693,10 +15346,10 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
14693
15346
|
const out = [];
|
|
14694
15347
|
for (const name of names) {
|
|
14695
15348
|
if (!name.endsWith(".json")) continue;
|
|
14696
|
-
const file =
|
|
15349
|
+
const file = import_node_path67.default.join(dir, name);
|
|
14697
15350
|
let raw;
|
|
14698
15351
|
try {
|
|
14699
|
-
raw = await
|
|
15352
|
+
raw = await import_node_fs33.promises.readFile(file, "utf8");
|
|
14700
15353
|
} catch {
|
|
14701
15354
|
continue;
|
|
14702
15355
|
}
|
|
@@ -14724,7 +15377,7 @@ async function readRegistry() {
|
|
|
14724
15377
|
const file = registryPath();
|
|
14725
15378
|
let raw;
|
|
14726
15379
|
try {
|
|
14727
|
-
raw = await
|
|
15380
|
+
raw = await import_node_fs33.promises.readFile(file, "utf8");
|
|
14728
15381
|
} catch (err) {
|
|
14729
15382
|
if (err.code === "ENOENT") {
|
|
14730
15383
|
return { version: 1, projects: [] };
|
|
@@ -14732,7 +15385,7 @@ async function readRegistry() {
|
|
|
14732
15385
|
throw err;
|
|
14733
15386
|
}
|
|
14734
15387
|
const parsed = JSON.parse(raw);
|
|
14735
|
-
return
|
|
15388
|
+
return import_types55.RegistryFileSchema.parse(parsed);
|
|
14736
15389
|
}
|
|
14737
15390
|
async function getProject(name) {
|
|
14738
15391
|
const reg = await readRegistry();
|
|
@@ -14807,8 +15460,8 @@ init_auth();
|
|
|
14807
15460
|
// src/connectors-config.ts
|
|
14808
15461
|
init_cjs_shims();
|
|
14809
15462
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
14810
|
-
var
|
|
14811
|
-
var
|
|
15463
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
15464
|
+
var import_node_fs34 = require("fs");
|
|
14812
15465
|
var CONNECTORS_CONFIG_VERSION = 1;
|
|
14813
15466
|
var EnvRefUnsetError = class extends Error {
|
|
14814
15467
|
ref;
|
|
@@ -14822,17 +15475,17 @@ var EnvRefUnsetError = class extends Error {
|
|
|
14822
15475
|
};
|
|
14823
15476
|
function neatHome2() {
|
|
14824
15477
|
const override = process.env.NEAT_HOME;
|
|
14825
|
-
if (override && override.length > 0) return
|
|
14826
|
-
return
|
|
15478
|
+
if (override && override.length > 0) return import_node_path68.default.resolve(override);
|
|
15479
|
+
return import_node_path68.default.join(import_node_os4.default.homedir(), ".neat");
|
|
14827
15480
|
}
|
|
14828
15481
|
function connectorsConfigPath(home = neatHome2()) {
|
|
14829
|
-
return
|
|
15482
|
+
return import_node_path68.default.join(home, "connectors.json");
|
|
14830
15483
|
}
|
|
14831
15484
|
var MODE_MASK_LOOSER_THAN_0600 = 63;
|
|
14832
15485
|
async function warnIfModeLooserThan0600(file) {
|
|
14833
15486
|
if (process.platform === "win32") return;
|
|
14834
15487
|
try {
|
|
14835
|
-
const stat = await
|
|
15488
|
+
const stat = await import_node_fs34.promises.stat(file);
|
|
14836
15489
|
if ((stat.mode & MODE_MASK_LOOSER_THAN_0600) !== 0) {
|
|
14837
15490
|
const mode = (stat.mode & 511).toString(8).padStart(3, "0");
|
|
14838
15491
|
console.warn(
|
|
@@ -14846,7 +15499,7 @@ async function readConnectorsConfig(home = neatHome2()) {
|
|
|
14846
15499
|
const file = connectorsConfigPath(home);
|
|
14847
15500
|
let raw;
|
|
14848
15501
|
try {
|
|
14849
|
-
raw = await
|
|
15502
|
+
raw = await import_node_fs34.promises.readFile(file, "utf8");
|
|
14850
15503
|
} catch (err) {
|
|
14851
15504
|
if (err.code === "ENOENT") {
|
|
14852
15505
|
return { version: CONNECTORS_CONFIG_VERSION, connectors: [] };
|
|
@@ -15013,15 +15666,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
|
|
|
15013
15666
|
|
|
15014
15667
|
// src/connectors/index.ts
|
|
15015
15668
|
init_cjs_shims();
|
|
15016
|
-
var
|
|
15669
|
+
var import_types56 = require("@neat.is/types");
|
|
15017
15670
|
var NO_ENV = "unknown";
|
|
15018
15671
|
function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
15019
15672
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
15020
15673
|
const sites = [];
|
|
15021
15674
|
for (const edgeId of graph.inboundEdges(targetNodeId)) {
|
|
15022
15675
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
15023
|
-
if (edge.provenance !==
|
|
15024
|
-
const parsed = (0,
|
|
15676
|
+
if (edge.provenance !== import_types56.Provenance.EXTRACTED) continue;
|
|
15677
|
+
const parsed = (0, import_types56.parseFileId)(edge.source);
|
|
15025
15678
|
if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
|
|
15026
15679
|
const site = { relPath: edge.evidence.file };
|
|
15027
15680
|
if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
|
|
@@ -15032,7 +15685,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
|
15032
15685
|
function routeCallSiteFor(graph, targetNodeId) {
|
|
15033
15686
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
15034
15687
|
const attrs = graph.getNodeAttributes(targetNodeId);
|
|
15035
|
-
if (attrs.type !==
|
|
15688
|
+
if (attrs.type !== import_types56.NodeType.RouteNode || !attrs.path) return void 0;
|
|
15036
15689
|
const site = { relPath: attrs.path };
|
|
15037
15690
|
if (attrs.line !== void 0) site.line = attrs.line;
|
|
15038
15691
|
return site;
|
|
@@ -15489,10 +16142,10 @@ var SUPABASE_RPC_TARGET_KIND = "supabase-rpc";
|
|
|
15489
16142
|
// src/connectors/supabase/map.ts
|
|
15490
16143
|
var REST_RPC_PATH_RE = /^\/rest\/v1\/rpc\/([^/?]+)/;
|
|
15491
16144
|
var REST_TABLE_PATH_RE = /^\/rest\/v1\/([^/?]+)/;
|
|
15492
|
-
function targetFromRestPath(
|
|
15493
|
-
const rpcMatch = REST_RPC_PATH_RE.exec(
|
|
16145
|
+
function targetFromRestPath(path71) {
|
|
16146
|
+
const rpcMatch = REST_RPC_PATH_RE.exec(path71);
|
|
15494
16147
|
if (rpcMatch) return { targetKind: SUPABASE_RPC_TARGET_KIND, name: rpcMatch[1] };
|
|
15495
|
-
const tableMatch = REST_TABLE_PATH_RE.exec(
|
|
16148
|
+
const tableMatch = REST_TABLE_PATH_RE.exec(path71);
|
|
15496
16149
|
if (tableMatch) return { targetKind: SUPABASE_TABLE_TARGET_KIND, name: tableMatch[1] };
|
|
15497
16150
|
return null;
|
|
15498
16151
|
}
|
|
@@ -15603,23 +16256,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
|
|
|
15603
16256
|
|
|
15604
16257
|
// src/connectors/supabase/resolve.ts
|
|
15605
16258
|
init_cjs_shims();
|
|
15606
|
-
var
|
|
16259
|
+
var import_types58 = require("@neat.is/types");
|
|
15607
16260
|
function createSupabaseResolveTarget(graph, config) {
|
|
15608
16261
|
return (signal, _ctx) => {
|
|
15609
16262
|
if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
|
|
15610
16263
|
return null;
|
|
15611
16264
|
}
|
|
15612
|
-
const subResourceId = (0,
|
|
16265
|
+
const subResourceId = (0, import_types58.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
|
|
15613
16266
|
if (graph.hasNode(subResourceId)) {
|
|
15614
|
-
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType:
|
|
16267
|
+
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types58.EdgeType.CALLS };
|
|
15615
16268
|
}
|
|
15616
|
-
const bareResourceId = (0,
|
|
16269
|
+
const bareResourceId = (0, import_types58.infraId)(signal.targetKind, signal.targetName);
|
|
15617
16270
|
if (graph.hasNode(bareResourceId)) {
|
|
15618
|
-
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType:
|
|
16271
|
+
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types58.EdgeType.CALLS };
|
|
15619
16272
|
}
|
|
15620
|
-
const projectLevelId = (0,
|
|
16273
|
+
const projectLevelId = (0, import_types58.infraId)("supabase", config.nodeRef);
|
|
15621
16274
|
if (graph.hasNode(projectLevelId)) {
|
|
15622
|
-
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType:
|
|
16275
|
+
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types58.EdgeType.CALLS };
|
|
15623
16276
|
}
|
|
15624
16277
|
return null;
|
|
15625
16278
|
};
|
|
@@ -15712,7 +16365,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
|
|
|
15712
16365
|
|
|
15713
16366
|
// src/connectors/railway/index.ts
|
|
15714
16367
|
init_cjs_shims();
|
|
15715
|
-
var
|
|
16368
|
+
var import_types62 = require("@neat.is/types");
|
|
15716
16369
|
|
|
15717
16370
|
// src/connectors/railway/client.ts
|
|
15718
16371
|
init_cjs_shims();
|
|
@@ -15863,7 +16516,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
|
|
|
15863
16516
|
const out = [];
|
|
15864
16517
|
graph.forEachNode((_id, attrs) => {
|
|
15865
16518
|
const node = attrs;
|
|
15866
|
-
if (node.type !==
|
|
16519
|
+
if (node.type !== import_types62.NodeType.RouteNode) return;
|
|
15867
16520
|
const route = attrs;
|
|
15868
16521
|
if (route.service !== serviceName) return;
|
|
15869
16522
|
out.push({
|
|
@@ -15967,12 +16620,12 @@ function createRailwayResolveTarget(config) {
|
|
|
15967
16620
|
const serviceName = config.serviceNameById[config.serviceId];
|
|
15968
16621
|
if (!serviceName) return null;
|
|
15969
16622
|
if (signal.targetKind === ROUTE_TARGET_KIND) {
|
|
15970
|
-
return { targetNodeId: signal.targetName, serviceName, edgeType:
|
|
16623
|
+
return { targetNodeId: signal.targetName, serviceName, edgeType: import_types62.EdgeType.CALLS };
|
|
15971
16624
|
}
|
|
15972
16625
|
if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
|
|
15973
16626
|
const peerName = config.serviceNameById[signal.targetName];
|
|
15974
16627
|
if (!peerName) return null;
|
|
15975
|
-
return { targetNodeId: (0,
|
|
16628
|
+
return { targetNodeId: (0, import_types62.serviceId)(peerName), serviceName, edgeType: import_types62.EdgeType.CONNECTS_TO };
|
|
15976
16629
|
}
|
|
15977
16630
|
return null;
|
|
15978
16631
|
};
|
|
@@ -16096,9 +16749,9 @@ function parseFirebaseTargetName(targetName) {
|
|
|
16096
16749
|
const secondSep = rest.indexOf(FIELD_SEP);
|
|
16097
16750
|
if (secondSep === -1) return null;
|
|
16098
16751
|
const method = rest.slice(0, secondSep);
|
|
16099
|
-
const
|
|
16100
|
-
if (!resourceName || !method || !
|
|
16101
|
-
return { resourceName, method, path:
|
|
16752
|
+
const path71 = rest.slice(secondSep + 1);
|
|
16753
|
+
if (!resourceName || !method || !path71) return null;
|
|
16754
|
+
return { resourceName, method, path: path71 };
|
|
16102
16755
|
}
|
|
16103
16756
|
function resourceNameFor(type, labels) {
|
|
16104
16757
|
if (!labels) return null;
|
|
@@ -16136,14 +16789,14 @@ function mapLogEntryToSignal(entry) {
|
|
|
16136
16789
|
if (!req) return null;
|
|
16137
16790
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
16138
16791
|
const method = req.requestMethod.toUpperCase();
|
|
16139
|
-
const
|
|
16140
|
-
if (
|
|
16792
|
+
const path71 = pathFromRequestUrl(req.requestUrl);
|
|
16793
|
+
if (path71 === null) return null;
|
|
16141
16794
|
const timestamp = entry.timestamp;
|
|
16142
16795
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
16143
16796
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD2;
|
|
16144
16797
|
return {
|
|
16145
16798
|
targetKind: resourceType,
|
|
16146
|
-
targetName: packFirebaseTargetName({ resourceName, method, path:
|
|
16799
|
+
targetName: packFirebaseTargetName({ resourceName, method, path: path71 }),
|
|
16147
16800
|
callCount: 1,
|
|
16148
16801
|
errorCount: isError ? 1 : 0,
|
|
16149
16802
|
lastObservedIso: timestamp
|
|
@@ -16160,7 +16813,7 @@ function mapLogEntriesToSignals(entries) {
|
|
|
16160
16813
|
|
|
16161
16814
|
// src/connectors/firebase/resolve.ts
|
|
16162
16815
|
init_cjs_shims();
|
|
16163
|
-
var
|
|
16816
|
+
var import_types63 = require("@neat.is/types");
|
|
16164
16817
|
function neatServiceNameFor(resourceType, resourceName, serviceMap) {
|
|
16165
16818
|
switch (resourceType) {
|
|
16166
16819
|
case "cloud_function":
|
|
@@ -16175,7 +16828,7 @@ function routeEntriesFor(graph, serviceName) {
|
|
|
16175
16828
|
const entries = [];
|
|
16176
16829
|
graph.forEachNode((_id, attrs) => {
|
|
16177
16830
|
const node = attrs;
|
|
16178
|
-
if (node.type !==
|
|
16831
|
+
if (node.type !== import_types63.NodeType.RouteNode) return;
|
|
16179
16832
|
const route = attrs;
|
|
16180
16833
|
if (route.service !== serviceName) return;
|
|
16181
16834
|
entries.push({
|
|
@@ -16207,7 +16860,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
|
|
|
16207
16860
|
return {
|
|
16208
16861
|
targetNodeId: match.routeNodeId,
|
|
16209
16862
|
serviceName,
|
|
16210
|
-
edgeType:
|
|
16863
|
+
edgeType: import_types63.EdgeType.CALLS
|
|
16211
16864
|
};
|
|
16212
16865
|
};
|
|
16213
16866
|
}
|
|
@@ -16234,7 +16887,7 @@ init_cjs_shims();
|
|
|
16234
16887
|
|
|
16235
16888
|
// src/connectors/cloudflare/connector.ts
|
|
16236
16889
|
init_cjs_shims();
|
|
16237
|
-
var
|
|
16890
|
+
var import_types65 = require("@neat.is/types");
|
|
16238
16891
|
|
|
16239
16892
|
// src/connectors/cloudflare/client.ts
|
|
16240
16893
|
init_cjs_shims();
|
|
@@ -16350,7 +17003,7 @@ function mapEventToSignal(event) {
|
|
|
16350
17003
|
if (Number.isNaN(observedAt.getTime())) return null;
|
|
16351
17004
|
const statusCode = metadata?.statusCode;
|
|
16352
17005
|
const isError = typeof statusCode === "number" && statusCode >= ERROR_STATUS_THRESHOLD3;
|
|
16353
|
-
const
|
|
17006
|
+
const path71 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
|
|
16354
17007
|
return {
|
|
16355
17008
|
targetKind: CLOUDFLARE_TARGET_KIND,
|
|
16356
17009
|
targetName: scriptName,
|
|
@@ -16358,7 +17011,7 @@ function mapEventToSignal(event) {
|
|
|
16358
17011
|
errorCount: isError ? 1 : 0,
|
|
16359
17012
|
lastObservedIso: observedAt.toISOString(),
|
|
16360
17013
|
method,
|
|
16361
|
-
...
|
|
17014
|
+
...path71 ? { path: path71 } : {},
|
|
16362
17015
|
...typeof statusCode === "number" ? { statusCode } : {},
|
|
16363
17016
|
...typeof metadata?.duration === "number" ? { duration: metadata.duration } : {}
|
|
16364
17017
|
};
|
|
@@ -16398,19 +17051,19 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
16398
17051
|
graph.forEachNode((id, attrs) => {
|
|
16399
17052
|
if (found) return;
|
|
16400
17053
|
const a = attrs;
|
|
16401
|
-
if (a.type ===
|
|
17054
|
+
if (a.type === import_types65.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
|
|
16402
17055
|
found = id;
|
|
16403
17056
|
}
|
|
16404
17057
|
});
|
|
16405
17058
|
return found;
|
|
16406
17059
|
}
|
|
16407
|
-
function findMatchingRouteNode(graph, serviceName, method,
|
|
16408
|
-
const normalizedPath = normalizePathTemplate(
|
|
17060
|
+
function findMatchingRouteNode(graph, serviceName, method, path71) {
|
|
17061
|
+
const normalizedPath = normalizePathTemplate(path71);
|
|
16409
17062
|
let found = null;
|
|
16410
17063
|
graph.forEachNode((id, attrs) => {
|
|
16411
17064
|
if (found) return;
|
|
16412
17065
|
const a = attrs;
|
|
16413
|
-
if (a.type !==
|
|
17066
|
+
if (a.type !== import_types65.NodeType.RouteNode || a.service !== serviceName) return;
|
|
16414
17067
|
if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
|
|
16415
17068
|
const routeMethod = (a.method ?? "").toUpperCase();
|
|
16416
17069
|
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
@@ -16422,18 +17075,18 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
16422
17075
|
return (signal) => {
|
|
16423
17076
|
if (signal.targetKind !== CLOUDFLARE_TARGET_KIND) return null;
|
|
16424
17077
|
const scriptName = signal.targetName;
|
|
16425
|
-
const { method, path:
|
|
17078
|
+
const { method, path: path71 } = signal;
|
|
16426
17079
|
const resolveRouteGrain = (serviceName, wholeFileId) => {
|
|
16427
|
-
if (!method || !
|
|
16428
|
-
return findMatchingRouteNode(graph, serviceName, method,
|
|
17080
|
+
if (!method || !path71) return wholeFileId;
|
|
17081
|
+
return findMatchingRouteNode(graph, serviceName, method, path71) ?? wholeFileId;
|
|
16429
17082
|
};
|
|
16430
17083
|
const mapping = config.workers?.[scriptName];
|
|
16431
17084
|
if (mapping) {
|
|
16432
|
-
const wholeFileId = (0,
|
|
17085
|
+
const wholeFileId = (0, import_types65.fileId)(mapping.service, mapping.entryFile);
|
|
16433
17086
|
return {
|
|
16434
17087
|
targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
|
|
16435
17088
|
serviceName: mapping.service,
|
|
16436
|
-
edgeType:
|
|
17089
|
+
edgeType: import_types65.EdgeType.CALLS
|
|
16437
17090
|
};
|
|
16438
17091
|
}
|
|
16439
17092
|
const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
|
|
@@ -16442,13 +17095,13 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
16442
17095
|
return {
|
|
16443
17096
|
targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
|
|
16444
17097
|
serviceName: fileNode.service,
|
|
16445
|
-
edgeType:
|
|
17098
|
+
edgeType: import_types65.EdgeType.CALLS
|
|
16446
17099
|
};
|
|
16447
17100
|
}
|
|
16448
17101
|
return {
|
|
16449
|
-
targetNodeId: (0,
|
|
17102
|
+
targetNodeId: (0, import_types65.infraId)("cloudflare-worker", scriptName),
|
|
16450
17103
|
serviceName: scriptName,
|
|
16451
|
-
edgeType:
|
|
17104
|
+
edgeType: import_types65.EdgeType.CALLS,
|
|
16452
17105
|
ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
|
|
16453
17106
|
};
|
|
16454
17107
|
};
|
|
@@ -16644,14 +17297,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
|
|
|
16644
17297
|
|
|
16645
17298
|
// src/connectors/neon/resolve.ts
|
|
16646
17299
|
init_cjs_shims();
|
|
16647
|
-
var
|
|
17300
|
+
var import_types69 = require("@neat.is/types");
|
|
16648
17301
|
function createNeonResolveTarget(config) {
|
|
16649
17302
|
return (signal) => {
|
|
16650
17303
|
if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
16651
17304
|
return {
|
|
16652
|
-
targetNodeId: (0,
|
|
17305
|
+
targetNodeId: (0, import_types69.infraId)("sql-table", signal.targetName),
|
|
16653
17306
|
serviceName: config.serviceName,
|
|
16654
|
-
edgeType:
|
|
17307
|
+
edgeType: import_types69.EdgeType.CALLS,
|
|
16655
17308
|
ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
|
|
16656
17309
|
};
|
|
16657
17310
|
};
|
|
@@ -16777,9 +17430,9 @@ function parseCloudRunTargetName(targetName) {
|
|
|
16777
17430
|
const secondSep = rest.indexOf(FIELD_SEP2);
|
|
16778
17431
|
if (secondSep === -1) return null;
|
|
16779
17432
|
const method = rest.slice(0, secondSep);
|
|
16780
|
-
const
|
|
16781
|
-
if (!serviceName || !method || !
|
|
16782
|
-
return { serviceName, method, path:
|
|
17433
|
+
const path71 = rest.slice(secondSep + 1);
|
|
17434
|
+
if (!serviceName || !method || !path71) return null;
|
|
17435
|
+
return { serviceName, method, path: path71 };
|
|
16783
17436
|
}
|
|
16784
17437
|
|
|
16785
17438
|
// src/connectors/cloud-run/map.ts
|
|
@@ -16808,14 +17461,14 @@ function mapLogEntryToSignal2(entry) {
|
|
|
16808
17461
|
if (!req) return null;
|
|
16809
17462
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
16810
17463
|
const method = req.requestMethod.toUpperCase();
|
|
16811
|
-
const
|
|
16812
|
-
if (
|
|
17464
|
+
const path71 = pathFromRequestUrl2(req.requestUrl);
|
|
17465
|
+
if (path71 === null) return null;
|
|
16813
17466
|
const timestamp = entry.timestamp;
|
|
16814
17467
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
16815
17468
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD4;
|
|
16816
17469
|
return {
|
|
16817
17470
|
targetKind: CLOUD_RUN_TARGET_KIND,
|
|
16818
|
-
targetName: packCloudRunTargetName({ serviceName, method, path:
|
|
17471
|
+
targetName: packCloudRunTargetName({ serviceName, method, path: path71 }),
|
|
16819
17472
|
callCount: 1,
|
|
16820
17473
|
errorCount: isError ? 1 : 0,
|
|
16821
17474
|
lastObservedIso: timestamp
|
|
@@ -16832,14 +17485,14 @@ function mapLogEntriesToSignals2(entries) {
|
|
|
16832
17485
|
|
|
16833
17486
|
// src/connectors/cloud-run/resolve.ts
|
|
16834
17487
|
init_cjs_shims();
|
|
16835
|
-
var
|
|
17488
|
+
var import_types73 = require("@neat.is/types");
|
|
16836
17489
|
var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
|
|
16837
17490
|
function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
|
|
16838
17491
|
let found = null;
|
|
16839
17492
|
graph.forEachNode((_id, attrs) => {
|
|
16840
17493
|
if (found) return;
|
|
16841
17494
|
const node = attrs;
|
|
16842
|
-
if (node.type !==
|
|
17495
|
+
if (node.type !== import_types73.NodeType.RouteNode) return;
|
|
16843
17496
|
const route = attrs;
|
|
16844
17497
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
16845
17498
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -16854,23 +17507,23 @@ function createCloudRunResolveTarget(graph, config) {
|
|
|
16854
17507
|
if (signal.targetKind !== CLOUD_RUN_TARGET_KIND) return null;
|
|
16855
17508
|
const identity = parseCloudRunTargetName(signal.targetName);
|
|
16856
17509
|
if (!identity) return null;
|
|
16857
|
-
const { serviceName: gcpServiceName, method, path:
|
|
17510
|
+
const { serviceName: gcpServiceName, method, path: path71 } = identity;
|
|
16858
17511
|
const mappedService = config.serviceMap?.[gcpServiceName];
|
|
16859
17512
|
if (mappedService) {
|
|
16860
17513
|
const routeNodeId = findMatchingRouteNode2(
|
|
16861
17514
|
graph,
|
|
16862
17515
|
mappedService,
|
|
16863
17516
|
method,
|
|
16864
|
-
normalizePathTemplate(
|
|
17517
|
+
normalizePathTemplate(path71)
|
|
16865
17518
|
);
|
|
16866
17519
|
if (routeNodeId) {
|
|
16867
|
-
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType:
|
|
17520
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types73.EdgeType.CALLS };
|
|
16868
17521
|
}
|
|
16869
17522
|
}
|
|
16870
17523
|
return {
|
|
16871
|
-
targetNodeId: (0,
|
|
17524
|
+
targetNodeId: (0, import_types73.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
|
|
16872
17525
|
serviceName: mappedService ?? gcpServiceName,
|
|
16873
|
-
edgeType:
|
|
17526
|
+
edgeType: import_types73.EdgeType.CALLS,
|
|
16874
17527
|
ensureInfraNode: {
|
|
16875
17528
|
kind: CLOUD_RUN_SERVICE_INFRA_KIND,
|
|
16876
17529
|
name: gcpServiceName,
|
|
@@ -16911,7 +17564,7 @@ function createCloudRunConnector(graph, config = {}) {
|
|
|
16911
17564
|
|
|
16912
17565
|
// src/connectors/render/index.ts
|
|
16913
17566
|
init_cjs_shims();
|
|
16914
|
-
var
|
|
17567
|
+
var import_types76 = require("@neat.is/types");
|
|
16915
17568
|
|
|
16916
17569
|
// src/connectors/render/types.ts
|
|
16917
17570
|
init_cjs_shims();
|
|
@@ -16989,7 +17642,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
16989
17642
|
const out = [];
|
|
16990
17643
|
graph.forEachNode((_id, attrs) => {
|
|
16991
17644
|
const node = attrs;
|
|
16992
|
-
if (node.type !==
|
|
17645
|
+
if (node.type !== import_types76.NodeType.RouteNode) return;
|
|
16993
17646
|
const route = attrs;
|
|
16994
17647
|
if (route.service !== serviceName) return;
|
|
16995
17648
|
out.push({
|
|
@@ -17074,7 +17727,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
|
|
|
17074
17727
|
function createRenderResolveTarget(config) {
|
|
17075
17728
|
return (signal) => {
|
|
17076
17729
|
if (signal.targetKind === ROUTE_TARGET_KIND2) {
|
|
17077
|
-
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType:
|
|
17730
|
+
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types76.EdgeType.CALLS };
|
|
17078
17731
|
}
|
|
17079
17732
|
return null;
|
|
17080
17733
|
};
|
|
@@ -17212,21 +17865,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
|
|
|
17212
17865
|
|
|
17213
17866
|
// src/connectors/planetscale/resolve.ts
|
|
17214
17867
|
init_cjs_shims();
|
|
17215
|
-
var
|
|
17868
|
+
var import_types80 = require("@neat.is/types");
|
|
17216
17869
|
var PLANETSCALE_DATABASE_KIND = "planetscale-database";
|
|
17217
17870
|
function createPlanetscaleResolveTarget(graph, config) {
|
|
17218
17871
|
const databaseName = `${config.organization}/${config.database}`;
|
|
17219
17872
|
return (signal, _ctx) => {
|
|
17220
17873
|
if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
17221
|
-
const tableId = (0,
|
|
17874
|
+
const tableId = (0, import_types80.infraId)("sql-table", signal.targetName);
|
|
17222
17875
|
if (graph.hasNode(tableId)) {
|
|
17223
|
-
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType:
|
|
17876
|
+
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types80.EdgeType.CALLS };
|
|
17224
17877
|
}
|
|
17225
|
-
const providerId = (0,
|
|
17878
|
+
const providerId = (0, import_types80.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
|
|
17226
17879
|
return {
|
|
17227
17880
|
targetNodeId: providerId,
|
|
17228
17881
|
serviceName: config.serviceName,
|
|
17229
|
-
edgeType:
|
|
17882
|
+
edgeType: import_types80.EdgeType.CALLS,
|
|
17230
17883
|
ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
|
|
17231
17884
|
};
|
|
17232
17885
|
};
|
|
@@ -17491,7 +18144,7 @@ function mapBuildsToSignals(builds, serviceName) {
|
|
|
17491
18144
|
|
|
17492
18145
|
// src/connectors/eas/resolve.ts
|
|
17493
18146
|
init_cjs_shims();
|
|
17494
|
-
var
|
|
18147
|
+
var import_types85 = require("@neat.is/types");
|
|
17495
18148
|
var NO_ENV2 = "unknown";
|
|
17496
18149
|
var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
|
|
17497
18150
|
var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
|
|
@@ -17507,8 +18160,8 @@ function configBasenamesForPhase(phase) {
|
|
|
17507
18160
|
function configNodeService(graph, configNodeId) {
|
|
17508
18161
|
for (const edgeId of graph.inboundEdges(configNodeId)) {
|
|
17509
18162
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
17510
|
-
if (edge.type !==
|
|
17511
|
-
const parsed = (0,
|
|
18163
|
+
if (edge.type !== import_types85.EdgeType.CONFIGURED_BY) continue;
|
|
18164
|
+
const parsed = (0, import_types85.parseFileId)(edge.source);
|
|
17512
18165
|
if (parsed) return parsed.service;
|
|
17513
18166
|
}
|
|
17514
18167
|
return null;
|
|
@@ -17519,7 +18172,7 @@ function findConfigNode(graph, basenames, serviceName) {
|
|
|
17519
18172
|
graph.forEachNode((id, attrs) => {
|
|
17520
18173
|
if (scoped) return;
|
|
17521
18174
|
const node = attrs;
|
|
17522
|
-
if (node.type !==
|
|
18175
|
+
if (node.type !== import_types85.NodeType.ConfigNode) return;
|
|
17523
18176
|
if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
|
|
17524
18177
|
if (anyMatch === null) anyMatch = id;
|
|
17525
18178
|
if (configNodeService(graph, id) === serviceName) scoped = id;
|
|
@@ -17536,13 +18189,13 @@ function createEasResolveTarget(graph) {
|
|
|
17536
18189
|
if (basenames.length > 0) {
|
|
17537
18190
|
const configNodeId = findConfigNode(graph, basenames, serviceName);
|
|
17538
18191
|
if (configNodeId) {
|
|
17539
|
-
return { targetNodeId: configNodeId, serviceName, edgeType:
|
|
18192
|
+
return { targetNodeId: configNodeId, serviceName, edgeType: import_types85.EdgeType.CALLS };
|
|
17540
18193
|
}
|
|
17541
18194
|
}
|
|
17542
18195
|
return {
|
|
17543
18196
|
targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
|
|
17544
18197
|
serviceName,
|
|
17545
|
-
edgeType:
|
|
18198
|
+
edgeType: import_types85.EdgeType.CALLS
|
|
17546
18199
|
};
|
|
17547
18200
|
};
|
|
17548
18201
|
}
|
|
@@ -18221,11 +18874,11 @@ function registerRoutes(scope, ctx) {
|
|
|
18221
18874
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
18222
18875
|
const parsed = [];
|
|
18223
18876
|
for (const c of candidates) {
|
|
18224
|
-
const r =
|
|
18877
|
+
const r = import_types88.DivergenceTypeSchema.safeParse(c);
|
|
18225
18878
|
if (!r.success) {
|
|
18226
18879
|
return reply.code(400).send({
|
|
18227
18880
|
error: `unknown divergence type "${c}"`,
|
|
18228
|
-
allowed:
|
|
18881
|
+
allowed: import_types88.DivergenceTypeSchema.options
|
|
18229
18882
|
});
|
|
18230
18883
|
}
|
|
18231
18884
|
parsed.push(r.data);
|
|
@@ -18567,7 +19220,7 @@ function registerRoutes(scope, ctx) {
|
|
|
18567
19220
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
18568
19221
|
let violations = await log.readAll();
|
|
18569
19222
|
if (req.query.severity) {
|
|
18570
|
-
const sev =
|
|
19223
|
+
const sev = import_types88.PolicySeveritySchema.safeParse(req.query.severity);
|
|
18571
19224
|
if (!sev.success) {
|
|
18572
19225
|
return reply.code(400).send({
|
|
18573
19226
|
error: "invalid severity",
|
|
@@ -18606,7 +19259,7 @@ function registerRoutes(scope, ctx) {
|
|
|
18606
19259
|
scope.post("/policies/check", async (req, reply) => {
|
|
18607
19260
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
18608
19261
|
if (!proj) return;
|
|
18609
|
-
const parsed =
|
|
19262
|
+
const parsed = import_types88.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
18610
19263
|
if (!parsed.success) {
|
|
18611
19264
|
return reply.code(400).send({
|
|
18612
19265
|
error: "invalid /policies/check body",
|
|
@@ -18927,8 +19580,8 @@ init_otel_grpc();
|
|
|
18927
19580
|
|
|
18928
19581
|
// src/search.ts
|
|
18929
19582
|
init_cjs_shims();
|
|
18930
|
-
var
|
|
18931
|
-
var
|
|
19583
|
+
var import_node_fs35 = require("fs");
|
|
19584
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
18932
19585
|
var import_node_crypto4 = require("crypto");
|
|
18933
19586
|
var DEFAULT_LIMIT = 10;
|
|
18934
19587
|
var NOMIC_DIM = 768;
|
|
@@ -19082,7 +19735,7 @@ async function pickEmbedder() {
|
|
|
19082
19735
|
}
|
|
19083
19736
|
async function readCache(cachePath) {
|
|
19084
19737
|
try {
|
|
19085
|
-
const raw = await
|
|
19738
|
+
const raw = await import_node_fs35.promises.readFile(cachePath, "utf8");
|
|
19086
19739
|
const parsed = JSON.parse(raw);
|
|
19087
19740
|
if (parsed.version !== 1) return null;
|
|
19088
19741
|
return parsed;
|
|
@@ -19091,8 +19744,8 @@ async function readCache(cachePath) {
|
|
|
19091
19744
|
}
|
|
19092
19745
|
}
|
|
19093
19746
|
async function writeCache(cachePath, cache) {
|
|
19094
|
-
await
|
|
19095
|
-
await
|
|
19747
|
+
await import_node_fs35.promises.mkdir(import_node_path69.default.dirname(cachePath), { recursive: true });
|
|
19748
|
+
await import_node_fs35.promises.writeFile(cachePath, JSON.stringify(cache));
|
|
19096
19749
|
}
|
|
19097
19750
|
var VectorIndex = class {
|
|
19098
19751
|
constructor(embedder, cachePath) {
|
|
@@ -19306,14 +19959,14 @@ async function bootProject(registry, name, scanPath, baseDir) {
|
|
|
19306
19959
|
async function main() {
|
|
19307
19960
|
const baseDirEnv = process.env.NEAT_OUT_DIR;
|
|
19308
19961
|
const legacyOutPath = process.env.NEAT_OUT_PATH;
|
|
19309
|
-
const baseDir = baseDirEnv ?
|
|
19310
|
-
const defaultScanPath =
|
|
19962
|
+
const baseDir = baseDirEnv ? import_node_path70.default.resolve(baseDirEnv) : legacyOutPath ? import_node_path70.default.resolve(import_node_path70.default.dirname(legacyOutPath)) : import_node_path70.default.resolve("./neat-out");
|
|
19963
|
+
const defaultScanPath = import_node_path70.default.resolve(process.env.NEAT_SCAN_PATH ?? "./demo");
|
|
19311
19964
|
const registry = new Projects();
|
|
19312
19965
|
await bootProject(registry, DEFAULT_PROJECT, defaultScanPath, baseDir);
|
|
19313
19966
|
for (const name of parseExtraProjects(process.env.NEAT_PROJECTS)) {
|
|
19314
19967
|
const envKey = `NEAT_PROJECT_SCAN_PATH_${name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`;
|
|
19315
19968
|
const projectScan = process.env[envKey];
|
|
19316
|
-
await bootProject(registry, name, projectScan ?
|
|
19969
|
+
await bootProject(registry, name, projectScan ? import_node_path70.default.resolve(projectScan) : void 0, baseDir);
|
|
19317
19970
|
}
|
|
19318
19971
|
const host = process.env.HOST ?? "0.0.0.0";
|
|
19319
19972
|
const port = Number(process.env.PORT ?? 8080);
|