@neat.is/core 0.8.2-dev.20260818 → 0.9.0
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-T4UGEMWN.js → chunk-RDLDSIEY.js} +958 -494
- package/dist/chunk-RDLDSIEY.js.map +1 -0
- package/dist/{chunk-WLCHTXO3.js → chunk-WMYVJXUF.js} +2 -2
- package/dist/cli.cjs +1538 -1071
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +1222 -755
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +1235 -768
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +1124 -657
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +5 -2
- package/dist/chunk-T4UGEMWN.js.map +0 -1
- /package/dist/{chunk-WLCHTXO3.js.map → chunk-WMYVJXUF.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 path74 = (req.url.split("?")[0] ?? "").replace(/\/+$/, "");
|
|
63
|
+
if (exactUnauthPaths.has(path74) || PROJECT_SCOPED_UNAUTH_PATTERN.test(path74)) {
|
|
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_path53.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
196
|
+
return import_node_path53.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_path53, 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_path53 = __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 path74 = q === -1 ? v : v.slice(0, q);
|
|
417
|
+
if (path74.length > 0) return path74;
|
|
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_path54.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
480
|
+
const protoRoot = import_node_path54.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_path54.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_path54, 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_path54 = __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_path73 = __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_types91 = 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", ".cs", ".java"]);
|
|
2018
|
+
var SERVICE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs", ".ts", ".tsx", ".py", ".go", ".rb", ".php", ".cs", ".java", ".kt", ".rs", ".cpp", ".cc", ".cxx", ".c++", ".hpp", ".hh", ".hxx", ".h++"]);
|
|
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([
|
|
@@ -2284,7 +2284,8 @@ function buildServiceHostIndex(services) {
|
|
|
2284
2284
|
}
|
|
2285
2285
|
return { knownHosts, hostToNodeId };
|
|
2286
2286
|
}
|
|
2287
|
-
async function walkSourceFiles(dir) {
|
|
2287
|
+
async function walkSourceFiles(dir, excludeDirs = []) {
|
|
2288
|
+
const excluded = new Set(excludeDirs.map((d) => import_node_path7.default.resolve(d)));
|
|
2288
2289
|
const out = [];
|
|
2289
2290
|
async function walk9(current) {
|
|
2290
2291
|
const entries = await import_node_fs7.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
@@ -2292,6 +2293,7 @@ async function walkSourceFiles(dir) {
|
|
|
2292
2293
|
const full = import_node_path7.default.join(current, entry.name);
|
|
2293
2294
|
if (entry.isDirectory()) {
|
|
2294
2295
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
2296
|
+
if (excluded.has(import_node_path7.default.resolve(full))) continue;
|
|
2295
2297
|
if (await isPythonVenvDir(full)) continue;
|
|
2296
2298
|
await walk9(full);
|
|
2297
2299
|
} else if (entry.isFile() && SERVICE_FILE_EXTENSIONS.has(import_node_path7.default.extname(entry.name)) && // Skip NEAT's own generated `otel-init.*` bootstrap — extracting it
|
|
@@ -2304,8 +2306,8 @@ async function walkSourceFiles(dir) {
|
|
|
2304
2306
|
await walk9(dir);
|
|
2305
2307
|
return out;
|
|
2306
2308
|
}
|
|
2307
|
-
async function loadSourceFiles(dir) {
|
|
2308
|
-
const paths = await walkSourceFiles(dir);
|
|
2309
|
+
async function loadSourceFiles(dir, excludeDirs = []) {
|
|
2310
|
+
const paths = await walkSourceFiles(dir, excludeDirs);
|
|
2309
2311
|
const out = [];
|
|
2310
2312
|
for (const p of paths) {
|
|
2311
2313
|
try {
|
|
@@ -2342,6 +2344,19 @@ function languageForPath(relPath) {
|
|
|
2342
2344
|
return "csharp";
|
|
2343
2345
|
case ".java":
|
|
2344
2346
|
return "java";
|
|
2347
|
+
case ".kt":
|
|
2348
|
+
return "kotlin";
|
|
2349
|
+
case ".rs":
|
|
2350
|
+
return "rust";
|
|
2351
|
+
case ".cpp":
|
|
2352
|
+
case ".cc":
|
|
2353
|
+
case ".cxx":
|
|
2354
|
+
case ".c++":
|
|
2355
|
+
case ".hpp":
|
|
2356
|
+
case ".hh":
|
|
2357
|
+
case ".hxx":
|
|
2358
|
+
case ".h++":
|
|
2359
|
+
return "cpp";
|
|
2345
2360
|
case ".ts":
|
|
2346
2361
|
case ".tsx":
|
|
2347
2362
|
return "typescript";
|
|
@@ -2675,6 +2690,7 @@ async function resolveGoImport(specifier, modulePath, serviceDir) {
|
|
|
2675
2690
|
function emitImportEdge(graph, serviceName, importerFileId, importerRelPath, importeeRelPath, line, snippet2) {
|
|
2676
2691
|
const importeeFileId = (0, import_types5.fileId)(serviceName, importeeRelPath);
|
|
2677
2692
|
if (!graph.hasNode(importeeFileId)) return 0;
|
|
2693
|
+
if (importerFileId === importeeFileId) return 0;
|
|
2678
2694
|
const edgeId = (0, import_types5.extractedEdgeId)(importerFileId, importeeFileId, import_types5.EdgeType.IMPORTS);
|
|
2679
2695
|
if (graph.hasEdge(edgeId)) return 0;
|
|
2680
2696
|
const edge = {
|
|
@@ -2696,7 +2712,7 @@ async function addImports(graph, services) {
|
|
|
2696
2712
|
let edgesAdded = 0;
|
|
2697
2713
|
for (const service of services) {
|
|
2698
2714
|
const tsPaths = await loadTsPathConfig(service.dir);
|
|
2699
|
-
const files = await loadSourceFiles(service.dir);
|
|
2715
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
2700
2716
|
for (const file of files) {
|
|
2701
2717
|
if (isTestPath(file.path)) continue;
|
|
2702
2718
|
const relFile = toPosix(import_node_path8.default.relative(service.dir, file.path));
|
|
@@ -2878,8 +2894,8 @@ function chiRoutesFromSource(source, parser) {
|
|
|
2878
2894
|
chiWalk(tree.rootNode, "", out);
|
|
2879
2895
|
return out;
|
|
2880
2896
|
}
|
|
2881
|
-
function stripChiRegex(
|
|
2882
|
-
return
|
|
2897
|
+
function stripChiRegex(path74) {
|
|
2898
|
+
return path74.replace(/\{([^{}:]+):[^{}]*\}/g, "{$1}");
|
|
2883
2899
|
}
|
|
2884
2900
|
function chiWalk(node, prefix, out) {
|
|
2885
2901
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
@@ -3551,9 +3567,9 @@ function rubyRocketRoute(args) {
|
|
|
3551
3567
|
if (!pair || pair.type !== "pair") continue;
|
|
3552
3568
|
const k = pair.childForFieldName("key");
|
|
3553
3569
|
if (k?.type !== "string") continue;
|
|
3554
|
-
const
|
|
3555
|
-
if (
|
|
3556
|
-
return { path:
|
|
3570
|
+
const path74 = rubyLiteral(k);
|
|
3571
|
+
if (path74 === null) continue;
|
|
3572
|
+
return { path: path74, target: rubyLiteral(pair.childForFieldName("value")) };
|
|
3557
3573
|
}
|
|
3558
3574
|
return null;
|
|
3559
3575
|
}
|
|
@@ -4238,7 +4254,7 @@ async function addRoutes(graph, services) {
|
|
|
4238
4254
|
const hasLaravel = deps["laravel/framework"] !== void 0;
|
|
4239
4255
|
if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasNestjs && !hasFastapi && !hasFlask && !hasDjango && !hasGin && !hasEcho && !hasFiber && !hasChi && !isGoService && !hasRails && !hasLaravel)
|
|
4240
4256
|
continue;
|
|
4241
|
-
const files = await loadSourceFiles(service.dir);
|
|
4257
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
4242
4258
|
const mountPrefixes = hasExpress ? await expressMountPrefixes(files, service.dir, await loadTsPathConfig(service.dir)) : /* @__PURE__ */ new Map();
|
|
4243
4259
|
for (const file of files) {
|
|
4244
4260
|
if (isTestPath(file.path)) continue;
|
|
@@ -5596,29 +5612,29 @@ function promoteFrontierNodes(graph, opts = {}) {
|
|
|
5596
5612
|
toPromote.push({ frontierId: id, serviceId: target });
|
|
5597
5613
|
});
|
|
5598
5614
|
let promoted = 0;
|
|
5599
|
-
for (const { frontierId: frontierId2, serviceId:
|
|
5615
|
+
for (const { frontierId: frontierId2, serviceId: serviceId15 } of toPromote) {
|
|
5600
5616
|
if (opts.policies && opts.policies.length > 0 && opts.policyCtx) {
|
|
5601
5617
|
const gate = canPromoteFrontier(graph, frontierId2, opts.policies, opts.policyCtx);
|
|
5602
5618
|
if (!gate.allowed) {
|
|
5603
5619
|
continue;
|
|
5604
5620
|
}
|
|
5605
5621
|
}
|
|
5606
|
-
rewireFrontierEdges(graph, frontierId2,
|
|
5622
|
+
rewireFrontierEdges(graph, frontierId2, serviceId15);
|
|
5607
5623
|
graph.dropNode(frontierId2);
|
|
5608
5624
|
promoted++;
|
|
5609
5625
|
}
|
|
5610
5626
|
return promoted;
|
|
5611
5627
|
}
|
|
5612
|
-
function rewireFrontierEdges(graph, frontierId2,
|
|
5628
|
+
function rewireFrontierEdges(graph, frontierId2, serviceId15) {
|
|
5613
5629
|
const inbound = [...graph.inboundEdges(frontierId2)];
|
|
5614
5630
|
const outbound = [...graph.outboundEdges(frontierId2)];
|
|
5615
5631
|
for (const edgeId of inbound) {
|
|
5616
5632
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
5617
|
-
rebuildEdge(graph, edge, edge.source,
|
|
5633
|
+
rebuildEdge(graph, edge, edge.source, serviceId15, edgeId);
|
|
5618
5634
|
}
|
|
5619
5635
|
for (const edgeId of outbound) {
|
|
5620
5636
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
5621
|
-
rebuildEdge(graph, edge,
|
|
5637
|
+
rebuildEdge(graph, edge, serviceId15, edge.target, edgeId);
|
|
5622
5638
|
}
|
|
5623
5639
|
}
|
|
5624
5640
|
function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
|
|
@@ -5937,19 +5953,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
5937
5953
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
5938
5954
|
let best = { path: [start], edges: [] };
|
|
5939
5955
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
5940
|
-
function step(node,
|
|
5941
|
-
if (
|
|
5942
|
-
best = { path: [...
|
|
5956
|
+
function step(node, path74, edges) {
|
|
5957
|
+
if (path74.length > best.path.length) {
|
|
5958
|
+
best = { path: [...path74], edges: [...edges] };
|
|
5943
5959
|
}
|
|
5944
|
-
if (
|
|
5960
|
+
if (path74.length - 1 >= maxDepth) return;
|
|
5945
5961
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
5946
5962
|
for (const [srcId, edge] of incoming) {
|
|
5947
5963
|
if (visited.has(srcId)) continue;
|
|
5948
5964
|
visited.add(srcId);
|
|
5949
|
-
|
|
5965
|
+
path74.push(srcId);
|
|
5950
5966
|
edges.push(edge);
|
|
5951
|
-
step(srcId,
|
|
5952
|
-
|
|
5967
|
+
step(srcId, path74, edges);
|
|
5968
|
+
path74.pop();
|
|
5953
5969
|
edges.pop();
|
|
5954
5970
|
visited.delete(srcId);
|
|
5955
5971
|
}
|
|
@@ -5964,7 +5980,7 @@ function databaseRootCauseShape(graph, origin, walk9) {
|
|
|
5964
5980
|
for (const id of walk9.path) {
|
|
5965
5981
|
const owner = resolveOwningService(graph, id);
|
|
5966
5982
|
if (!owner) continue;
|
|
5967
|
-
const { id:
|
|
5983
|
+
const { id: serviceId15, svc } = owner;
|
|
5968
5984
|
const deps = svc.dependencies ?? {};
|
|
5969
5985
|
for (const pair of candidatePairs) {
|
|
5970
5986
|
const declared = deps[pair.driver];
|
|
@@ -5977,7 +5993,7 @@ function databaseRootCauseShape(graph, origin, walk9) {
|
|
|
5977
5993
|
);
|
|
5978
5994
|
if (!result.compatible) {
|
|
5979
5995
|
return {
|
|
5980
|
-
rootCauseNode:
|
|
5996
|
+
rootCauseNode: serviceId15,
|
|
5981
5997
|
rootCauseReason: result.reason ?? "incompatible driver",
|
|
5982
5998
|
...result.minDriverVersion ? {
|
|
5983
5999
|
fixRecommendation: `Upgrade ${svc.name} ${pair.driver} driver to >= ${result.minDriverVersion}`
|
|
@@ -5992,7 +6008,7 @@ function serviceRootCauseShape(graph, _origin, walk9) {
|
|
|
5992
6008
|
for (const id of walk9.path) {
|
|
5993
6009
|
const owner = resolveOwningService(graph, id);
|
|
5994
6010
|
if (!owner) continue;
|
|
5995
|
-
const { id:
|
|
6011
|
+
const { id: serviceId15, svc } = owner;
|
|
5996
6012
|
const deps = svc.dependencies ?? {};
|
|
5997
6013
|
const serviceNodeEngine = svc.nodeEngine;
|
|
5998
6014
|
for (const constraint of nodeEngineConstraints()) {
|
|
@@ -6001,7 +6017,7 @@ function serviceRootCauseShape(graph, _origin, walk9) {
|
|
|
6001
6017
|
const result = checkNodeEngineConstraint(constraint, declared, serviceNodeEngine);
|
|
6002
6018
|
if (!result.compatible && result.reason) {
|
|
6003
6019
|
return {
|
|
6004
|
-
rootCauseNode:
|
|
6020
|
+
rootCauseNode: serviceId15,
|
|
6005
6021
|
rootCauseReason: result.reason,
|
|
6006
6022
|
...result.requiredNodeVersion ? {
|
|
6007
6023
|
fixRecommendation: `Bump ${svc.name}'s engines.node to >= ${result.requiredNodeVersion}`
|
|
@@ -6016,7 +6032,7 @@ function serviceRootCauseShape(graph, _origin, walk9) {
|
|
|
6016
6032
|
const result = checkPackageConflict(conflict, declared, requiredDeclared);
|
|
6017
6033
|
if (!result.compatible && result.reason) {
|
|
6018
6034
|
return {
|
|
6019
|
-
rootCauseNode:
|
|
6035
|
+
rootCauseNode: serviceId15,
|
|
6020
6036
|
rootCauseReason: result.reason,
|
|
6021
6037
|
fixRecommendation: `Upgrade ${svc.name}'s ${conflict.requires.name} to >= ${conflict.requires.minVersion}`
|
|
6022
6038
|
};
|
|
@@ -6117,9 +6133,9 @@ function rootCauseFromIncidents(nodeId, incidents, errorEvent) {
|
|
|
6117
6133
|
function isFailingCallEdge(e) {
|
|
6118
6134
|
return e.type === import_types8.EdgeType.CALLS && (e.signal?.errorCount ?? 0) > 0;
|
|
6119
6135
|
}
|
|
6120
|
-
function callSourcesForService(graph,
|
|
6121
|
-
const ids = [
|
|
6122
|
-
for (const edgeId of graph.outboundEdges(
|
|
6136
|
+
function callSourcesForService(graph, serviceId15) {
|
|
6137
|
+
const ids = [serviceId15];
|
|
6138
|
+
for (const edgeId of graph.outboundEdges(serviceId15)) {
|
|
6123
6139
|
const e = graph.getEdgeAttributes(edgeId);
|
|
6124
6140
|
if (e.type !== import_types8.EdgeType.CONTAINS) continue;
|
|
6125
6141
|
const tgt = graph.getNodeAttributes(e.target);
|
|
@@ -6143,9 +6159,9 @@ function failingCallDominates(e, id, curEdge, curId) {
|
|
|
6143
6159
|
}
|
|
6144
6160
|
return id < curId;
|
|
6145
6161
|
}
|
|
6146
|
-
function dominantFailingCall(graph,
|
|
6162
|
+
function dominantFailingCall(graph, serviceId15, visited) {
|
|
6147
6163
|
let best = null;
|
|
6148
|
-
for (const src of callSourcesForService(graph,
|
|
6164
|
+
for (const src of callSourcesForService(graph, serviceId15)) {
|
|
6149
6165
|
for (const edgeId of graph.outboundEdges(src)) {
|
|
6150
6166
|
const e = graph.getEdgeAttributes(edgeId);
|
|
6151
6167
|
if (!isFailingCallEdge(e)) continue;
|
|
@@ -6160,26 +6176,26 @@ function dominantFailingCall(graph, serviceId12, visited) {
|
|
|
6160
6176
|
return best;
|
|
6161
6177
|
}
|
|
6162
6178
|
function followFailingCallChain(graph, originServiceId, maxDepth) {
|
|
6163
|
-
const
|
|
6179
|
+
const path74 = [originServiceId];
|
|
6164
6180
|
const edges = [];
|
|
6165
6181
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
6166
6182
|
let current = originServiceId;
|
|
6167
6183
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
6168
6184
|
const hop = dominantFailingCall(graph, current, visited);
|
|
6169
6185
|
if (!hop) break;
|
|
6170
|
-
|
|
6186
|
+
path74.push(hop.nextService);
|
|
6171
6187
|
edges.push(hop.edge);
|
|
6172
6188
|
visited.add(hop.nextService);
|
|
6173
6189
|
current = hop.nextService;
|
|
6174
6190
|
}
|
|
6175
6191
|
if (edges.length === 0) return null;
|
|
6176
|
-
return { path:
|
|
6192
|
+
return { path: path74, edges, culprit: current };
|
|
6177
6193
|
}
|
|
6178
6194
|
function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
6179
6195
|
const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
|
|
6180
6196
|
if (!chain) return null;
|
|
6181
6197
|
const culprit = chain.culprit;
|
|
6182
|
-
const
|
|
6198
|
+
const path74 = [...chain.path];
|
|
6183
6199
|
const edgeProvenances = chain.edges.map((e) => e.provenance);
|
|
6184
6200
|
const baseConfidence = confidenceFromMix(chain.edges);
|
|
6185
6201
|
const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
|
|
@@ -6187,14 +6203,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
6187
6203
|
if (loc) {
|
|
6188
6204
|
let rootCauseNode = culprit;
|
|
6189
6205
|
if (loc.fileNode) {
|
|
6190
|
-
|
|
6206
|
+
path74.push(loc.fileNode);
|
|
6191
6207
|
edgeProvenances.push(import_types8.Provenance.OBSERVED);
|
|
6192
6208
|
rootCauseNode = loc.fileNode;
|
|
6193
6209
|
}
|
|
6194
6210
|
return import_types8.RootCauseResultSchema.parse({
|
|
6195
6211
|
rootCauseNode,
|
|
6196
6212
|
rootCauseReason: loc.rootCauseReason,
|
|
6197
|
-
traversalPath:
|
|
6213
|
+
traversalPath: path74,
|
|
6198
6214
|
edgeProvenances,
|
|
6199
6215
|
confidence,
|
|
6200
6216
|
...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
|
|
@@ -6206,7 +6222,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
6206
6222
|
return import_types8.RootCauseResultSchema.parse({
|
|
6207
6223
|
rootCauseNode: culprit,
|
|
6208
6224
|
rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
|
|
6209
|
-
traversalPath:
|
|
6225
|
+
traversalPath: path74,
|
|
6210
6226
|
edgeProvenances,
|
|
6211
6227
|
confidence,
|
|
6212
6228
|
fixRecommendation: `Inspect ${culpritName}'s failing handler`
|
|
@@ -6642,10 +6658,10 @@ function enrichWithNavigation(graph, errorNodeId, legacy, incidents, now) {
|
|
|
6642
6658
|
let traversalPath = legacy.traversalPath;
|
|
6643
6659
|
let edgeProvenances = legacy.edgeProvenances;
|
|
6644
6660
|
if (top.node !== seedNode) {
|
|
6645
|
-
const
|
|
6646
|
-
if (
|
|
6647
|
-
traversalPath =
|
|
6648
|
-
edgeProvenances =
|
|
6661
|
+
const path74 = findPath(graph, errorNodeId, top.node, "up", ROOT_CAUSE_MAX_DEPTH);
|
|
6662
|
+
if (path74) {
|
|
6663
|
+
traversalPath = path74.nodes;
|
|
6664
|
+
edgeProvenances = path74.edges.map((e) => e.provenance);
|
|
6649
6665
|
} else {
|
|
6650
6666
|
traversalPath = [errorNodeId, top.node];
|
|
6651
6667
|
edgeProvenances = [top.provenance ?? import_types8.Provenance.OBSERVED];
|
|
@@ -7057,11 +7073,11 @@ init_cjs_shims();
|
|
|
7057
7073
|
|
|
7058
7074
|
// src/extract/services.ts
|
|
7059
7075
|
init_cjs_shims();
|
|
7060
|
-
var
|
|
7061
|
-
var
|
|
7076
|
+
var import_node_fs20 = require("fs");
|
|
7077
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
7062
7078
|
var import_ignore = __toESM(require("ignore"), 1);
|
|
7063
7079
|
var import_minimatch2 = require("minimatch");
|
|
7064
|
-
var
|
|
7080
|
+
var import_types19 = require("@neat.is/types");
|
|
7065
7081
|
|
|
7066
7082
|
// src/extract/python.ts
|
|
7067
7083
|
init_cjs_shims();
|
|
@@ -7386,11 +7402,158 @@ async function discoverJavaService(scanPath, dir) {
|
|
|
7386
7402
|
return { pkg, dir, node };
|
|
7387
7403
|
}
|
|
7388
7404
|
|
|
7389
|
-
// src/extract/
|
|
7405
|
+
// src/extract/kotlin.ts
|
|
7390
7406
|
init_cjs_shims();
|
|
7391
7407
|
var import_node_fs15 = require("fs");
|
|
7392
7408
|
var import_node_path17 = __toESM(require("path"), 1);
|
|
7393
7409
|
var import_types15 = require("@neat.is/types");
|
|
7410
|
+
var KOTLIN_SOURCE_EXT = ".kt";
|
|
7411
|
+
var JAVA_SOURCE_EXT = ".java";
|
|
7412
|
+
var SOURCE_PROBE_MAX_DEPTH = 8;
|
|
7413
|
+
async function dominantJvmSourceLanguage(dir) {
|
|
7414
|
+
let kt = 0;
|
|
7415
|
+
let java = 0;
|
|
7416
|
+
async function recurse(current, depth) {
|
|
7417
|
+
if (depth > SOURCE_PROBE_MAX_DEPTH) return;
|
|
7418
|
+
const entries = await import_node_fs15.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
7419
|
+
for (const entry of entries) {
|
|
7420
|
+
if (entry.isDirectory()) {
|
|
7421
|
+
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
7422
|
+
await recurse(import_node_path17.default.join(current, entry.name), depth + 1);
|
|
7423
|
+
continue;
|
|
7424
|
+
}
|
|
7425
|
+
if (!entry.isFile()) continue;
|
|
7426
|
+
const ext = import_node_path17.default.extname(entry.name).toLowerCase();
|
|
7427
|
+
if (ext === KOTLIN_SOURCE_EXT) kt++;
|
|
7428
|
+
else if (ext === JAVA_SOURCE_EXT) java++;
|
|
7429
|
+
}
|
|
7430
|
+
}
|
|
7431
|
+
await recurse(dir, 0);
|
|
7432
|
+
if (kt > 0 && kt >= java) return "kotlin";
|
|
7433
|
+
if (java > 0) return "java";
|
|
7434
|
+
return void 0;
|
|
7435
|
+
}
|
|
7436
|
+
async function readJvmManifest(dir) {
|
|
7437
|
+
const pomPath = import_node_path17.default.join(dir, JAVA_MANIFESTS[0]);
|
|
7438
|
+
const gradlePath = import_node_path17.default.join(dir, JAVA_MANIFESTS[1]);
|
|
7439
|
+
const gradleKtsPath = import_node_path17.default.join(dir, JAVA_MANIFESTS[2]);
|
|
7440
|
+
if (await exists2(pomPath)) {
|
|
7441
|
+
return parsePomXml(await import_node_fs15.promises.readFile(pomPath, "utf8").catch(() => ""));
|
|
7442
|
+
}
|
|
7443
|
+
if (await exists2(gradlePath)) {
|
|
7444
|
+
return parseGradle(await import_node_fs15.promises.readFile(gradlePath, "utf8").catch(() => ""));
|
|
7445
|
+
}
|
|
7446
|
+
if (await exists2(gradleKtsPath)) {
|
|
7447
|
+
return parseGradle(await import_node_fs15.promises.readFile(gradleKtsPath, "utf8").catch(() => ""));
|
|
7448
|
+
}
|
|
7449
|
+
return null;
|
|
7450
|
+
}
|
|
7451
|
+
async function discoverKotlinService(scanPath, dir) {
|
|
7452
|
+
if (!await hasJavaManifest(dir)) return null;
|
|
7453
|
+
if (await dominantJvmSourceLanguage(dir) !== "kotlin") return null;
|
|
7454
|
+
const manifest = await readJvmManifest(dir);
|
|
7455
|
+
if (!manifest) return null;
|
|
7456
|
+
const name = manifest.name?.trim() || import_node_path17.default.basename(dir);
|
|
7457
|
+
const dependencies = manifest.dependencies;
|
|
7458
|
+
const pkg = { name, dependencies };
|
|
7459
|
+
const node = {
|
|
7460
|
+
id: (0, import_types15.serviceId)(name),
|
|
7461
|
+
type: import_types15.NodeType.ServiceNode,
|
|
7462
|
+
name,
|
|
7463
|
+
language: "kotlin",
|
|
7464
|
+
dependencies,
|
|
7465
|
+
repoPath: import_node_path17.default.relative(scanPath, dir)
|
|
7466
|
+
};
|
|
7467
|
+
return { pkg, dir, node };
|
|
7468
|
+
}
|
|
7469
|
+
|
|
7470
|
+
// src/extract/rust.ts
|
|
7471
|
+
init_cjs_shims();
|
|
7472
|
+
var import_node_fs16 = require("fs");
|
|
7473
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
7474
|
+
var import_smol_toml2 = require("smol-toml");
|
|
7475
|
+
var import_types16 = require("@neat.is/types");
|
|
7476
|
+
var CARGO_MANIFEST = "Cargo.toml";
|
|
7477
|
+
async function hasRustManifest(dir) {
|
|
7478
|
+
return exists2(import_node_path18.default.join(dir, CARGO_MANIFEST));
|
|
7479
|
+
}
|
|
7480
|
+
function parseCargoToml(source) {
|
|
7481
|
+
const dependencies = {};
|
|
7482
|
+
let name;
|
|
7483
|
+
let parsed;
|
|
7484
|
+
try {
|
|
7485
|
+
parsed = (0, import_smol_toml2.parse)(source);
|
|
7486
|
+
} catch {
|
|
7487
|
+
return { dependencies };
|
|
7488
|
+
}
|
|
7489
|
+
if (typeof parsed.package?.name === "string") name = parsed.package.name;
|
|
7490
|
+
for (const [crate, spec] of Object.entries(parsed.dependencies ?? {})) {
|
|
7491
|
+
if (typeof spec === "string") {
|
|
7492
|
+
dependencies[crate] = spec;
|
|
7493
|
+
} else if (spec && typeof spec === "object") {
|
|
7494
|
+
const version = spec.version;
|
|
7495
|
+
dependencies[crate] = typeof version === "string" ? version : "";
|
|
7496
|
+
} else {
|
|
7497
|
+
dependencies[crate] = "";
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7500
|
+
return { name, dependencies };
|
|
7501
|
+
}
|
|
7502
|
+
async function discoverRustService(scanPath, dir) {
|
|
7503
|
+
const cargoPath = import_node_path18.default.join(dir, CARGO_MANIFEST);
|
|
7504
|
+
if (!await exists2(cargoPath)) return null;
|
|
7505
|
+
const manifest = parseCargoToml(await import_node_fs16.promises.readFile(cargoPath, "utf8").catch(() => ""));
|
|
7506
|
+
const name = manifest.name?.trim() || import_node_path18.default.basename(dir);
|
|
7507
|
+
const dependencies = manifest.dependencies;
|
|
7508
|
+
const pkg = { name, dependencies };
|
|
7509
|
+
const node = {
|
|
7510
|
+
id: (0, import_types16.serviceId)(name),
|
|
7511
|
+
type: import_types16.NodeType.ServiceNode,
|
|
7512
|
+
name,
|
|
7513
|
+
language: "rust",
|
|
7514
|
+
dependencies,
|
|
7515
|
+
repoPath: import_node_path18.default.relative(scanPath, dir)
|
|
7516
|
+
};
|
|
7517
|
+
return { pkg, dir, node };
|
|
7518
|
+
}
|
|
7519
|
+
|
|
7520
|
+
// src/extract/cpp.ts
|
|
7521
|
+
init_cjs_shims();
|
|
7522
|
+
var import_node_fs17 = require("fs");
|
|
7523
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
7524
|
+
var import_types17 = require("@neat.is/types");
|
|
7525
|
+
var CMAKE_MANIFEST = "CMakeLists.txt";
|
|
7526
|
+
async function hasCppManifest(dir) {
|
|
7527
|
+
return exists2(import_node_path19.default.join(dir, CMAKE_MANIFEST));
|
|
7528
|
+
}
|
|
7529
|
+
function parseCMakeProjectName(source) {
|
|
7530
|
+
const withoutComments = source.replace(/#.*$/gm, "");
|
|
7531
|
+
const m = withoutComments.match(/\bproject\s*\(\s*"?([A-Za-z0-9_.+-]+)"?/i);
|
|
7532
|
+
return m?.[1];
|
|
7533
|
+
}
|
|
7534
|
+
async function discoverCppService(scanPath, dir) {
|
|
7535
|
+
const cmakePath = import_node_path19.default.join(dir, CMAKE_MANIFEST);
|
|
7536
|
+
if (!await exists2(cmakePath)) return null;
|
|
7537
|
+
const source = await import_node_fs17.promises.readFile(cmakePath, "utf8").catch(() => "");
|
|
7538
|
+
const name = parseCMakeProjectName(source)?.trim() || import_node_path19.default.basename(dir);
|
|
7539
|
+
const dependencies = {};
|
|
7540
|
+
const pkg = { name, dependencies };
|
|
7541
|
+
const node = {
|
|
7542
|
+
id: (0, import_types17.serviceId)(name),
|
|
7543
|
+
type: import_types17.NodeType.ServiceNode,
|
|
7544
|
+
name,
|
|
7545
|
+
language: "cpp",
|
|
7546
|
+
dependencies,
|
|
7547
|
+
repoPath: import_node_path19.default.relative(scanPath, dir)
|
|
7548
|
+
};
|
|
7549
|
+
return { pkg, dir, node };
|
|
7550
|
+
}
|
|
7551
|
+
|
|
7552
|
+
// src/extract/dockerfile-service.ts
|
|
7553
|
+
init_cjs_shims();
|
|
7554
|
+
var import_node_fs18 = require("fs");
|
|
7555
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
7556
|
+
var import_types18 = require("@neat.is/types");
|
|
7394
7557
|
function languageForSourceExt(ext) {
|
|
7395
7558
|
switch (ext) {
|
|
7396
7559
|
case ".py":
|
|
@@ -7405,6 +7568,19 @@ function languageForSourceExt(ext) {
|
|
|
7405
7568
|
return "csharp";
|
|
7406
7569
|
case ".java":
|
|
7407
7570
|
return "java";
|
|
7571
|
+
case ".kt":
|
|
7572
|
+
return "kotlin";
|
|
7573
|
+
case ".rs":
|
|
7574
|
+
return "rust";
|
|
7575
|
+
case ".cpp":
|
|
7576
|
+
case ".cc":
|
|
7577
|
+
case ".cxx":
|
|
7578
|
+
case ".c++":
|
|
7579
|
+
case ".hpp":
|
|
7580
|
+
case ".hh":
|
|
7581
|
+
case ".hxx":
|
|
7582
|
+
case ".h++":
|
|
7583
|
+
return "cpp";
|
|
7408
7584
|
case ".ts":
|
|
7409
7585
|
case ".tsx":
|
|
7410
7586
|
return "typescript";
|
|
@@ -7416,14 +7592,14 @@ function languageForSourceExt(ext) {
|
|
|
7416
7592
|
return null;
|
|
7417
7593
|
}
|
|
7418
7594
|
}
|
|
7419
|
-
var LANGUAGE_PRECEDENCE = ["typescript", "javascript", "python", "go", "ruby", "php", "csharp", "java"];
|
|
7595
|
+
var LANGUAGE_PRECEDENCE = ["typescript", "javascript", "python", "go", "ruby", "php", "csharp", "java", "kotlin", "rust", "cpp"];
|
|
7420
7596
|
async function inferServiceLanguage(dir) {
|
|
7421
|
-
const entries = await
|
|
7597
|
+
const entries = await import_node_fs18.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
7422
7598
|
const counts = /* @__PURE__ */ new Map();
|
|
7423
7599
|
for (const entry of entries) {
|
|
7424
7600
|
if (!entry.isFile()) continue;
|
|
7425
7601
|
if (isNeatAuthoredSourceFile(entry.name)) continue;
|
|
7426
|
-
const ext =
|
|
7602
|
+
const ext = import_node_path20.default.extname(entry.name).toLowerCase();
|
|
7427
7603
|
if (!SERVICE_FILE_EXTENSIONS.has(ext)) continue;
|
|
7428
7604
|
const lang = languageForSourceExt(ext);
|
|
7429
7605
|
if (!lang) continue;
|
|
@@ -7442,46 +7618,50 @@ async function inferServiceLanguage(dir) {
|
|
|
7442
7618
|
return best;
|
|
7443
7619
|
}
|
|
7444
7620
|
async function hasLanguageManifest(dir) {
|
|
7445
|
-
return await exists2(
|
|
7621
|
+
return await exists2(import_node_path20.default.join(dir, "package.json")) || await exists2(import_node_path20.default.join(dir, "pyproject.toml")) || await exists2(import_node_path20.default.join(dir, "requirements.txt")) || await exists2(import_node_path20.default.join(dir, "setup.py")) || await exists2(import_node_path20.default.join(dir, "go.mod")) || await exists2(import_node_path20.default.join(dir, "Gemfile")) || await exists2(import_node_path20.default.join(dir, "composer.json")) || // C#'s marker is a glob (`*.csproj` / `*.sln`), so it reads the directory
|
|
7446
7622
|
// rather than probing a fixed filename (ADR-196).
|
|
7447
|
-
await hasCsharpProject(dir) || // Java
|
|
7448
|
-
|
|
7623
|
+
await hasCsharpProject(dir) || // Java (and its JVM sibling Kotlin, ADR-199) key on the same Maven / Gradle
|
|
7624
|
+
// build manifest (ADR-197), so this one check stands the Dockerfile fallback
|
|
7625
|
+
// down for both.
|
|
7626
|
+
await hasJavaManifest(dir) || // Rust's marker is a fixed `Cargo.toml` (ADR-201).
|
|
7627
|
+
await hasRustManifest(dir) || // C++'s marker is a fixed `CMakeLists.txt` (ADR-202).
|
|
7628
|
+
await hasCppManifest(dir);
|
|
7449
7629
|
}
|
|
7450
7630
|
async function hasDockerfileDeclaredService(dir) {
|
|
7451
|
-
if (!await exists2(
|
|
7631
|
+
if (!await exists2(import_node_path20.default.join(dir, "Dockerfile"))) return false;
|
|
7452
7632
|
return await inferServiceLanguage(dir) !== null;
|
|
7453
7633
|
}
|
|
7454
7634
|
async function discoverDockerfileService(scanPath, dir) {
|
|
7455
|
-
if (!await exists2(
|
|
7635
|
+
if (!await exists2(import_node_path20.default.join(dir, "Dockerfile"))) return null;
|
|
7456
7636
|
if (await hasLanguageManifest(dir)) return null;
|
|
7457
7637
|
const language = await inferServiceLanguage(dir);
|
|
7458
7638
|
if (!language) return null;
|
|
7459
|
-
const name =
|
|
7639
|
+
const name = import_node_path20.default.basename(dir);
|
|
7460
7640
|
const pkg = { name, dependencies: {} };
|
|
7461
7641
|
const node = {
|
|
7462
|
-
id: (0,
|
|
7463
|
-
type:
|
|
7642
|
+
id: (0, import_types18.serviceId)(name),
|
|
7643
|
+
type: import_types18.NodeType.ServiceNode,
|
|
7464
7644
|
name,
|
|
7465
7645
|
language,
|
|
7466
7646
|
dependencies: {},
|
|
7467
|
-
repoPath:
|
|
7647
|
+
repoPath: import_node_path20.default.relative(scanPath, dir)
|
|
7468
7648
|
};
|
|
7469
7649
|
return { pkg, dir, node };
|
|
7470
7650
|
}
|
|
7471
7651
|
|
|
7472
7652
|
// src/extract/owners.ts
|
|
7473
7653
|
init_cjs_shims();
|
|
7474
|
-
var
|
|
7475
|
-
var
|
|
7654
|
+
var import_node_fs19 = require("fs");
|
|
7655
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
7476
7656
|
var import_minimatch = require("minimatch");
|
|
7477
7657
|
async function loadCodeowners(scanPath) {
|
|
7478
7658
|
const candidates = [
|
|
7479
|
-
|
|
7480
|
-
|
|
7659
|
+
import_node_path21.default.join(scanPath, "CODEOWNERS"),
|
|
7660
|
+
import_node_path21.default.join(scanPath, ".github", "CODEOWNERS")
|
|
7481
7661
|
];
|
|
7482
7662
|
for (const file of candidates) {
|
|
7483
7663
|
if (await exists2(file)) {
|
|
7484
|
-
const raw = await
|
|
7664
|
+
const raw = await import_node_fs19.promises.readFile(file, "utf8");
|
|
7485
7665
|
return parseCodeowners(raw);
|
|
7486
7666
|
}
|
|
7487
7667
|
}
|
|
@@ -7499,7 +7679,7 @@ function parseCodeowners(raw) {
|
|
|
7499
7679
|
return { rules };
|
|
7500
7680
|
}
|
|
7501
7681
|
function matchOwner(file, repoPath) {
|
|
7502
|
-
const normalized = repoPath.split(
|
|
7682
|
+
const normalized = repoPath.split(import_node_path21.default.sep).join("/");
|
|
7503
7683
|
for (const rule of file.rules) {
|
|
7504
7684
|
if (matchesPattern(rule.pattern, normalized)) return rule.owners;
|
|
7505
7685
|
}
|
|
@@ -7515,7 +7695,7 @@ function matchesPattern(rawPattern, repoPath) {
|
|
|
7515
7695
|
return false;
|
|
7516
7696
|
}
|
|
7517
7697
|
async function readPackageJsonAuthor(serviceDir) {
|
|
7518
|
-
const pkgPath =
|
|
7698
|
+
const pkgPath = import_node_path21.default.join(serviceDir, "package.json");
|
|
7519
7699
|
if (!await exists2(pkgPath)) return null;
|
|
7520
7700
|
try {
|
|
7521
7701
|
const pkg = await readJson(pkgPath);
|
|
@@ -7552,36 +7732,36 @@ function workspaceGlobs(pkg) {
|
|
|
7552
7732
|
return null;
|
|
7553
7733
|
}
|
|
7554
7734
|
async function hasPythonManifest(dir) {
|
|
7555
|
-
return await exists2(
|
|
7735
|
+
return await exists2(import_node_path22.default.join(dir, "pyproject.toml")) || await exists2(import_node_path22.default.join(dir, "requirements.txt")) || await exists2(import_node_path22.default.join(dir, "setup.py"));
|
|
7556
7736
|
}
|
|
7557
7737
|
async function hasGoManifest(dir) {
|
|
7558
|
-
return exists2(
|
|
7738
|
+
return exists2(import_node_path22.default.join(dir, "go.mod"));
|
|
7559
7739
|
}
|
|
7560
7740
|
async function hasRubyManifest(dir) {
|
|
7561
|
-
return exists2(
|
|
7741
|
+
return exists2(import_node_path22.default.join(dir, "Gemfile"));
|
|
7562
7742
|
}
|
|
7563
7743
|
async function hasPhpManifest(dir) {
|
|
7564
|
-
return exists2(
|
|
7744
|
+
return exists2(import_node_path22.default.join(dir, "composer.json"));
|
|
7565
7745
|
}
|
|
7566
7746
|
async function hasCsharpManifest(dir) {
|
|
7567
7747
|
return hasCsharpProject(dir);
|
|
7568
7748
|
}
|
|
7569
7749
|
async function loadGitignore(scanPath) {
|
|
7570
|
-
const gitignorePath =
|
|
7750
|
+
const gitignorePath = import_node_path22.default.join(scanPath, ".gitignore");
|
|
7571
7751
|
if (!await exists2(gitignorePath)) return null;
|
|
7572
|
-
const raw = await
|
|
7752
|
+
const raw = await import_node_fs20.promises.readFile(gitignorePath, "utf8");
|
|
7573
7753
|
return (0, import_ignore.default)().add(raw);
|
|
7574
7754
|
}
|
|
7575
7755
|
async function walkDirs(start, scanPath, options, visit) {
|
|
7576
7756
|
async function recurse(current, depth) {
|
|
7577
7757
|
if (depth > options.maxDepth) return;
|
|
7578
|
-
const entries = await
|
|
7758
|
+
const entries = await import_node_fs20.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
7579
7759
|
for (const entry of entries) {
|
|
7580
7760
|
if (!entry.isDirectory()) continue;
|
|
7581
7761
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
7582
|
-
const child =
|
|
7762
|
+
const child = import_node_path22.default.join(current, entry.name);
|
|
7583
7763
|
if (options.ig) {
|
|
7584
|
-
const rel =
|
|
7764
|
+
const rel = import_node_path22.default.relative(scanPath, child).split(import_node_path22.default.sep).join("/");
|
|
7585
7765
|
if (rel && options.ig.ignores(rel + "/")) continue;
|
|
7586
7766
|
}
|
|
7587
7767
|
if (await isPythonVenvDir(child)) continue;
|
|
@@ -7597,8 +7777,8 @@ async function expandWorkspaceGlobs(scanPath, globs) {
|
|
|
7597
7777
|
for (const raw of globs) {
|
|
7598
7778
|
const pattern = raw.replace(/^\.\//, "");
|
|
7599
7779
|
if (!pattern.includes("*")) {
|
|
7600
|
-
const candidate =
|
|
7601
|
-
if (await exists2(
|
|
7780
|
+
const candidate = import_node_path22.default.join(scanPath, pattern);
|
|
7781
|
+
if (await exists2(import_node_path22.default.join(candidate, "package.json"))) found.add(candidate);
|
|
7602
7782
|
continue;
|
|
7603
7783
|
}
|
|
7604
7784
|
const segments = pattern.split("/");
|
|
@@ -7607,13 +7787,13 @@ async function expandWorkspaceGlobs(scanPath, globs) {
|
|
|
7607
7787
|
if (seg.includes("*")) break;
|
|
7608
7788
|
staticSegments.push(seg);
|
|
7609
7789
|
}
|
|
7610
|
-
const start =
|
|
7790
|
+
const start = import_node_path22.default.join(scanPath, ...staticSegments);
|
|
7611
7791
|
if (!await exists2(start)) continue;
|
|
7612
7792
|
const hasDoubleStar = pattern.includes("**");
|
|
7613
7793
|
const walkDepth = hasDoubleStar ? scanDepth : Math.max(0, segments.length - staticSegments.length - 1);
|
|
7614
7794
|
await walkDirs(start, scanPath, { maxDepth: walkDepth, ig: null }, async (dir) => {
|
|
7615
|
-
const rel =
|
|
7616
|
-
if ((0, import_minimatch2.minimatch)(rel, pattern) && await exists2(
|
|
7795
|
+
const rel = import_node_path22.default.relative(scanPath, dir).split(import_node_path22.default.sep).join("/");
|
|
7796
|
+
if ((0, import_minimatch2.minimatch)(rel, pattern) && await exists2(import_node_path22.default.join(dir, "package.json"))) {
|
|
7617
7797
|
found.add(dir);
|
|
7618
7798
|
}
|
|
7619
7799
|
});
|
|
@@ -7636,31 +7816,31 @@ function detectJsFramework(pkg) {
|
|
|
7636
7816
|
async function detectJsServiceLanguage(dir, pkg) {
|
|
7637
7817
|
const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
7638
7818
|
if (deps["typescript"] !== void 0) return "typescript";
|
|
7639
|
-
const entries = await
|
|
7819
|
+
const entries = await import_node_fs20.promises.readdir(dir).catch(() => []);
|
|
7640
7820
|
if (entries.some((name) => /^tsconfig(\..+)?\.json$/.test(name))) return "typescript";
|
|
7641
7821
|
return "javascript";
|
|
7642
7822
|
}
|
|
7643
7823
|
async function discoverNodeService(scanPath, dir) {
|
|
7644
|
-
const pkgPath =
|
|
7824
|
+
const pkgPath = import_node_path22.default.join(dir, "package.json");
|
|
7645
7825
|
if (!await exists2(pkgPath)) return null;
|
|
7646
7826
|
let pkg;
|
|
7647
7827
|
try {
|
|
7648
7828
|
pkg = await readJson(pkgPath);
|
|
7649
7829
|
} catch (err) {
|
|
7650
|
-
recordExtractionError("services",
|
|
7830
|
+
recordExtractionError("services", import_node_path22.default.relative(scanPath, pkgPath), err);
|
|
7651
7831
|
return null;
|
|
7652
7832
|
}
|
|
7653
7833
|
if (!pkg.name) return null;
|
|
7654
7834
|
const framework = detectJsFramework(pkg);
|
|
7655
7835
|
const language = await detectJsServiceLanguage(dir, pkg);
|
|
7656
7836
|
const node = {
|
|
7657
|
-
id: (0,
|
|
7658
|
-
type:
|
|
7837
|
+
id: (0, import_types19.serviceId)(pkg.name),
|
|
7838
|
+
type: import_types19.NodeType.ServiceNode,
|
|
7659
7839
|
name: pkg.name,
|
|
7660
7840
|
language,
|
|
7661
7841
|
version: pkg.version,
|
|
7662
7842
|
dependencies: pkg.dependencies ?? {},
|
|
7663
|
-
repoPath:
|
|
7843
|
+
repoPath: import_node_path22.default.relative(scanPath, dir),
|
|
7664
7844
|
...pkg.engines?.node ? { nodeEngine: pkg.engines.node } : {},
|
|
7665
7845
|
...framework ? { framework } : {}
|
|
7666
7846
|
};
|
|
@@ -7671,18 +7851,18 @@ async function discoverPyService(scanPath, dir) {
|
|
|
7671
7851
|
if (!py) return null;
|
|
7672
7852
|
const pkg = pythonToPackage(py);
|
|
7673
7853
|
const node = {
|
|
7674
|
-
id: (0,
|
|
7675
|
-
type:
|
|
7854
|
+
id: (0, import_types19.serviceId)(py.name),
|
|
7855
|
+
type: import_types19.NodeType.ServiceNode,
|
|
7676
7856
|
name: py.name,
|
|
7677
7857
|
language: "python",
|
|
7678
7858
|
version: py.version,
|
|
7679
7859
|
dependencies: py.dependencies,
|
|
7680
|
-
repoPath:
|
|
7860
|
+
repoPath: import_node_path22.default.relative(scanPath, dir)
|
|
7681
7861
|
};
|
|
7682
7862
|
return { pkg, dir, node };
|
|
7683
7863
|
}
|
|
7684
7864
|
async function discoverServices(scanPath) {
|
|
7685
|
-
const rootPkgPath =
|
|
7865
|
+
const rootPkgPath = import_node_path22.default.join(scanPath, "package.json");
|
|
7686
7866
|
let rootPkg = null;
|
|
7687
7867
|
if (await exists2(rootPkgPath)) {
|
|
7688
7868
|
try {
|
|
@@ -7690,7 +7870,7 @@ async function discoverServices(scanPath) {
|
|
|
7690
7870
|
} catch (err) {
|
|
7691
7871
|
recordExtractionError(
|
|
7692
7872
|
"services workspaces",
|
|
7693
|
-
|
|
7873
|
+
import_node_path22.default.relative(scanPath, rootPkgPath),
|
|
7694
7874
|
err
|
|
7695
7875
|
);
|
|
7696
7876
|
}
|
|
@@ -7702,7 +7882,7 @@ async function discoverServices(scanPath) {
|
|
|
7702
7882
|
} else {
|
|
7703
7883
|
if (rootPkg && rootPkg.name) {
|
|
7704
7884
|
candidateDirs.push(scanPath);
|
|
7705
|
-
} else if (await hasPythonManifest(scanPath) || await hasGoManifest(scanPath) || await hasRubyManifest(scanPath) || await hasPhpManifest(scanPath) || await hasCsharpManifest(scanPath) || await hasJavaManifest(scanPath)) {
|
|
7885
|
+
} else if (await hasPythonManifest(scanPath) || await hasGoManifest(scanPath) || await hasRubyManifest(scanPath) || await hasPhpManifest(scanPath) || await hasCsharpManifest(scanPath) || await hasJavaManifest(scanPath) || await hasRustManifest(scanPath) || await hasCppManifest(scanPath)) {
|
|
7706
7886
|
candidateDirs.push(scanPath);
|
|
7707
7887
|
}
|
|
7708
7888
|
const ig = await loadGitignore(scanPath);
|
|
@@ -7711,9 +7891,9 @@ async function discoverServices(scanPath) {
|
|
|
7711
7891
|
scanPath,
|
|
7712
7892
|
{ maxDepth: parseScanDepth(), ig },
|
|
7713
7893
|
async (dir) => {
|
|
7714
|
-
if (await exists2(
|
|
7894
|
+
if (await exists2(import_node_path22.default.join(dir, "package.json"))) {
|
|
7715
7895
|
candidateDirs.push(dir);
|
|
7716
|
-
} else if (await hasPythonManifest(dir) || await hasGoManifest(dir) || await hasRubyManifest(dir) || await hasPhpManifest(dir) || await hasCsharpManifest(dir) || await hasJavaManifest(dir)) {
|
|
7896
|
+
} else if (await hasPythonManifest(dir) || await hasGoManifest(dir) || await hasRubyManifest(dir) || await hasPhpManifest(dir) || await hasCsharpManifest(dir) || await hasJavaManifest(dir) || await hasRustManifest(dir) || await hasCppManifest(dir)) {
|
|
7717
7897
|
candidateDirs.push(dir);
|
|
7718
7898
|
} else if (await hasDockerfileDeclaredService(dir)) {
|
|
7719
7899
|
candidateDirs.push(dir);
|
|
@@ -7726,14 +7906,21 @@ async function discoverServices(scanPath) {
|
|
|
7726
7906
|
const seenDirs = /* @__PURE__ */ new Set();
|
|
7727
7907
|
const out = [];
|
|
7728
7908
|
for (const dir of candidateDirs) {
|
|
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) ??
|
|
7909
|
+
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) ?? // Kotlin runs ahead of Java: both mark a service with the same Maven/Gradle
|
|
7910
|
+
// manifest, so Kotlin claims a JVM-manifest dir whose source is `.kt` (ADR-199)
|
|
7911
|
+
// and a `.java`-dominant one falls through to the Java reader unchanged.
|
|
7912
|
+
await discoverKotlinService(scanPath, dir) ?? await discoverJavaService(scanPath, dir) ?? // Rust keys on a `Cargo.toml`, a manifest no other language shares (ADR-201),
|
|
7913
|
+
// so its order among the distinct-manifest discoverers doesn't matter.
|
|
7914
|
+
await discoverRustService(scanPath, dir) ?? // C++ keys on a `CMakeLists.txt`, likewise a manifest no other language shares
|
|
7915
|
+
// (ADR-202), so it too sits anywhere among the distinct-manifest discoverers.
|
|
7916
|
+
await discoverCppService(scanPath, dir) ?? await discoverDockerfileService(scanPath, dir);
|
|
7730
7917
|
if (!service) continue;
|
|
7731
7918
|
if (seenDirs.has(service.dir)) continue;
|
|
7732
7919
|
seenDirs.add(service.dir);
|
|
7733
7920
|
const existingDir = seen.get(service.node.name);
|
|
7734
7921
|
if (existingDir !== void 0) {
|
|
7735
|
-
const a =
|
|
7736
|
-
const b =
|
|
7922
|
+
const a = import_node_path22.default.relative(scanPath, existingDir) || ".";
|
|
7923
|
+
const b = import_node_path22.default.relative(scanPath, dir) || ".";
|
|
7737
7924
|
console.warn(
|
|
7738
7925
|
`[neat] duplicate package name "${service.node.name}" \u2014 keeping ${a}, ignoring ${b}`
|
|
7739
7926
|
);
|
|
@@ -7747,6 +7934,17 @@ async function discoverServices(scanPath) {
|
|
|
7747
7934
|
const owner = await computeServiceOwner(codeowners, service.node.repoPath, service.dir);
|
|
7748
7935
|
if (owner !== void 0) service.node.owner = owner;
|
|
7749
7936
|
}
|
|
7937
|
+
const resolvedDirs = out.map((s) => import_node_path22.default.resolve(s.dir));
|
|
7938
|
+
for (let i = 0; i < out.length; i++) {
|
|
7939
|
+
const self = resolvedDirs[i];
|
|
7940
|
+
const nested = [];
|
|
7941
|
+
for (let j = 0; j < out.length; j++) {
|
|
7942
|
+
if (i === j) continue;
|
|
7943
|
+
const other = resolvedDirs[j];
|
|
7944
|
+
if (other.startsWith(self + import_node_path22.default.sep)) nested.push(other);
|
|
7945
|
+
}
|
|
7946
|
+
out[i].excludeDirs = nested;
|
|
7947
|
+
}
|
|
7750
7948
|
return out;
|
|
7751
7949
|
}
|
|
7752
7950
|
function addServiceNodes(graph, services) {
|
|
@@ -7770,20 +7968,20 @@ function addServiceNodes(graph, services) {
|
|
|
7770
7968
|
|
|
7771
7969
|
// src/extract/aliases.ts
|
|
7772
7970
|
init_cjs_shims();
|
|
7773
|
-
var
|
|
7774
|
-
var
|
|
7971
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
7972
|
+
var import_node_fs21 = require("fs");
|
|
7775
7973
|
var import_yaml2 = require("yaml");
|
|
7776
|
-
var
|
|
7974
|
+
var import_types20 = require("@neat.is/types");
|
|
7777
7975
|
var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
7778
7976
|
"Service",
|
|
7779
7977
|
"Deployment",
|
|
7780
7978
|
"StatefulSet",
|
|
7781
7979
|
"DaemonSet"
|
|
7782
7980
|
]);
|
|
7783
|
-
function addAliases(graph,
|
|
7784
|
-
if (!graph.hasNode(
|
|
7785
|
-
const node = graph.getNodeAttributes(
|
|
7786
|
-
if (node.type !==
|
|
7981
|
+
function addAliases(graph, serviceId15, candidates) {
|
|
7982
|
+
if (!graph.hasNode(serviceId15)) return;
|
|
7983
|
+
const node = graph.getNodeAttributes(serviceId15);
|
|
7984
|
+
if (node.type !== import_types20.NodeType.ServiceNode) return;
|
|
7787
7985
|
const set = new Set(node.aliases ?? []);
|
|
7788
7986
|
for (const c of candidates) {
|
|
7789
7987
|
if (!c) continue;
|
|
@@ -7792,20 +7990,20 @@ function addAliases(graph, serviceId12, candidates) {
|
|
|
7792
7990
|
}
|
|
7793
7991
|
if (set.size === 0) return;
|
|
7794
7992
|
const updated = { ...node, aliases: [...set].sort() };
|
|
7795
|
-
graph.replaceNodeAttributes(
|
|
7993
|
+
graph.replaceNodeAttributes(serviceId15, updated);
|
|
7796
7994
|
}
|
|
7797
7995
|
function indexServicesByName(services) {
|
|
7798
7996
|
const map = /* @__PURE__ */ new Map();
|
|
7799
7997
|
for (const s of services) {
|
|
7800
7998
|
map.set(s.node.name, s.node.id);
|
|
7801
|
-
map.set(
|
|
7999
|
+
map.set(import_node_path23.default.basename(s.dir), s.node.id);
|
|
7802
8000
|
}
|
|
7803
8001
|
return map;
|
|
7804
8002
|
}
|
|
7805
8003
|
async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
7806
8004
|
let composePath = null;
|
|
7807
8005
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
7808
|
-
const abs =
|
|
8006
|
+
const abs = import_node_path23.default.join(scanPath, name);
|
|
7809
8007
|
if (await exists2(abs)) {
|
|
7810
8008
|
composePath = abs;
|
|
7811
8009
|
break;
|
|
@@ -7818,19 +8016,19 @@ async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
|
7818
8016
|
} catch (err) {
|
|
7819
8017
|
recordExtractionError(
|
|
7820
8018
|
"aliases compose",
|
|
7821
|
-
|
|
8019
|
+
import_node_path23.default.relative(scanPath, composePath),
|
|
7822
8020
|
err
|
|
7823
8021
|
);
|
|
7824
8022
|
return;
|
|
7825
8023
|
}
|
|
7826
8024
|
if (!compose?.services) return;
|
|
7827
8025
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
7828
|
-
const
|
|
7829
|
-
if (!
|
|
8026
|
+
const serviceId15 = serviceIndex.get(composeName);
|
|
8027
|
+
if (!serviceId15) continue;
|
|
7830
8028
|
const aliases = /* @__PURE__ */ new Set([composeName]);
|
|
7831
8029
|
if (svc.container_name) aliases.add(svc.container_name);
|
|
7832
8030
|
if (svc.hostname) aliases.add(svc.hostname);
|
|
7833
|
-
addAliases(graph,
|
|
8031
|
+
addAliases(graph, serviceId15, aliases);
|
|
7834
8032
|
}
|
|
7835
8033
|
}
|
|
7836
8034
|
var LABEL_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -7861,11 +8059,11 @@ function parseDockerfileLabels(content) {
|
|
|
7861
8059
|
}
|
|
7862
8060
|
async function collectDockerfileAliases(graph, services) {
|
|
7863
8061
|
for (const service of services) {
|
|
7864
|
-
const dockerfilePath =
|
|
8062
|
+
const dockerfilePath = import_node_path23.default.join(service.dir, "Dockerfile");
|
|
7865
8063
|
if (!await exists2(dockerfilePath)) continue;
|
|
7866
8064
|
let content;
|
|
7867
8065
|
try {
|
|
7868
|
-
content = await
|
|
8066
|
+
content = await import_node_fs21.promises.readFile(dockerfilePath, "utf8");
|
|
7869
8067
|
} catch (err) {
|
|
7870
8068
|
recordExtractionError("aliases dockerfile", dockerfilePath, err);
|
|
7871
8069
|
continue;
|
|
@@ -7877,15 +8075,15 @@ async function collectDockerfileAliases(graph, services) {
|
|
|
7877
8075
|
async function walkYamlFiles(start, depth = 0, max = 5) {
|
|
7878
8076
|
if (depth > max) return [];
|
|
7879
8077
|
const out = [];
|
|
7880
|
-
const entries = await
|
|
8078
|
+
const entries = await import_node_fs21.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
7881
8079
|
for (const entry of entries) {
|
|
7882
8080
|
if (entry.isDirectory()) {
|
|
7883
8081
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
7884
|
-
const child =
|
|
8082
|
+
const child = import_node_path23.default.join(start, entry.name);
|
|
7885
8083
|
if (await isPythonVenvDir(child)) continue;
|
|
7886
8084
|
out.push(...await walkYamlFiles(child, depth + 1, max));
|
|
7887
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
7888
|
-
out.push(
|
|
8085
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path23.default.extname(entry.name))) {
|
|
8086
|
+
out.push(import_node_path23.default.join(start, entry.name));
|
|
7889
8087
|
}
|
|
7890
8088
|
}
|
|
7891
8089
|
return out;
|
|
@@ -7912,7 +8110,7 @@ function k8sServiceTarget(doc, byName) {
|
|
|
7912
8110
|
async function collectK8sAliases(graph, scanPath, serviceIndex) {
|
|
7913
8111
|
const files = await walkYamlFiles(scanPath);
|
|
7914
8112
|
for (const file of files) {
|
|
7915
|
-
const content = await
|
|
8113
|
+
const content = await import_node_fs21.promises.readFile(file, "utf8");
|
|
7916
8114
|
let docs;
|
|
7917
8115
|
try {
|
|
7918
8116
|
docs = (0, import_yaml2.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
@@ -7937,14 +8135,14 @@ async function addServiceAliases(graph, scanPath, services) {
|
|
|
7937
8135
|
|
|
7938
8136
|
// src/extract/files.ts
|
|
7939
8137
|
init_cjs_shims();
|
|
7940
|
-
var
|
|
8138
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
7941
8139
|
async function addFiles(graph, services) {
|
|
7942
8140
|
let nodesAdded = 0;
|
|
7943
8141
|
let edgesAdded = 0;
|
|
7944
8142
|
for (const service of services) {
|
|
7945
|
-
const filePaths = await walkSourceFiles(service.dir);
|
|
8143
|
+
const filePaths = await walkSourceFiles(service.dir, service.excludeDirs);
|
|
7946
8144
|
for (const filePath of filePaths) {
|
|
7947
|
-
const relPath = toPosix(
|
|
8145
|
+
const relPath = toPosix(import_node_path24.default.relative(service.dir, filePath));
|
|
7948
8146
|
const { nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
7949
8147
|
graph,
|
|
7950
8148
|
service.pkg.name,
|
|
@@ -7960,7 +8158,7 @@ async function addFiles(graph, services) {
|
|
|
7960
8158
|
|
|
7961
8159
|
// src/extract/symbols.ts
|
|
7962
8160
|
init_cjs_shims();
|
|
7963
|
-
var
|
|
8161
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
7964
8162
|
var import_tree_sitter3 = __toESM(require("tree-sitter"), 1);
|
|
7965
8163
|
var import_tree_sitter_javascript3 = __toESM(require("tree-sitter-javascript"), 1);
|
|
7966
8164
|
var import_tree_sitter_typescript = __toESM(require("tree-sitter-typescript"), 1);
|
|
@@ -7970,7 +8168,10 @@ var import_tree_sitter_ruby2 = __toESM(require("tree-sitter-ruby"), 1);
|
|
|
7970
8168
|
var import_tree_sitter_php2 = __toESM(require("tree-sitter-php"), 1);
|
|
7971
8169
|
var import_tree_sitter_c_sharp = __toESM(require("tree-sitter-c-sharp"), 1);
|
|
7972
8170
|
var import_tree_sitter_java = __toESM(require("tree-sitter-java"), 1);
|
|
7973
|
-
var
|
|
8171
|
+
var import_tree_sitter_kotlin = __toESM(require("tree-sitter-kotlin"), 1);
|
|
8172
|
+
var import_tree_sitter_rust = __toESM(require("tree-sitter-rust"), 1);
|
|
8173
|
+
var import_tree_sitter_cpp = __toESM(require("tree-sitter-cpp"), 1);
|
|
8174
|
+
var import_types21 = require("@neat.is/types");
|
|
7974
8175
|
var PARSE_CHUNK3 = 16384;
|
|
7975
8176
|
var GRAMMAR_BY_EXT = {
|
|
7976
8177
|
".ts": import_tree_sitter_typescript.default.typescript,
|
|
@@ -7987,7 +8188,25 @@ var SYMBOL_GRAMMAR_BY_EXT = {
|
|
|
7987
8188
|
".rb": import_tree_sitter_ruby2.default,
|
|
7988
8189
|
".php": import_tree_sitter_php2.default.php_only,
|
|
7989
8190
|
".cs": import_tree_sitter_c_sharp.default,
|
|
7990
|
-
".java": import_tree_sitter_java.default
|
|
8191
|
+
".java": import_tree_sitter_java.default,
|
|
8192
|
+
".kt": import_tree_sitter_kotlin.default,
|
|
8193
|
+
".rs": import_tree_sitter_rust.default,
|
|
8194
|
+
// C++ (ADR-202) — only the UNAMBIGUOUS extensions. `.cpp` / `.cc` / `.cxx` /
|
|
8195
|
+
// `.c++` are implementation files; `.hpp` / `.hh` / `.hxx` / `.h++` are C++-only
|
|
8196
|
+
// headers. `.h` and `.c` are deliberately absent: they are shared with C (a
|
|
8197
|
+
// language NEAT does not add), and this map is global — the symbol grain
|
|
8198
|
+
// dispatches on extension, not on the owning service's language — so claiming
|
|
8199
|
+
// `.h` would parse every pure-C header in any repo with the C++ grammar and
|
|
8200
|
+
// mislabel it. The otel-demo `currency` target's executable code lives in a
|
|
8201
|
+
// `.cpp`, so nothing is lost.
|
|
8202
|
+
".cpp": import_tree_sitter_cpp.default,
|
|
8203
|
+
".cc": import_tree_sitter_cpp.default,
|
|
8204
|
+
".cxx": import_tree_sitter_cpp.default,
|
|
8205
|
+
".c++": import_tree_sitter_cpp.default,
|
|
8206
|
+
".hpp": import_tree_sitter_cpp.default,
|
|
8207
|
+
".hh": import_tree_sitter_cpp.default,
|
|
8208
|
+
".hxx": import_tree_sitter_cpp.default,
|
|
8209
|
+
".h++": import_tree_sitter_cpp.default
|
|
7991
8210
|
};
|
|
7992
8211
|
function parseSource3(parser, source) {
|
|
7993
8212
|
return parser.parse(
|
|
@@ -8400,6 +8619,237 @@ function collectJavaSymbolDefs(root) {
|
|
|
8400
8619
|
walkChildren(root, void 0);
|
|
8401
8620
|
return out;
|
|
8402
8621
|
}
|
|
8622
|
+
function collectKotlinSymbolDefs(root) {
|
|
8623
|
+
const out = [];
|
|
8624
|
+
const push = (kind, qualname, node) => {
|
|
8625
|
+
out.push({
|
|
8626
|
+
kind,
|
|
8627
|
+
qualname,
|
|
8628
|
+
startLine: node.startPosition.row + 1,
|
|
8629
|
+
endLine: node.endPosition.row + 1
|
|
8630
|
+
});
|
|
8631
|
+
};
|
|
8632
|
+
const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
|
|
8633
|
+
const firstChildOfType = (node, types) => {
|
|
8634
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
8635
|
+
const child = node.namedChild(i);
|
|
8636
|
+
if (child && types.includes(child.type)) return child;
|
|
8637
|
+
}
|
|
8638
|
+
return void 0;
|
|
8639
|
+
};
|
|
8640
|
+
const nameOf = (node, ...types) => firstChildOfType(node, types)?.text;
|
|
8641
|
+
const bodyOf = (node) => firstChildOfType(node, ["class_body", "enum_class_body"]);
|
|
8642
|
+
let pkg;
|
|
8643
|
+
for (let i = 0; i < root.namedChildCount; i++) {
|
|
8644
|
+
const child = root.namedChild(i);
|
|
8645
|
+
if (child?.type === "package_header") {
|
|
8646
|
+
pkg = child.namedChild(0)?.text;
|
|
8647
|
+
break;
|
|
8648
|
+
}
|
|
8649
|
+
}
|
|
8650
|
+
const walkChildren = (container, classCtx) => {
|
|
8651
|
+
for (let i = 0; i < container.namedChildCount; i++) {
|
|
8652
|
+
const child = container.namedChild(i);
|
|
8653
|
+
if (child) visit(child, classCtx);
|
|
8654
|
+
}
|
|
8655
|
+
};
|
|
8656
|
+
const visit = (node, classCtx) => {
|
|
8657
|
+
switch (node.type) {
|
|
8658
|
+
case "class_declaration":
|
|
8659
|
+
case "object_declaration": {
|
|
8660
|
+
const name = nameOf(node, "type_identifier");
|
|
8661
|
+
const full = name ? join(classCtx ?? pkg, name) : classCtx;
|
|
8662
|
+
if (name) push("class", full, node);
|
|
8663
|
+
const body = bodyOf(node);
|
|
8664
|
+
if (body) walkChildren(body, full);
|
|
8665
|
+
return;
|
|
8666
|
+
}
|
|
8667
|
+
case "companion_object": {
|
|
8668
|
+
const name = nameOf(node, "type_identifier");
|
|
8669
|
+
const full = name ? join(classCtx ?? pkg, name) : classCtx ?? pkg;
|
|
8670
|
+
const body = bodyOf(node);
|
|
8671
|
+
if (body) walkChildren(body, full);
|
|
8672
|
+
return;
|
|
8673
|
+
}
|
|
8674
|
+
case "function_declaration": {
|
|
8675
|
+
const name = nameOf(node, "simple_identifier");
|
|
8676
|
+
if (name) push(classCtx ? "method" : "function", join(classCtx ?? pkg, name), node);
|
|
8677
|
+
return;
|
|
8678
|
+
}
|
|
8679
|
+
case "secondary_constructor": {
|
|
8680
|
+
if (classCtx) {
|
|
8681
|
+
const typeName = classCtx.slice(classCtx.lastIndexOf(".") + 1);
|
|
8682
|
+
push("constructor", join(classCtx, typeName), node);
|
|
8683
|
+
}
|
|
8684
|
+
return;
|
|
8685
|
+
}
|
|
8686
|
+
}
|
|
8687
|
+
walkChildren(node, classCtx);
|
|
8688
|
+
};
|
|
8689
|
+
walkChildren(root, void 0);
|
|
8690
|
+
return out;
|
|
8691
|
+
}
|
|
8692
|
+
function collectRustSymbolDefs(root) {
|
|
8693
|
+
const out = [];
|
|
8694
|
+
const push = (kind, qualname, node) => {
|
|
8695
|
+
out.push({
|
|
8696
|
+
kind,
|
|
8697
|
+
qualname,
|
|
8698
|
+
startLine: node.startPosition.row + 1,
|
|
8699
|
+
endLine: node.endPosition.row + 1
|
|
8700
|
+
});
|
|
8701
|
+
};
|
|
8702
|
+
const join = (prefix, name) => prefix ? `${prefix}::${name}` : name;
|
|
8703
|
+
const walkTypeBody = (body, typeCtx) => {
|
|
8704
|
+
for (let i = 0; i < body.namedChildCount; i++) {
|
|
8705
|
+
const child = body.namedChild(i);
|
|
8706
|
+
if (!child) continue;
|
|
8707
|
+
if (child.type === "function_item" || child.type === "function_signature_item") {
|
|
8708
|
+
const name = child.childForFieldName("name")?.text;
|
|
8709
|
+
if (name) push("method", join(typeCtx, name), child);
|
|
8710
|
+
}
|
|
8711
|
+
}
|
|
8712
|
+
};
|
|
8713
|
+
const walkChildren = (container, modCtx) => {
|
|
8714
|
+
for (let i = 0; i < container.namedChildCount; i++) {
|
|
8715
|
+
const child = container.namedChild(i);
|
|
8716
|
+
if (child) visit(child, modCtx);
|
|
8717
|
+
}
|
|
8718
|
+
};
|
|
8719
|
+
const visit = (node, modCtx) => {
|
|
8720
|
+
switch (node.type) {
|
|
8721
|
+
case "mod_item": {
|
|
8722
|
+
const name = node.childForFieldName("name")?.text;
|
|
8723
|
+
const full = name ? join(modCtx, name) : modCtx;
|
|
8724
|
+
const body = node.childForFieldName("body");
|
|
8725
|
+
if (body) walkChildren(body, full);
|
|
8726
|
+
return;
|
|
8727
|
+
}
|
|
8728
|
+
case "struct_item":
|
|
8729
|
+
case "enum_item": {
|
|
8730
|
+
const name = node.childForFieldName("name")?.text;
|
|
8731
|
+
if (name) push("class", join(modCtx, name), node);
|
|
8732
|
+
return;
|
|
8733
|
+
}
|
|
8734
|
+
case "trait_item": {
|
|
8735
|
+
const name = node.childForFieldName("name")?.text;
|
|
8736
|
+
const full = name ? join(modCtx, name) : modCtx;
|
|
8737
|
+
if (name) push("class", full, node);
|
|
8738
|
+
const body = node.childForFieldName("body");
|
|
8739
|
+
if (body && full) walkTypeBody(body, full);
|
|
8740
|
+
return;
|
|
8741
|
+
}
|
|
8742
|
+
case "impl_item": {
|
|
8743
|
+
const typeName = node.childForFieldName("type")?.text;
|
|
8744
|
+
const full = typeName ? join(modCtx, typeName) : modCtx;
|
|
8745
|
+
const body = node.childForFieldName("body");
|
|
8746
|
+
if (body && full) walkTypeBody(body, full);
|
|
8747
|
+
return;
|
|
8748
|
+
}
|
|
8749
|
+
case "function_item": {
|
|
8750
|
+
const name = node.childForFieldName("name")?.text;
|
|
8751
|
+
if (name) push("function", join(modCtx, name), node);
|
|
8752
|
+
return;
|
|
8753
|
+
}
|
|
8754
|
+
}
|
|
8755
|
+
walkChildren(node, modCtx);
|
|
8756
|
+
};
|
|
8757
|
+
walkChildren(root, void 0);
|
|
8758
|
+
return out;
|
|
8759
|
+
}
|
|
8760
|
+
function collectCppSymbolDefs(root) {
|
|
8761
|
+
const out = [];
|
|
8762
|
+
const push = (kind, qualname, node) => {
|
|
8763
|
+
out.push({
|
|
8764
|
+
kind,
|
|
8765
|
+
qualname,
|
|
8766
|
+
startLine: node.startPosition.row + 1,
|
|
8767
|
+
endLine: node.endPosition.row + 1
|
|
8768
|
+
});
|
|
8769
|
+
};
|
|
8770
|
+
const join = (prefix, name) => prefix ? `${prefix}::${name}` : name;
|
|
8771
|
+
const DECLARATOR_WRAPPERS = /* @__PURE__ */ new Set([
|
|
8772
|
+
"function_declarator",
|
|
8773
|
+
"pointer_declarator",
|
|
8774
|
+
"reference_declarator",
|
|
8775
|
+
"parenthesized_declarator"
|
|
8776
|
+
]);
|
|
8777
|
+
const functionNameNode = (node) => {
|
|
8778
|
+
let decl = node.childForFieldName("declarator");
|
|
8779
|
+
for (let guard = 0; decl && guard < 8; guard++) {
|
|
8780
|
+
if (decl.type === "function_declarator") {
|
|
8781
|
+
return decl.childForFieldName("declarator") ?? void 0;
|
|
8782
|
+
}
|
|
8783
|
+
let next;
|
|
8784
|
+
for (let i = 0; i < decl.namedChildCount; i++) {
|
|
8785
|
+
const child = decl.namedChild(i);
|
|
8786
|
+
if (child && DECLARATOR_WRAPPERS.has(child.type)) {
|
|
8787
|
+
next = child;
|
|
8788
|
+
break;
|
|
8789
|
+
}
|
|
8790
|
+
}
|
|
8791
|
+
decl = next;
|
|
8792
|
+
}
|
|
8793
|
+
return void 0;
|
|
8794
|
+
};
|
|
8795
|
+
const classify = (nameText, prefix, enclosingClass) => {
|
|
8796
|
+
const qualname = join(prefix, nameText);
|
|
8797
|
+
let className;
|
|
8798
|
+
let memberName;
|
|
8799
|
+
const idx = nameText.lastIndexOf("::");
|
|
8800
|
+
if (idx >= 0) {
|
|
8801
|
+
memberName = nameText.slice(idx + 2);
|
|
8802
|
+
const before = nameText.slice(0, idx);
|
|
8803
|
+
const j = before.lastIndexOf("::");
|
|
8804
|
+
className = j >= 0 ? before.slice(j + 2) : before;
|
|
8805
|
+
} else {
|
|
8806
|
+
memberName = nameText;
|
|
8807
|
+
className = enclosingClass;
|
|
8808
|
+
}
|
|
8809
|
+
let kind;
|
|
8810
|
+
if (className && memberName === className) kind = "constructor";
|
|
8811
|
+
else if (className) kind = "method";
|
|
8812
|
+
else kind = "function";
|
|
8813
|
+
return { kind, qualname };
|
|
8814
|
+
};
|
|
8815
|
+
const walkChildren = (container, prefix, enclosingClass) => {
|
|
8816
|
+
for (let i = 0; i < container.namedChildCount; i++) {
|
|
8817
|
+
const child = container.namedChild(i);
|
|
8818
|
+
if (child) visit(child, prefix, enclosingClass);
|
|
8819
|
+
}
|
|
8820
|
+
};
|
|
8821
|
+
const visit = (node, prefix, enclosingClass) => {
|
|
8822
|
+
switch (node.type) {
|
|
8823
|
+
case "namespace_definition": {
|
|
8824
|
+
const name = node.childForFieldName("name")?.text;
|
|
8825
|
+
const newPrefix = name ? join(prefix, name) : prefix;
|
|
8826
|
+
const body = node.childForFieldName("body");
|
|
8827
|
+
if (body) walkChildren(body, newPrefix, void 0);
|
|
8828
|
+
return;
|
|
8829
|
+
}
|
|
8830
|
+
case "class_specifier":
|
|
8831
|
+
case "struct_specifier": {
|
|
8832
|
+
const name = node.childForFieldName("name")?.text;
|
|
8833
|
+
const full = name ? join(prefix, name) : prefix;
|
|
8834
|
+
if (name) push("class", full, node);
|
|
8835
|
+
const body = node.childForFieldName("body");
|
|
8836
|
+
if (body && name) walkChildren(body, full, name);
|
|
8837
|
+
return;
|
|
8838
|
+
}
|
|
8839
|
+
case "function_definition": {
|
|
8840
|
+
const nameNode = functionNameNode(node);
|
|
8841
|
+
if (nameNode) {
|
|
8842
|
+
const { kind, qualname } = classify(nameNode.text, prefix, enclosingClass);
|
|
8843
|
+
push(kind, qualname, node);
|
|
8844
|
+
}
|
|
8845
|
+
return;
|
|
8846
|
+
}
|
|
8847
|
+
}
|
|
8848
|
+
walkChildren(node, prefix, enclosingClass);
|
|
8849
|
+
};
|
|
8850
|
+
walkChildren(root, void 0, void 0);
|
|
8851
|
+
return out;
|
|
8852
|
+
}
|
|
8403
8853
|
function collectSymbolDefsForExt(ext, root) {
|
|
8404
8854
|
switch (ext) {
|
|
8405
8855
|
case ".py":
|
|
@@ -8414,6 +8864,19 @@ function collectSymbolDefsForExt(ext, root) {
|
|
|
8414
8864
|
return collectCsharpSymbolDefs(root);
|
|
8415
8865
|
case ".java":
|
|
8416
8866
|
return collectJavaSymbolDefs(root);
|
|
8867
|
+
case ".kt":
|
|
8868
|
+
return collectKotlinSymbolDefs(root);
|
|
8869
|
+
case ".rs":
|
|
8870
|
+
return collectRustSymbolDefs(root);
|
|
8871
|
+
case ".cpp":
|
|
8872
|
+
case ".cc":
|
|
8873
|
+
case ".cxx":
|
|
8874
|
+
case ".c++":
|
|
8875
|
+
case ".hpp":
|
|
8876
|
+
case ".hh":
|
|
8877
|
+
case ".hxx":
|
|
8878
|
+
case ".h++":
|
|
8879
|
+
return collectCppSymbolDefs(root);
|
|
8417
8880
|
default:
|
|
8418
8881
|
return collectSymbolDefs(root);
|
|
8419
8882
|
}
|
|
@@ -8445,12 +8908,12 @@ async function addSymbols(graph, services) {
|
|
|
8445
8908
|
let nodesAdded = 0;
|
|
8446
8909
|
let edgesAdded = 0;
|
|
8447
8910
|
for (const service of services) {
|
|
8448
|
-
const files = await loadSourceFiles(service.dir);
|
|
8911
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
8449
8912
|
for (const file of files) {
|
|
8450
|
-
const ext =
|
|
8913
|
+
const ext = import_node_path25.default.extname(file.path);
|
|
8451
8914
|
const parser = parserForExt5(ext);
|
|
8452
8915
|
if (!parser) continue;
|
|
8453
|
-
const relPath = toPosix(
|
|
8916
|
+
const relPath = toPosix(import_node_path25.default.relative(service.dir, file.path));
|
|
8454
8917
|
let defs;
|
|
8455
8918
|
try {
|
|
8456
8919
|
const tree = parseSource3(parser, file.content);
|
|
@@ -8469,11 +8932,11 @@ async function addSymbols(graph, services) {
|
|
|
8469
8932
|
nodesAdded += fn;
|
|
8470
8933
|
edgesAdded += fe;
|
|
8471
8934
|
for (const { def, disambiguator } of disambiguate(defs)) {
|
|
8472
|
-
const sid = (0,
|
|
8935
|
+
const sid = (0, import_types21.symbolId)(service.pkg.name, relPath, def.qualname, disambiguator);
|
|
8473
8936
|
if (!graph.hasNode(sid)) {
|
|
8474
8937
|
const node = {
|
|
8475
8938
|
id: sid,
|
|
8476
|
-
type:
|
|
8939
|
+
type: import_types21.NodeType.SymbolNode,
|
|
8477
8940
|
kind: def.kind,
|
|
8478
8941
|
qualname: def.qualname,
|
|
8479
8942
|
span: { startLine: def.startLine, endLine: def.endLine },
|
|
@@ -8484,15 +8947,15 @@ async function addSymbols(graph, services) {
|
|
|
8484
8947
|
graph.addNode(sid, node);
|
|
8485
8948
|
nodesAdded++;
|
|
8486
8949
|
}
|
|
8487
|
-
const containsId = (0,
|
|
8950
|
+
const containsId = (0, import_types21.extractedEdgeId)(fileNodeId, sid, import_types21.EdgeType.CONTAINS);
|
|
8488
8951
|
if (!graph.hasEdge(containsId)) {
|
|
8489
8952
|
const edge = {
|
|
8490
8953
|
id: containsId,
|
|
8491
8954
|
source: fileNodeId,
|
|
8492
8955
|
target: sid,
|
|
8493
|
-
type:
|
|
8494
|
-
provenance:
|
|
8495
|
-
confidence: (0,
|
|
8956
|
+
type: import_types21.EdgeType.CONTAINS,
|
|
8957
|
+
provenance: import_types21.Provenance.EXTRACTED,
|
|
8958
|
+
confidence: (0, import_types21.confidenceForExtracted)("structural"),
|
|
8496
8959
|
evidence: {
|
|
8497
8960
|
file: relPath,
|
|
8498
8961
|
line: def.startLine,
|
|
@@ -8510,9 +8973,9 @@ async function addSymbols(graph, services) {
|
|
|
8510
8973
|
|
|
8511
8974
|
// src/extract/symbol-edges.ts
|
|
8512
8975
|
init_cjs_shims();
|
|
8513
|
-
var
|
|
8976
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
8514
8977
|
var import_tree_sitter4 = __toESM(require("tree-sitter"), 1);
|
|
8515
|
-
var
|
|
8978
|
+
var import_types22 = require("@neat.is/types");
|
|
8516
8979
|
function extendsInfo(classHeritage) {
|
|
8517
8980
|
for (let i = 0; i < classHeritage.namedChildCount; i++) {
|
|
8518
8981
|
const child = classHeritage.namedChild(i);
|
|
@@ -8615,12 +9078,12 @@ async function addSymbolEdges(graph, services) {
|
|
|
8615
9078
|
for (const service of services) {
|
|
8616
9079
|
const serviceName = service.pkg.name;
|
|
8617
9080
|
const tsPaths = await loadTsPathConfig(service.dir);
|
|
8618
|
-
const files = await loadSourceFiles(service.dir);
|
|
9081
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
8619
9082
|
for (const file of files) {
|
|
8620
|
-
const parser = parserForExt5(
|
|
9083
|
+
const parser = parserForExt5(import_node_path26.default.extname(file.path));
|
|
8621
9084
|
if (!parser) continue;
|
|
8622
|
-
const relPath = toPosix(
|
|
8623
|
-
const fileDir =
|
|
9085
|
+
const relPath = toPosix(import_node_path26.default.relative(service.dir, file.path));
|
|
9086
|
+
const fileDir = import_node_path26.default.dirname(file.path);
|
|
8624
9087
|
let root;
|
|
8625
9088
|
try {
|
|
8626
9089
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -8630,7 +9093,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
8630
9093
|
}
|
|
8631
9094
|
const disambiguated = disambiguate(collectSymbolDefs(root));
|
|
8632
9095
|
const locals = disambiguated.map(({ def, disambiguator }) => ({
|
|
8633
|
-
sid: (0,
|
|
9096
|
+
sid: (0, import_types22.symbolId)(serviceName, relPath, def.qualname, disambiguator),
|
|
8634
9097
|
qualname: def.qualname,
|
|
8635
9098
|
kind: def.kind,
|
|
8636
9099
|
startLine: def.startLine,
|
|
@@ -8659,10 +9122,10 @@ async function addSymbolEdges(graph, services) {
|
|
|
8659
9122
|
if (local) return local.kind === wantKind ? local.sid : null;
|
|
8660
9123
|
const imp = resolvedImports.get(name);
|
|
8661
9124
|
if (imp) {
|
|
8662
|
-
const candidate = (0,
|
|
9125
|
+
const candidate = (0, import_types22.symbolId)(serviceName, imp.targetRelPath, imp.importedName);
|
|
8663
9126
|
if (graph.hasNode(candidate)) {
|
|
8664
9127
|
const node = graph.getNodeAttributes(candidate);
|
|
8665
|
-
if (node.type ===
|
|
9128
|
+
if (node.type === import_types22.NodeType.SymbolNode && node.kind === wantKind) return candidate;
|
|
8666
9129
|
}
|
|
8667
9130
|
}
|
|
8668
9131
|
return null;
|
|
@@ -8689,7 +9152,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
8689
9152
|
sourceSid: self.sid,
|
|
8690
9153
|
targetName: ext.name,
|
|
8691
9154
|
wantKind: "class",
|
|
8692
|
-
edgeType:
|
|
9155
|
+
edgeType: import_types22.EdgeType.INHERITS,
|
|
8693
9156
|
line: ext.line
|
|
8694
9157
|
});
|
|
8695
9158
|
}
|
|
@@ -8698,7 +9161,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
8698
9161
|
sourceSid: self.sid,
|
|
8699
9162
|
targetName: impl.name,
|
|
8700
9163
|
wantKind: "class",
|
|
8701
|
-
edgeType:
|
|
9164
|
+
edgeType: import_types22.EdgeType.IMPLEMENTS,
|
|
8702
9165
|
line: impl.line
|
|
8703
9166
|
});
|
|
8704
9167
|
}
|
|
@@ -8714,7 +9177,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
8714
9177
|
sourceSid: caller.sid,
|
|
8715
9178
|
targetName: fn.text,
|
|
8716
9179
|
wantKind: "function",
|
|
8717
|
-
edgeType:
|
|
9180
|
+
edgeType: import_types22.EdgeType.CALLS,
|
|
8718
9181
|
line
|
|
8719
9182
|
});
|
|
8720
9183
|
}
|
|
@@ -8730,15 +9193,15 @@ async function addSymbolEdges(graph, services) {
|
|
|
8730
9193
|
const targetSid = resolveTarget(req.targetName, req.wantKind);
|
|
8731
9194
|
if (!targetSid) continue;
|
|
8732
9195
|
if (targetSid === req.sourceSid) continue;
|
|
8733
|
-
const edgeId = (0,
|
|
9196
|
+
const edgeId = (0, import_types22.extractedEdgeId)(req.sourceSid, targetSid, req.edgeType);
|
|
8734
9197
|
if (graph.hasEdge(edgeId)) continue;
|
|
8735
9198
|
const edge = {
|
|
8736
9199
|
id: edgeId,
|
|
8737
9200
|
source: req.sourceSid,
|
|
8738
9201
|
target: targetSid,
|
|
8739
9202
|
type: req.edgeType,
|
|
8740
|
-
provenance:
|
|
8741
|
-
confidence: (0,
|
|
9203
|
+
provenance: import_types22.Provenance.EXTRACTED,
|
|
9204
|
+
confidence: (0, import_types22.confidenceForExtracted)("structural"),
|
|
8742
9205
|
evidence: {
|
|
8743
9206
|
file: relPath,
|
|
8744
9207
|
line: req.line,
|
|
@@ -8755,9 +9218,9 @@ async function addSymbolEdges(graph, services) {
|
|
|
8755
9218
|
|
|
8756
9219
|
// src/extract/actions.ts
|
|
8757
9220
|
init_cjs_shims();
|
|
8758
|
-
var
|
|
9221
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
8759
9222
|
var import_tree_sitter5 = __toESM(require("tree-sitter"), 1);
|
|
8760
|
-
var
|
|
9223
|
+
var import_types23 = require("@neat.is/types");
|
|
8761
9224
|
function stringLiteralText2(node) {
|
|
8762
9225
|
for (let i = 0; i < node.childCount; i++) {
|
|
8763
9226
|
const child = node.child(i);
|
|
@@ -8899,12 +9362,12 @@ async function addServerActions(graph, services) {
|
|
|
8899
9362
|
};
|
|
8900
9363
|
if (deps["next"] === void 0) continue;
|
|
8901
9364
|
const tsPaths = await loadTsPathConfig(service.dir);
|
|
8902
|
-
const files = await loadSourceFiles(service.dir);
|
|
9365
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
8903
9366
|
for (const file of files) {
|
|
8904
9367
|
if (isTestPath(file.path)) continue;
|
|
8905
|
-
const parser = parserForExt5(
|
|
9368
|
+
const parser = parserForExt5(import_node_path27.default.extname(file.path));
|
|
8906
9369
|
if (!parser) continue;
|
|
8907
|
-
const relPath = toPosix(
|
|
9370
|
+
const relPath = toPosix(import_node_path27.default.relative(service.dir, file.path));
|
|
8908
9371
|
let root;
|
|
8909
9372
|
try {
|
|
8910
9373
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -8927,11 +9390,11 @@ async function addServerActions(graph, services) {
|
|
|
8927
9390
|
nodesAdded += fn;
|
|
8928
9391
|
edgesAdded += fe;
|
|
8929
9392
|
for (const action of actions) {
|
|
8930
|
-
const aid = (0,
|
|
9393
|
+
const aid = (0, import_types23.serverActionId)(service.pkg.name, relPath, action.exportName);
|
|
8931
9394
|
if (!graph.hasNode(aid)) {
|
|
8932
9395
|
const node = {
|
|
8933
9396
|
id: aid,
|
|
8934
|
-
type:
|
|
9397
|
+
type: import_types23.NodeType.ServerActionNode,
|
|
8935
9398
|
name: action.exportName,
|
|
8936
9399
|
service: service.pkg.name,
|
|
8937
9400
|
module: relPath,
|
|
@@ -8943,15 +9406,15 @@ async function addServerActions(graph, services) {
|
|
|
8943
9406
|
graph.addNode(aid, node);
|
|
8944
9407
|
nodesAdded++;
|
|
8945
9408
|
}
|
|
8946
|
-
const containsId = (0,
|
|
9409
|
+
const containsId = (0, import_types23.extractedEdgeId)(fileNodeId, aid, import_types23.EdgeType.CONTAINS);
|
|
8947
9410
|
if (!graph.hasEdge(containsId)) {
|
|
8948
9411
|
const edge = {
|
|
8949
9412
|
id: containsId,
|
|
8950
9413
|
source: fileNodeId,
|
|
8951
9414
|
target: aid,
|
|
8952
|
-
type:
|
|
8953
|
-
provenance:
|
|
8954
|
-
confidence: (0,
|
|
9415
|
+
type: import_types23.EdgeType.CONTAINS,
|
|
9416
|
+
provenance: import_types23.Provenance.EXTRACTED,
|
|
9417
|
+
confidence: (0, import_types23.confidenceForExtracted)("structural"),
|
|
8955
9418
|
evidence: {
|
|
8956
9419
|
file: relPath,
|
|
8957
9420
|
line: action.line,
|
|
@@ -8965,10 +9428,10 @@ async function addServerActions(graph, services) {
|
|
|
8965
9428
|
}
|
|
8966
9429
|
for (const file of files) {
|
|
8967
9430
|
if (isTestPath(file.path)) continue;
|
|
8968
|
-
const parser = parserForExt5(
|
|
9431
|
+
const parser = parserForExt5(import_node_path27.default.extname(file.path));
|
|
8969
9432
|
if (!parser) continue;
|
|
8970
|
-
const relPath = toPosix(
|
|
8971
|
-
const fileDir =
|
|
9433
|
+
const relPath = toPosix(import_node_path27.default.relative(service.dir, file.path));
|
|
9434
|
+
const fileDir = import_node_path27.default.dirname(file.path);
|
|
8972
9435
|
let root;
|
|
8973
9436
|
try {
|
|
8974
9437
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -8981,7 +9444,7 @@ async function addServerActions(graph, services) {
|
|
|
8981
9444
|
for (const [local, binding] of bindings) {
|
|
8982
9445
|
const target = await resolveJsImport(binding.specifier, fileDir, service.dir, tsPaths);
|
|
8983
9446
|
if (!target) continue;
|
|
8984
|
-
const aid = (0,
|
|
9447
|
+
const aid = (0, import_types23.serverActionId)(service.pkg.name, target, binding.importedName);
|
|
8985
9448
|
if (graph.hasNode(aid)) actionBindings.set(local, aid);
|
|
8986
9449
|
}
|
|
8987
9450
|
if (actionBindings.size === 0) continue;
|
|
@@ -8996,15 +9459,15 @@ async function addServerActions(graph, services) {
|
|
|
8996
9459
|
nodesAdded += ensured.nodesAdded;
|
|
8997
9460
|
edgesAdded += ensured.edgesAdded;
|
|
8998
9461
|
}
|
|
8999
|
-
const callsId = (0,
|
|
9462
|
+
const callsId = (0, import_types23.extractedEdgeId)(clientFileId, aid, import_types23.EdgeType.CALLS);
|
|
9000
9463
|
if (graph.hasEdge(callsId)) continue;
|
|
9001
9464
|
const edge = {
|
|
9002
9465
|
id: callsId,
|
|
9003
9466
|
source: clientFileId,
|
|
9004
9467
|
target: aid,
|
|
9005
|
-
type:
|
|
9006
|
-
provenance:
|
|
9007
|
-
confidence: (0,
|
|
9468
|
+
type: import_types23.EdgeType.CALLS,
|
|
9469
|
+
provenance: import_types23.Provenance.EXTRACTED,
|
|
9470
|
+
confidence: (0, import_types23.confidenceForExtracted)("structural"),
|
|
9008
9471
|
evidence: {
|
|
9009
9472
|
file: relPath,
|
|
9010
9473
|
line,
|
|
@@ -9021,14 +9484,14 @@ async function addServerActions(graph, services) {
|
|
|
9021
9484
|
|
|
9022
9485
|
// src/extract/databases/index.ts
|
|
9023
9486
|
init_cjs_shims();
|
|
9024
|
-
var
|
|
9025
|
-
var
|
|
9487
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
9488
|
+
var import_types24 = require("@neat.is/types");
|
|
9026
9489
|
|
|
9027
9490
|
// src/extract/databases/db-config-yaml.ts
|
|
9028
9491
|
init_cjs_shims();
|
|
9029
|
-
var
|
|
9492
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
9030
9493
|
async function parse(serviceDir) {
|
|
9031
|
-
const yamlPath =
|
|
9494
|
+
const yamlPath = import_node_path28.default.join(serviceDir, "db-config.yaml");
|
|
9032
9495
|
if (!await exists2(yamlPath)) return [];
|
|
9033
9496
|
const raw = await readYaml(yamlPath);
|
|
9034
9497
|
return [
|
|
@@ -9046,13 +9509,13 @@ var dbConfigYamlParser = { name: "db-config.yaml", parse };
|
|
|
9046
9509
|
|
|
9047
9510
|
// src/extract/databases/dotenv.ts
|
|
9048
9511
|
init_cjs_shims();
|
|
9049
|
-
var
|
|
9050
|
-
var
|
|
9512
|
+
var import_node_fs23 = require("fs");
|
|
9513
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
9051
9514
|
|
|
9052
9515
|
// src/extract/databases/shared.ts
|
|
9053
9516
|
init_cjs_shims();
|
|
9054
|
-
var
|
|
9055
|
-
var
|
|
9517
|
+
var import_node_fs22 = require("fs");
|
|
9518
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
9056
9519
|
function schemeToEngine(scheme) {
|
|
9057
9520
|
const s = scheme.toLowerCase().split("+")[0];
|
|
9058
9521
|
switch (s) {
|
|
@@ -9091,18 +9554,18 @@ function parseConnectionString(url) {
|
|
|
9091
9554
|
}
|
|
9092
9555
|
async function readIfExists(filePath) {
|
|
9093
9556
|
try {
|
|
9094
|
-
return await
|
|
9557
|
+
return await import_node_fs22.promises.readFile(filePath, "utf8");
|
|
9095
9558
|
} catch {
|
|
9096
9559
|
return null;
|
|
9097
9560
|
}
|
|
9098
9561
|
}
|
|
9099
9562
|
async function resolveEnvVar(serviceDir, name) {
|
|
9100
|
-
const entries = await
|
|
9563
|
+
const entries = await import_node_fs22.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
9101
9564
|
const envNames = entries.filter((e) => e.isFile() && (e.name === ".env" || e.name.startsWith(".env."))).map((e) => e.name);
|
|
9102
9565
|
const rank = (n) => n === ".env.local" ? 0 : n === ".env" ? 1 : 2;
|
|
9103
9566
|
envNames.sort((a, b) => rank(a) - rank(b) || a.localeCompare(b));
|
|
9104
9567
|
for (const fileName of envNames) {
|
|
9105
|
-
const content = await readIfExists(
|
|
9568
|
+
const content = await readIfExists(import_node_path29.default.join(serviceDir, fileName));
|
|
9106
9569
|
if (!content) continue;
|
|
9107
9570
|
for (const line of content.split("\n")) {
|
|
9108
9571
|
const trimmed = line.trim();
|
|
@@ -9121,7 +9584,7 @@ async function resolveEnvVar(serviceDir, name) {
|
|
|
9121
9584
|
}
|
|
9122
9585
|
async function findFirst(serviceDir, candidates) {
|
|
9123
9586
|
for (const rel of candidates) {
|
|
9124
|
-
const abs =
|
|
9587
|
+
const abs = import_node_path29.default.join(serviceDir, rel);
|
|
9125
9588
|
const content = await readIfExists(abs);
|
|
9126
9589
|
if (content !== null) return abs;
|
|
9127
9590
|
}
|
|
@@ -9179,15 +9642,15 @@ function parseDotenvLine(line) {
|
|
|
9179
9642
|
return { key, value };
|
|
9180
9643
|
}
|
|
9181
9644
|
async function parse2(serviceDir) {
|
|
9182
|
-
const entries = await
|
|
9645
|
+
const entries = await import_node_fs23.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
9183
9646
|
const configs = [];
|
|
9184
9647
|
const seen = /* @__PURE__ */ new Set();
|
|
9185
9648
|
for (const entry of entries) {
|
|
9186
9649
|
if (!entry.isFile()) continue;
|
|
9187
9650
|
const match = isConfigFile(entry.name);
|
|
9188
9651
|
if (!match.match || match.fileType !== "env") continue;
|
|
9189
|
-
const filePath =
|
|
9190
|
-
const content = await
|
|
9652
|
+
const filePath = import_node_path30.default.join(serviceDir, entry.name);
|
|
9653
|
+
const content = await import_node_fs23.promises.readFile(filePath, "utf8");
|
|
9191
9654
|
for (const line of content.split("\n")) {
|
|
9192
9655
|
const parsed = parseDotenvLine(line);
|
|
9193
9656
|
if (!parsed) continue;
|
|
@@ -9206,9 +9669,9 @@ var dotenvParser = { name: ".env", parse: parse2 };
|
|
|
9206
9669
|
|
|
9207
9670
|
// src/extract/databases/prisma.ts
|
|
9208
9671
|
init_cjs_shims();
|
|
9209
|
-
var
|
|
9672
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
9210
9673
|
async function parse3(serviceDir) {
|
|
9211
|
-
const schemaPath =
|
|
9674
|
+
const schemaPath = import_node_path31.default.join(serviceDir, "prisma", "schema.prisma");
|
|
9212
9675
|
const content = await readIfExists(schemaPath);
|
|
9213
9676
|
if (!content) return [];
|
|
9214
9677
|
const block = content.match(/datasource\s+\w+\s*\{([^}]*)\}/s);
|
|
@@ -9366,10 +9829,10 @@ var knexParser = { name: "knex", parse: parse5 };
|
|
|
9366
9829
|
|
|
9367
9830
|
// src/extract/databases/ormconfig.ts
|
|
9368
9831
|
init_cjs_shims();
|
|
9369
|
-
var
|
|
9832
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
9370
9833
|
async function parse6(serviceDir) {
|
|
9371
9834
|
for (const candidate of ["ormconfig.json", "ormconfig.yaml", "ormconfig.yml"]) {
|
|
9372
|
-
const abs =
|
|
9835
|
+
const abs = import_node_path32.default.join(serviceDir, candidate);
|
|
9373
9836
|
if (!await exists2(abs)) continue;
|
|
9374
9837
|
const raw = candidate.endsWith(".json") ? await readJson(abs) : await readYaml(abs);
|
|
9375
9838
|
const entries = Array.isArray(raw) ? raw : [raw];
|
|
@@ -9429,9 +9892,9 @@ var typeormParser = { name: "typeorm", parse: parse7 };
|
|
|
9429
9892
|
|
|
9430
9893
|
// src/extract/databases/sequelize.ts
|
|
9431
9894
|
init_cjs_shims();
|
|
9432
|
-
var
|
|
9895
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
9433
9896
|
async function parse8(serviceDir) {
|
|
9434
|
-
const configPath =
|
|
9897
|
+
const configPath = import_node_path33.default.join(serviceDir, "config", "config.json");
|
|
9435
9898
|
if (!await exists2(configPath)) return [];
|
|
9436
9899
|
const raw = await readJson(configPath);
|
|
9437
9900
|
const out = [];
|
|
@@ -9458,7 +9921,7 @@ var sequelizeParser = { name: "sequelize", parse: parse8 };
|
|
|
9458
9921
|
|
|
9459
9922
|
// src/extract/databases/docker-compose.ts
|
|
9460
9923
|
init_cjs_shims();
|
|
9461
|
-
var
|
|
9924
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
9462
9925
|
function portFromService(svc) {
|
|
9463
9926
|
for (const raw of svc.ports ?? []) {
|
|
9464
9927
|
const str = String(raw);
|
|
@@ -9485,7 +9948,7 @@ function databaseFromEnv(svc) {
|
|
|
9485
9948
|
}
|
|
9486
9949
|
async function parse9(serviceDir) {
|
|
9487
9950
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
9488
|
-
const abs =
|
|
9951
|
+
const abs = import_node_path34.default.join(serviceDir, name);
|
|
9489
9952
|
if (!await exists2(abs)) continue;
|
|
9490
9953
|
const raw = await readYaml(abs);
|
|
9491
9954
|
if (!raw?.services) return [];
|
|
@@ -9526,8 +9989,8 @@ function compatibleDriversFor(engine) {
|
|
|
9526
9989
|
}
|
|
9527
9990
|
function toDatabaseNode(config) {
|
|
9528
9991
|
return {
|
|
9529
|
-
id: (0,
|
|
9530
|
-
type:
|
|
9992
|
+
id: (0, import_types24.databaseId)(config.host),
|
|
9993
|
+
type: import_types24.NodeType.DatabaseNode,
|
|
9531
9994
|
name: config.database || config.host,
|
|
9532
9995
|
engine: config.engine,
|
|
9533
9996
|
engineVersion: config.engineVersion,
|
|
@@ -9657,7 +10120,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
9657
10120
|
discoveredVia: mergedDiscoveredVia
|
|
9658
10121
|
});
|
|
9659
10122
|
}
|
|
9660
|
-
const relConfigFile = toPosix(
|
|
10123
|
+
const relConfigFile = toPosix(import_node_path35.default.relative(service.dir, config.sourceFile));
|
|
9661
10124
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
9662
10125
|
graph,
|
|
9663
10126
|
service.pkg.name,
|
|
@@ -9666,14 +10129,14 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
9666
10129
|
);
|
|
9667
10130
|
nodesAdded += fn;
|
|
9668
10131
|
edgesAdded += fe;
|
|
9669
|
-
const evidenceFile = toPosix(
|
|
10132
|
+
const evidenceFile = toPosix(import_node_path35.default.relative(scanPath, config.sourceFile));
|
|
9670
10133
|
const edge = {
|
|
9671
|
-
id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id,
|
|
10134
|
+
id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id, import_types24.EdgeType.CONNECTS_TO),
|
|
9672
10135
|
source: fileNodeId,
|
|
9673
10136
|
target: dbNode.id,
|
|
9674
|
-
type:
|
|
9675
|
-
provenance:
|
|
9676
|
-
confidence: (0,
|
|
10137
|
+
type: import_types24.EdgeType.CONNECTS_TO,
|
|
10138
|
+
provenance: import_types24.Provenance.EXTRACTED,
|
|
10139
|
+
confidence: (0, import_types24.confidenceForExtracted)("structural"),
|
|
9677
10140
|
evidence: { file: evidenceFile }
|
|
9678
10141
|
};
|
|
9679
10142
|
if (!graph.hasEdge(edge.id)) {
|
|
@@ -9684,26 +10147,26 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
9684
10147
|
if (allConfigs.length === 1) {
|
|
9685
10148
|
const primary = allConfigs[0];
|
|
9686
10149
|
service.node.dbConnectionTarget = primary.port ? `${primary.host}:${primary.port}` : primary.host;
|
|
9687
|
-
const relPath =
|
|
9688
|
-
const cfgId = (0,
|
|
10150
|
+
const relPath = import_node_path35.default.relative(scanPath, primary.sourceFile);
|
|
10151
|
+
const cfgId = (0, import_types24.configId)(relPath);
|
|
9689
10152
|
if (!graph.hasNode(cfgId)) {
|
|
9690
10153
|
const cfgNode = {
|
|
9691
10154
|
id: cfgId,
|
|
9692
|
-
type:
|
|
9693
|
-
name:
|
|
10155
|
+
type: import_types24.NodeType.ConfigNode,
|
|
10156
|
+
name: import_node_path35.default.basename(primary.sourceFile),
|
|
9694
10157
|
path: relPath,
|
|
9695
|
-
fileType: isConfigFile(
|
|
10158
|
+
fileType: isConfigFile(import_node_path35.default.basename(primary.sourceFile)).fileType || "config"
|
|
9696
10159
|
};
|
|
9697
10160
|
graph.addNode(cfgId, cfgNode);
|
|
9698
10161
|
nodesAdded++;
|
|
9699
10162
|
}
|
|
9700
10163
|
const cfgEdge = {
|
|
9701
|
-
id: (0, import_types3.extractedEdgeId)(service.node.id, cfgId,
|
|
10164
|
+
id: (0, import_types3.extractedEdgeId)(service.node.id, cfgId, import_types24.EdgeType.CONFIGURED_BY),
|
|
9702
10165
|
source: service.node.id,
|
|
9703
10166
|
target: cfgId,
|
|
9704
|
-
type:
|
|
9705
|
-
provenance:
|
|
9706
|
-
confidence: (0,
|
|
10167
|
+
type: import_types24.EdgeType.CONFIGURED_BY,
|
|
10168
|
+
provenance: import_types24.Provenance.EXTRACTED,
|
|
10169
|
+
confidence: (0, import_types24.confidenceForExtracted)("structural"),
|
|
9707
10170
|
evidence: { file: toPosix(relPath) }
|
|
9708
10171
|
};
|
|
9709
10172
|
if (!graph.hasEdge(cfgEdge.id)) {
|
|
@@ -9733,17 +10196,19 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
9733
10196
|
|
|
9734
10197
|
// src/extract/configs.ts
|
|
9735
10198
|
init_cjs_shims();
|
|
9736
|
-
var
|
|
9737
|
-
var
|
|
9738
|
-
var
|
|
9739
|
-
async function walkConfigFiles(dir) {
|
|
10199
|
+
var import_node_fs24 = require("fs");
|
|
10200
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
10201
|
+
var import_types25 = require("@neat.is/types");
|
|
10202
|
+
async function walkConfigFiles(dir, excludeDirs = []) {
|
|
10203
|
+
const excluded = new Set(excludeDirs.map((d) => import_node_path36.default.resolve(d)));
|
|
9740
10204
|
const out = [];
|
|
9741
10205
|
async function walk9(current) {
|
|
9742
|
-
const entries = await
|
|
10206
|
+
const entries = await import_node_fs24.promises.readdir(current, { withFileTypes: true });
|
|
9743
10207
|
for (const entry of entries) {
|
|
9744
|
-
const full =
|
|
10208
|
+
const full = import_node_path36.default.join(current, entry.name);
|
|
9745
10209
|
if (entry.isDirectory()) {
|
|
9746
10210
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
10211
|
+
if (excluded.has(import_node_path36.default.resolve(full))) continue;
|
|
9747
10212
|
if (await isPythonVenvDir(full)) continue;
|
|
9748
10213
|
await walk9(full);
|
|
9749
10214
|
} else if (entry.isFile() && isConfigFile(entry.name).match) {
|
|
@@ -9758,21 +10223,21 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
9758
10223
|
let nodesAdded = 0;
|
|
9759
10224
|
let edgesAdded = 0;
|
|
9760
10225
|
for (const service of services) {
|
|
9761
|
-
const configFiles = await walkConfigFiles(service.dir);
|
|
10226
|
+
const configFiles = await walkConfigFiles(service.dir, service.excludeDirs);
|
|
9762
10227
|
for (const file of configFiles) {
|
|
9763
|
-
const relPath =
|
|
10228
|
+
const relPath = import_node_path36.default.relative(scanPath, file);
|
|
9764
10229
|
const node = {
|
|
9765
|
-
id: (0,
|
|
9766
|
-
type:
|
|
9767
|
-
name:
|
|
10230
|
+
id: (0, import_types25.configId)(relPath),
|
|
10231
|
+
type: import_types25.NodeType.ConfigNode,
|
|
10232
|
+
name: import_node_path36.default.basename(file),
|
|
9768
10233
|
path: relPath,
|
|
9769
|
-
fileType: isConfigFile(
|
|
10234
|
+
fileType: isConfigFile(import_node_path36.default.basename(file)).fileType
|
|
9770
10235
|
};
|
|
9771
10236
|
if (!graph.hasNode(node.id)) {
|
|
9772
10237
|
graph.addNode(node.id, node);
|
|
9773
10238
|
nodesAdded++;
|
|
9774
10239
|
}
|
|
9775
|
-
const relToService = toPosix(
|
|
10240
|
+
const relToService = toPosix(import_node_path36.default.relative(service.dir, file));
|
|
9776
10241
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
9777
10242
|
graph,
|
|
9778
10243
|
service.pkg.name,
|
|
@@ -9782,13 +10247,13 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
9782
10247
|
nodesAdded += fn;
|
|
9783
10248
|
edgesAdded += fe;
|
|
9784
10249
|
const edge = {
|
|
9785
|
-
id: (0, import_types3.extractedEdgeId)(fileNodeId, node.id,
|
|
10250
|
+
id: (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types25.EdgeType.CONFIGURED_BY),
|
|
9786
10251
|
source: fileNodeId,
|
|
9787
10252
|
target: node.id,
|
|
9788
|
-
type:
|
|
9789
|
-
provenance:
|
|
9790
|
-
confidence: (0,
|
|
9791
|
-
evidence: { file: relPath.split(
|
|
10253
|
+
type: import_types25.EdgeType.CONFIGURED_BY,
|
|
10254
|
+
provenance: import_types25.Provenance.EXTRACTED,
|
|
10255
|
+
confidence: (0, import_types25.confidenceForExtracted)("structural"),
|
|
10256
|
+
evidence: { file: relPath.split(import_node_path36.default.sep).join("/") }
|
|
9792
10257
|
};
|
|
9793
10258
|
if (!graph.hasEdge(edge.id)) {
|
|
9794
10259
|
graph.addEdgeWithKey(edge.id, edge.source, edge.target, edge);
|
|
@@ -9801,9 +10266,9 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
9801
10266
|
|
|
9802
10267
|
// src/extract/proto.ts
|
|
9803
10268
|
init_cjs_shims();
|
|
9804
|
-
var
|
|
9805
|
-
var
|
|
9806
|
-
var
|
|
10269
|
+
var import_node_fs25 = require("fs");
|
|
10270
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
10271
|
+
var import_types26 = require("@neat.is/types");
|
|
9807
10272
|
var PROTO_EXTENSION = ".proto";
|
|
9808
10273
|
function packageOf(content) {
|
|
9809
10274
|
const m = content.match(/^\s*package\s+([A-Za-z_][A-Za-z0-9_.]*)\s*;/m);
|
|
@@ -9839,17 +10304,19 @@ function grpcMethodsFromProto(content, fqPackage) {
|
|
|
9839
10304
|
}
|
|
9840
10305
|
return out;
|
|
9841
10306
|
}
|
|
9842
|
-
async function walkProtoFiles(dir) {
|
|
10307
|
+
async function walkProtoFiles(dir, excludeDirs = []) {
|
|
10308
|
+
const excluded = new Set(excludeDirs.map((d) => import_node_path37.default.resolve(d)));
|
|
9843
10309
|
const out = [];
|
|
9844
10310
|
async function walk9(current) {
|
|
9845
|
-
const entries = await
|
|
10311
|
+
const entries = await import_node_fs25.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
9846
10312
|
for (const entry of entries) {
|
|
9847
|
-
const full =
|
|
10313
|
+
const full = import_node_path37.default.join(current, entry.name);
|
|
9848
10314
|
if (entry.isDirectory()) {
|
|
9849
10315
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
10316
|
+
if (excluded.has(import_node_path37.default.resolve(full))) continue;
|
|
9850
10317
|
if (await isPythonVenvDir(full)) continue;
|
|
9851
10318
|
await walk9(full);
|
|
9852
|
-
} else if (entry.isFile() &&
|
|
10319
|
+
} else if (entry.isFile() && import_node_path37.default.extname(entry.name) === PROTO_EXTENSION) {
|
|
9853
10320
|
out.push(full);
|
|
9854
10321
|
}
|
|
9855
10322
|
}
|
|
@@ -9861,13 +10328,13 @@ async function addGrpcMethods(graph, services) {
|
|
|
9861
10328
|
let nodesAdded = 0;
|
|
9862
10329
|
let edgesAdded = 0;
|
|
9863
10330
|
for (const service of services) {
|
|
9864
|
-
const protoPaths = await walkProtoFiles(service.dir);
|
|
10331
|
+
const protoPaths = await walkProtoFiles(service.dir, service.excludeDirs);
|
|
9865
10332
|
for (const protoPath of protoPaths) {
|
|
9866
10333
|
if (isTestPath(protoPath)) continue;
|
|
9867
|
-
const relFile = toPosix(
|
|
10334
|
+
const relFile = toPosix(import_node_path37.default.relative(service.dir, protoPath));
|
|
9868
10335
|
let content;
|
|
9869
10336
|
try {
|
|
9870
|
-
content = await
|
|
10337
|
+
content = await import_node_fs25.promises.readFile(protoPath, "utf8");
|
|
9871
10338
|
} catch (err) {
|
|
9872
10339
|
recordExtractionError("proto extraction", protoPath, err);
|
|
9873
10340
|
continue;
|
|
@@ -9881,11 +10348,11 @@ async function addGrpcMethods(graph, services) {
|
|
|
9881
10348
|
}
|
|
9882
10349
|
if (methods.length === 0) continue;
|
|
9883
10350
|
for (const method of methods) {
|
|
9884
|
-
const mid = (0,
|
|
10351
|
+
const mid = (0, import_types26.grpcMethodId)(method.rpcService, method.rpcMethod);
|
|
9885
10352
|
if (!graph.hasNode(mid)) {
|
|
9886
10353
|
const node = {
|
|
9887
10354
|
id: mid,
|
|
9888
|
-
type:
|
|
10355
|
+
type: import_types26.NodeType.GrpcMethodNode,
|
|
9889
10356
|
name: `${method.rpcService}/${method.rpcMethod}`,
|
|
9890
10357
|
rpcService: method.rpcService,
|
|
9891
10358
|
rpcMethod: method.rpcMethod,
|
|
@@ -9896,15 +10363,15 @@ async function addGrpcMethods(graph, services) {
|
|
|
9896
10363
|
graph.addNode(mid, node);
|
|
9897
10364
|
nodesAdded++;
|
|
9898
10365
|
}
|
|
9899
|
-
const containsId = (0,
|
|
10366
|
+
const containsId = (0, import_types26.extractedEdgeId)(service.node.id, mid, import_types26.EdgeType.CONTAINS);
|
|
9900
10367
|
if (!graph.hasEdge(containsId)) {
|
|
9901
10368
|
const edge = {
|
|
9902
10369
|
id: containsId,
|
|
9903
10370
|
source: service.node.id,
|
|
9904
10371
|
target: mid,
|
|
9905
|
-
type:
|
|
9906
|
-
provenance:
|
|
9907
|
-
confidence: (0,
|
|
10372
|
+
type: import_types26.EdgeType.CONTAINS,
|
|
10373
|
+
provenance: import_types26.Provenance.EXTRACTED,
|
|
10374
|
+
confidence: (0, import_types26.confidenceForExtracted)("structural"),
|
|
9908
10375
|
evidence: {
|
|
9909
10376
|
file: relFile,
|
|
9910
10377
|
line: method.line,
|
|
@@ -9922,16 +10389,16 @@ async function addGrpcMethods(graph, services) {
|
|
|
9922
10389
|
|
|
9923
10390
|
// src/extract/calls/index.ts
|
|
9924
10391
|
init_cjs_shims();
|
|
9925
|
-
var
|
|
10392
|
+
var import_types44 = require("@neat.is/types");
|
|
9926
10393
|
|
|
9927
10394
|
// src/extract/calls/http.ts
|
|
9928
10395
|
init_cjs_shims();
|
|
9929
|
-
var
|
|
10396
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
9930
10397
|
var import_tree_sitter6 = __toESM(require("tree-sitter"), 1);
|
|
9931
10398
|
var import_tree_sitter_javascript4 = __toESM(require("tree-sitter-javascript"), 1);
|
|
9932
10399
|
var import_tree_sitter_typescript2 = __toESM(require("tree-sitter-typescript"), 1);
|
|
9933
10400
|
var import_tree_sitter_python4 = __toESM(require("tree-sitter-python"), 1);
|
|
9934
|
-
var
|
|
10401
|
+
var import_types27 = require("@neat.is/types");
|
|
9935
10402
|
var STRING_LITERAL_NODE_TYPES = /* @__PURE__ */ new Set(["string_fragment", "string_content"]);
|
|
9936
10403
|
var JSX_EXTERNAL_LINK_TAGS = /* @__PURE__ */ new Set(["a", "Link", "NavLink", "ExternalLink", "Anchor"]);
|
|
9937
10404
|
function isInsideJsxExternalLink(node) {
|
|
@@ -10005,11 +10472,11 @@ async function addHttpCallEdges(graph, services) {
|
|
|
10005
10472
|
let nodesAdded = 0;
|
|
10006
10473
|
let edgesAdded = 0;
|
|
10007
10474
|
for (const service of services) {
|
|
10008
|
-
const files = await loadSourceFiles(service.dir);
|
|
10475
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
10009
10476
|
const seen = /* @__PURE__ */ new Set();
|
|
10010
10477
|
for (const file of files) {
|
|
10011
10478
|
if (isTestPath(file.path)) continue;
|
|
10012
|
-
const parser = parserForExt(
|
|
10479
|
+
const parser = parserForExt(import_node_path38.default.extname(file.path), parserCache);
|
|
10013
10480
|
let sites;
|
|
10014
10481
|
try {
|
|
10015
10482
|
sites = callsFromSource(file.content, parser, knownHosts);
|
|
@@ -10018,14 +10485,14 @@ async function addHttpCallEdges(graph, services) {
|
|
|
10018
10485
|
continue;
|
|
10019
10486
|
}
|
|
10020
10487
|
if (sites.length === 0) continue;
|
|
10021
|
-
const relFile = toPosix(
|
|
10488
|
+
const relFile = toPosix(import_node_path38.default.relative(service.dir, file.path));
|
|
10022
10489
|
for (const site of sites) {
|
|
10023
10490
|
const targetId = hostToNodeId.get(site.host);
|
|
10024
10491
|
if (!targetId || targetId === service.node.id) continue;
|
|
10025
10492
|
const dedupKey = `${relFile}|${targetId}`;
|
|
10026
10493
|
if (seen.has(dedupKey)) continue;
|
|
10027
10494
|
seen.add(dedupKey);
|
|
10028
|
-
const confidence = (0,
|
|
10495
|
+
const confidence = (0, import_types27.confidenceForExtracted)("url-literal-service-target");
|
|
10029
10496
|
const ev = {
|
|
10030
10497
|
file: relFile,
|
|
10031
10498
|
line: site.line,
|
|
@@ -10039,25 +10506,25 @@ async function addHttpCallEdges(graph, services) {
|
|
|
10039
10506
|
);
|
|
10040
10507
|
nodesAdded += n;
|
|
10041
10508
|
edgesAdded += e;
|
|
10042
|
-
if (!(0,
|
|
10509
|
+
if (!(0, import_types27.passesExtractedFloor)(confidence)) {
|
|
10043
10510
|
noteExtractedDropped({
|
|
10044
10511
|
source: fileNodeId,
|
|
10045
10512
|
target: targetId,
|
|
10046
|
-
type:
|
|
10513
|
+
type: import_types27.EdgeType.CALLS,
|
|
10047
10514
|
confidence,
|
|
10048
10515
|
confidenceKind: "url-literal-service-target",
|
|
10049
10516
|
evidence: ev
|
|
10050
10517
|
});
|
|
10051
10518
|
continue;
|
|
10052
10519
|
}
|
|
10053
|
-
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, targetId,
|
|
10520
|
+
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, targetId, import_types27.EdgeType.CALLS);
|
|
10054
10521
|
if (!graph.hasEdge(edgeId)) {
|
|
10055
10522
|
const edge = {
|
|
10056
10523
|
id: edgeId,
|
|
10057
10524
|
source: fileNodeId,
|
|
10058
10525
|
target: targetId,
|
|
10059
|
-
type:
|
|
10060
|
-
provenance:
|
|
10526
|
+
type: import_types27.EdgeType.CALLS,
|
|
10527
|
+
provenance: import_types27.Provenance.EXTRACTED,
|
|
10061
10528
|
confidence,
|
|
10062
10529
|
evidence: ev
|
|
10063
10530
|
};
|
|
@@ -10072,10 +10539,10 @@ async function addHttpCallEdges(graph, services) {
|
|
|
10072
10539
|
|
|
10073
10540
|
// src/extract/calls/route-match.ts
|
|
10074
10541
|
init_cjs_shims();
|
|
10075
|
-
var
|
|
10542
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
10076
10543
|
var import_tree_sitter7 = __toESM(require("tree-sitter"), 1);
|
|
10077
10544
|
var import_tree_sitter_javascript5 = __toESM(require("tree-sitter-javascript"), 1);
|
|
10078
|
-
var
|
|
10545
|
+
var import_types28 = require("@neat.is/types");
|
|
10079
10546
|
var PARSE_CHUNK5 = 16384;
|
|
10080
10547
|
function parseSource5(parser, source) {
|
|
10081
10548
|
return parser.parse(
|
|
@@ -10240,9 +10707,9 @@ function buildRouteIndex(graph) {
|
|
|
10240
10707
|
const index = /* @__PURE__ */ new Map();
|
|
10241
10708
|
graph.forEachNode((_id, attrs) => {
|
|
10242
10709
|
const node = attrs;
|
|
10243
|
-
if (node.type !==
|
|
10710
|
+
if (node.type !== import_types28.NodeType.RouteNode) return;
|
|
10244
10711
|
const route = attrs;
|
|
10245
|
-
const owner = (0,
|
|
10712
|
+
const owner = (0, import_types28.serviceId)(route.service);
|
|
10246
10713
|
const entry = {
|
|
10247
10714
|
method: route.method.toUpperCase(),
|
|
10248
10715
|
normalizedPath: normalizePathTemplate(route.pathTemplate),
|
|
@@ -10267,11 +10734,11 @@ async function addRouteCallEdges(graph, services) {
|
|
|
10267
10734
|
let nodesAdded = 0;
|
|
10268
10735
|
let edgesAdded = 0;
|
|
10269
10736
|
for (const service of services) {
|
|
10270
|
-
const files = await loadSourceFiles(service.dir);
|
|
10737
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
10271
10738
|
const seen = /* @__PURE__ */ new Set();
|
|
10272
10739
|
for (const file of files) {
|
|
10273
10740
|
if (isTestPath(file.path)) continue;
|
|
10274
|
-
if (!JS_CLIENT_EXTENSIONS.has(
|
|
10741
|
+
if (!JS_CLIENT_EXTENSIONS.has(import_node_path39.default.extname(file.path))) continue;
|
|
10275
10742
|
let sites;
|
|
10276
10743
|
try {
|
|
10277
10744
|
sites = clientCallSitesFromSource(file.content, jsParser, knownHosts);
|
|
@@ -10280,7 +10747,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
10280
10747
|
continue;
|
|
10281
10748
|
}
|
|
10282
10749
|
if (sites.length === 0) continue;
|
|
10283
|
-
const relFile = toPosix(
|
|
10750
|
+
const relFile = toPosix(import_node_path39.default.relative(service.dir, file.path));
|
|
10284
10751
|
for (const site of sites) {
|
|
10285
10752
|
const serverServiceId = hostToNodeId.get(site.host);
|
|
10286
10753
|
if (!serverServiceId || serverServiceId === service.node.id) continue;
|
|
@@ -10300,7 +10767,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
10300
10767
|
);
|
|
10301
10768
|
nodesAdded += n;
|
|
10302
10769
|
edgesAdded += e;
|
|
10303
|
-
const confidence = (0,
|
|
10770
|
+
const confidence = (0, import_types28.confidenceForExtracted)("verified-call-site");
|
|
10304
10771
|
const ev = {
|
|
10305
10772
|
file: relFile,
|
|
10306
10773
|
line: site.line,
|
|
@@ -10308,25 +10775,25 @@ async function addRouteCallEdges(graph, services) {
|
|
|
10308
10775
|
method: site.method ?? match.method,
|
|
10309
10776
|
pathTemplate: site.pathTemplate
|
|
10310
10777
|
};
|
|
10311
|
-
if (!(0,
|
|
10778
|
+
if (!(0, import_types28.passesExtractedFloor)(confidence)) {
|
|
10312
10779
|
noteExtractedDropped({
|
|
10313
10780
|
source: fileNodeId,
|
|
10314
10781
|
target: match.routeNodeId,
|
|
10315
|
-
type:
|
|
10782
|
+
type: import_types28.EdgeType.CALLS,
|
|
10316
10783
|
confidence,
|
|
10317
10784
|
confidenceKind: "verified-call-site",
|
|
10318
10785
|
evidence: ev
|
|
10319
10786
|
});
|
|
10320
10787
|
continue;
|
|
10321
10788
|
}
|
|
10322
|
-
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, match.routeNodeId,
|
|
10789
|
+
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, match.routeNodeId, import_types28.EdgeType.CALLS);
|
|
10323
10790
|
if (!graph.hasEdge(edgeId)) {
|
|
10324
10791
|
const edge = {
|
|
10325
10792
|
id: edgeId,
|
|
10326
10793
|
source: fileNodeId,
|
|
10327
10794
|
target: match.routeNodeId,
|
|
10328
|
-
type:
|
|
10329
|
-
provenance:
|
|
10795
|
+
type: import_types28.EdgeType.CALLS,
|
|
10796
|
+
provenance: import_types28.Provenance.EXTRACTED,
|
|
10330
10797
|
confidence,
|
|
10331
10798
|
evidence: ev
|
|
10332
10799
|
};
|
|
@@ -10341,8 +10808,8 @@ async function addRouteCallEdges(graph, services) {
|
|
|
10341
10808
|
|
|
10342
10809
|
// src/extract/calls/kafka.ts
|
|
10343
10810
|
init_cjs_shims();
|
|
10344
|
-
var
|
|
10345
|
-
var
|
|
10811
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
10812
|
+
var import_types29 = require("@neat.is/types");
|
|
10346
10813
|
var PRODUCER_TOPIC_RE = /(?:producer|kafkaProducer)[\s\S]{0,40}?\.send\s*\(\s*\{[\s\S]{0,200}?topic\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
10347
10814
|
var CONSUMER_TOPIC_RE = /(?:consumer|kafkaConsumer)[\s\S]{0,40}?\.(?:subscribe|run)\s*\(\s*\{[\s\S]{0,200}?topic[s]?\s*:\s*(?:\[\s*)?['"`]([^'"`]+)['"`]/g;
|
|
10348
10815
|
function findAll(re, text) {
|
|
@@ -10363,7 +10830,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
10363
10830
|
seen.add(key);
|
|
10364
10831
|
const line = lineOf(file.content, topic);
|
|
10365
10832
|
out.push({
|
|
10366
|
-
infraId: (0,
|
|
10833
|
+
infraId: (0, import_types29.infraId)("kafka-topic", topic),
|
|
10367
10834
|
name: topic,
|
|
10368
10835
|
kind: "kafka-topic",
|
|
10369
10836
|
edgeType,
|
|
@@ -10372,7 +10839,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
10372
10839
|
// tier (ADR-066).
|
|
10373
10840
|
confidenceKind: "verified-call-site",
|
|
10374
10841
|
evidence: {
|
|
10375
|
-
file:
|
|
10842
|
+
file: import_node_path40.default.relative(serviceDir, file.path),
|
|
10376
10843
|
line,
|
|
10377
10844
|
snippet: snippet(file.content, line)
|
|
10378
10845
|
}
|
|
@@ -10385,8 +10852,8 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
10385
10852
|
|
|
10386
10853
|
// src/extract/calls/redis.ts
|
|
10387
10854
|
init_cjs_shims();
|
|
10388
|
-
var
|
|
10389
|
-
var
|
|
10855
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
10856
|
+
var import_types30 = require("@neat.is/types");
|
|
10390
10857
|
var REDIS_URL_RE = /redis(?:s)?:\/\/(?:[^@'"`\s]+@)?([^:/'"`\s]+)(?::(\d+))?/g;
|
|
10391
10858
|
function redisEndpointsFromFile(file, serviceDir) {
|
|
10392
10859
|
const out = [];
|
|
@@ -10399,7 +10866,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
10399
10866
|
seen.add(host);
|
|
10400
10867
|
const line = lineOf(file.content, host);
|
|
10401
10868
|
out.push({
|
|
10402
|
-
infraId: (0,
|
|
10869
|
+
infraId: (0, import_types30.infraId)("redis", host),
|
|
10403
10870
|
name: host,
|
|
10404
10871
|
kind: "redis",
|
|
10405
10872
|
edgeType: "CALLS",
|
|
@@ -10408,7 +10875,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
10408
10875
|
// support tier (ADR-066).
|
|
10409
10876
|
confidenceKind: "url-with-structural-support",
|
|
10410
10877
|
evidence: {
|
|
10411
|
-
file:
|
|
10878
|
+
file: import_node_path41.default.relative(serviceDir, file.path),
|
|
10412
10879
|
line,
|
|
10413
10880
|
snippet: snippet(file.content, line)
|
|
10414
10881
|
}
|
|
@@ -10419,8 +10886,8 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
10419
10886
|
|
|
10420
10887
|
// src/extract/calls/aws.ts
|
|
10421
10888
|
init_cjs_shims();
|
|
10422
|
-
var
|
|
10423
|
-
var
|
|
10889
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
10890
|
+
var import_types31 = require("@neat.is/types");
|
|
10424
10891
|
var S3_BUCKET_RE = /Bucket\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
10425
10892
|
var DYNAMO_TABLE_RE = /TableName\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
10426
10893
|
function hasMarker(text, markers) {
|
|
@@ -10444,7 +10911,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
10444
10911
|
seen.add(key);
|
|
10445
10912
|
const line = lineOf(file.content, name);
|
|
10446
10913
|
out.push({
|
|
10447
|
-
infraId: (0,
|
|
10914
|
+
infraId: (0, import_types31.infraId)(kind, name),
|
|
10448
10915
|
name,
|
|
10449
10916
|
kind,
|
|
10450
10917
|
edgeType: "CALLS",
|
|
@@ -10453,7 +10920,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
10453
10920
|
// (ADR-066).
|
|
10454
10921
|
confidenceKind: "verified-call-site",
|
|
10455
10922
|
evidence: {
|
|
10456
|
-
file:
|
|
10923
|
+
file: import_node_path42.default.relative(serviceDir, file.path),
|
|
10457
10924
|
line,
|
|
10458
10925
|
snippet: snippet(file.content, line)
|
|
10459
10926
|
}
|
|
@@ -10478,8 +10945,8 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
10478
10945
|
|
|
10479
10946
|
// src/extract/calls/grpc.ts
|
|
10480
10947
|
init_cjs_shims();
|
|
10481
|
-
var
|
|
10482
|
-
var
|
|
10948
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
10949
|
+
var import_types32 = require("@neat.is/types");
|
|
10483
10950
|
var GRPC_CLIENT_RE = /new\s+([A-Z][A-Za-z0-9_]*)Client\s*\(\s*['"`]?([^,'"`)]+)?/g;
|
|
10484
10951
|
var AWS_SDK_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@aws-sdk\/client-([a-z0-9-]+)['"`]/g;
|
|
10485
10952
|
var GRPC_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@grpc\/grpc-js['"`]|_grpc_pb['"`]/;
|
|
@@ -10528,7 +10995,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
10528
10995
|
const { kind } = classified;
|
|
10529
10996
|
const line = lineOf(file.content, m[0]);
|
|
10530
10997
|
out.push({
|
|
10531
|
-
infraId: (0,
|
|
10998
|
+
infraId: (0, import_types32.infraId)(kind, name),
|
|
10532
10999
|
name,
|
|
10533
11000
|
kind,
|
|
10534
11001
|
edgeType: "CALLS",
|
|
@@ -10537,7 +11004,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
10537
11004
|
// tier (ADR-066).
|
|
10538
11005
|
confidenceKind: "verified-call-site",
|
|
10539
11006
|
evidence: {
|
|
10540
|
-
file:
|
|
11007
|
+
file: import_node_path43.default.relative(serviceDir, file.path),
|
|
10541
11008
|
line,
|
|
10542
11009
|
snippet: snippet(file.content, line)
|
|
10543
11010
|
}
|
|
@@ -10548,8 +11015,8 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
10548
11015
|
|
|
10549
11016
|
// src/extract/calls/supabase.ts
|
|
10550
11017
|
init_cjs_shims();
|
|
10551
|
-
var
|
|
10552
|
-
var
|
|
11018
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
11019
|
+
var import_types33 = require("@neat.is/types");
|
|
10553
11020
|
var SUPABASE_JS_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/supabase-js['"`]/;
|
|
10554
11021
|
var SUPABASE_SSR_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/ssr['"`]/;
|
|
10555
11022
|
var SUPABASE_CLIENT_RE = /\b(createClient|createServerClient|createBrowserClient)\s*\(\s*(?:['"`]([^'"`]*)['"`])?/g;
|
|
@@ -10597,7 +11064,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
10597
11064
|
seen.add(name);
|
|
10598
11065
|
const line = lineOf(file.content, m[0]);
|
|
10599
11066
|
out.push({
|
|
10600
|
-
infraId: (0,
|
|
11067
|
+
infraId: (0, import_types33.infraId)("supabase", name),
|
|
10601
11068
|
name,
|
|
10602
11069
|
kind: "supabase",
|
|
10603
11070
|
edgeType: "CALLS",
|
|
@@ -10607,7 +11074,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
10607
11074
|
// tier (ADR-066), the same grade aws.ts / grpc.ts emit at.
|
|
10608
11075
|
confidenceKind: "verified-call-site",
|
|
10609
11076
|
evidence: {
|
|
10610
|
-
file:
|
|
11077
|
+
file: import_node_path44.default.relative(serviceDir, file.path),
|
|
10611
11078
|
line,
|
|
10612
11079
|
snippet: snippet(file.content, line)
|
|
10613
11080
|
}
|
|
@@ -10628,13 +11095,13 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
10628
11095
|
seen.add(key);
|
|
10629
11096
|
const line = lineOf(file.content, am[0]);
|
|
10630
11097
|
out.push({
|
|
10631
|
-
infraId: (0,
|
|
11098
|
+
infraId: (0, import_types33.infraId)(kind, resource),
|
|
10632
11099
|
name: resource,
|
|
10633
11100
|
kind,
|
|
10634
11101
|
edgeType: "CALLS",
|
|
10635
11102
|
confidenceKind: "verified-call-site",
|
|
10636
11103
|
evidence: {
|
|
10637
|
-
file:
|
|
11104
|
+
file: import_node_path44.default.relative(serviceDir, file.path),
|
|
10638
11105
|
line,
|
|
10639
11106
|
snippet: snippet(file.content, line)
|
|
10640
11107
|
}
|
|
@@ -10646,10 +11113,10 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
10646
11113
|
|
|
10647
11114
|
// src/extract/calls/firestore.ts
|
|
10648
11115
|
init_cjs_shims();
|
|
10649
|
-
var
|
|
11116
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
10650
11117
|
var import_tree_sitter8 = __toESM(require("tree-sitter"), 1);
|
|
10651
11118
|
var import_tree_sitter_javascript6 = __toESM(require("tree-sitter-javascript"), 1);
|
|
10652
|
-
var
|
|
11119
|
+
var import_types34 = require("@neat.is/types");
|
|
10653
11120
|
var FIRESTORE_CLIENT_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase\/firestore['"`]/;
|
|
10654
11121
|
var FIRESTORE_ADMIN_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase-admin(?:\/firestore)?['"`]/;
|
|
10655
11122
|
function parserForExt2(ext) {
|
|
@@ -10817,7 +11284,7 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
10817
11284
|
const hasAdmin = FIRESTORE_ADMIN_IMPORT_RE.test(file.content);
|
|
10818
11285
|
if (!hasClient && !hasAdmin) return [];
|
|
10819
11286
|
const fileSdk = hasClient && !hasAdmin ? "client" : hasAdmin && !hasClient ? "admin" : null;
|
|
10820
|
-
const tree = parseSource3(parserForExt2(
|
|
11287
|
+
const tree = parseSource3(parserForExt2(import_node_path45.default.extname(file.path)), file.content);
|
|
10821
11288
|
const clientVars = firestoreClientVars(tree.rootNode);
|
|
10822
11289
|
const collLine = /* @__PURE__ */ new Map();
|
|
10823
11290
|
const writes = /* @__PURE__ */ new Map();
|
|
@@ -10910,7 +11377,7 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
10910
11377
|
}
|
|
10911
11378
|
}
|
|
10912
11379
|
out.push({
|
|
10913
|
-
infraId: (0,
|
|
11380
|
+
infraId: (0, import_types34.infraId)("firestore-collection", collPath),
|
|
10914
11381
|
name: collPath,
|
|
10915
11382
|
kind: "firestore-collection",
|
|
10916
11383
|
edgeType: "CALLS",
|
|
@@ -10921,7 +11388,7 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
10921
11388
|
...columnSet.size > 0 ? { columns: [...columnSet] } : {},
|
|
10922
11389
|
...sdkWrites ? { sdkWrites } : {},
|
|
10923
11390
|
evidence: {
|
|
10924
|
-
file:
|
|
11391
|
+
file: import_node_path45.default.relative(serviceDir, file.path),
|
|
10925
11392
|
line,
|
|
10926
11393
|
snippet: snippet(file.content, line)
|
|
10927
11394
|
}
|
|
@@ -10932,8 +11399,8 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
10932
11399
|
|
|
10933
11400
|
// src/extract/calls/mongoose.ts
|
|
10934
11401
|
init_cjs_shims();
|
|
10935
|
-
var
|
|
10936
|
-
var
|
|
11402
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
11403
|
+
var import_types35 = require("@neat.is/types");
|
|
10937
11404
|
var MONGOOSE_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongoose['"`]/;
|
|
10938
11405
|
var MONGODB_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongodb['"`]/;
|
|
10939
11406
|
var PLURALIZE_DISABLED_RE = /\bpluralize\s*\(\s*(?:null|false)\s*\)/;
|
|
@@ -11078,12 +11545,12 @@ function collectModelDefs(content, pluralizeOn) {
|
|
|
11078
11545
|
function endpoint(r, file, serviceDir, matchText) {
|
|
11079
11546
|
const line = lineOf(file.content, matchText);
|
|
11080
11547
|
return {
|
|
11081
|
-
infraId: (0,
|
|
11548
|
+
infraId: (0, import_types35.infraId)(r.kind, r.name),
|
|
11082
11549
|
name: r.name,
|
|
11083
11550
|
kind: r.kind,
|
|
11084
11551
|
edgeType: "CALLS",
|
|
11085
11552
|
confidenceKind: "verified-call-site",
|
|
11086
|
-
evidence: { file:
|
|
11553
|
+
evidence: { file: import_node_path46.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
11087
11554
|
};
|
|
11088
11555
|
}
|
|
11089
11556
|
function mongooseEndpointsFromFile(file, serviceDir) {
|
|
@@ -11173,7 +11640,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
11173
11640
|
const registry = /* @__PURE__ */ new Map();
|
|
11174
11641
|
for (const f of mongooseFiles) {
|
|
11175
11642
|
const fx = fileExportsOf(f.content, pluralizeOn);
|
|
11176
|
-
if (fx) registry.set(toPosix(
|
|
11643
|
+
if (fx) registry.set(toPosix(import_node_path46.default.relative(serviceDir, f.path)), fx);
|
|
11177
11644
|
}
|
|
11178
11645
|
if (registry.size === 0) return [];
|
|
11179
11646
|
const out = [];
|
|
@@ -11184,7 +11651,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
11184
11651
|
const directColl = /* @__PURE__ */ new Map();
|
|
11185
11652
|
const nsExports = /* @__PURE__ */ new Map();
|
|
11186
11653
|
for (const b of bindings) {
|
|
11187
|
-
const resolvedRel = await resolveJsImport(b.specifier,
|
|
11654
|
+
const resolvedRel = await resolveJsImport(b.specifier, import_node_path46.default.dirname(f.path), serviceDir, null);
|
|
11188
11655
|
if (!resolvedRel) continue;
|
|
11189
11656
|
const fx = registry.get(resolvedRel);
|
|
11190
11657
|
if (!fx) continue;
|
|
@@ -11228,10 +11695,10 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
11228
11695
|
|
|
11229
11696
|
// src/extract/calls/sqlalchemy.ts
|
|
11230
11697
|
init_cjs_shims();
|
|
11231
|
-
var
|
|
11698
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
11232
11699
|
var import_tree_sitter9 = __toESM(require("tree-sitter"), 1);
|
|
11233
11700
|
var import_tree_sitter_python5 = __toESM(require("tree-sitter-python"), 1);
|
|
11234
|
-
var
|
|
11701
|
+
var import_types36 = require("@neat.is/types");
|
|
11235
11702
|
var SQLALCHEMY_IMPORT_RE = /(?:from|import)\s+(?:flask_sqlalchemy|sqlalchemy)\b/;
|
|
11236
11703
|
var PARSE_CHUNK6 = 16384;
|
|
11237
11704
|
function makePyParser3() {
|
|
@@ -11367,7 +11834,7 @@ function sqlalchemyForeignKeys(file, serviceDir) {
|
|
|
11367
11834
|
childTable,
|
|
11368
11835
|
parentTable,
|
|
11369
11836
|
evidence: {
|
|
11370
|
-
file:
|
|
11837
|
+
file: import_node_path47.default.relative(serviceDir, file.path),
|
|
11371
11838
|
line,
|
|
11372
11839
|
snippet: snippet(file.content, line)
|
|
11373
11840
|
}
|
|
@@ -11385,14 +11852,14 @@ function sqlalchemyEndpointsFromFile(file, serviceDir) {
|
|
|
11385
11852
|
if (seen.has(name)) return;
|
|
11386
11853
|
seen.add(name);
|
|
11387
11854
|
out.push({
|
|
11388
|
-
infraId: (0,
|
|
11855
|
+
infraId: (0, import_types36.infraId)("sql-table", name),
|
|
11389
11856
|
name,
|
|
11390
11857
|
kind: "sql-table",
|
|
11391
11858
|
edgeType: "CALLS",
|
|
11392
11859
|
confidenceKind: "verified-call-site",
|
|
11393
11860
|
...columns && columns.length > 0 ? { columns } : {},
|
|
11394
11861
|
evidence: {
|
|
11395
|
-
file:
|
|
11862
|
+
file: import_node_path47.default.relative(serviceDir, file.path),
|
|
11396
11863
|
line,
|
|
11397
11864
|
snippet: snippet(file.content, line)
|
|
11398
11865
|
}
|
|
@@ -11493,13 +11960,13 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
|
|
|
11493
11960
|
if (seen.has(key)) continue;
|
|
11494
11961
|
seen.add(key);
|
|
11495
11962
|
out.push({
|
|
11496
|
-
infraId: (0,
|
|
11963
|
+
infraId: (0, import_types36.infraId)("sql-table", t),
|
|
11497
11964
|
name: t,
|
|
11498
11965
|
kind: "sql-table",
|
|
11499
11966
|
edgeType: "CALLS",
|
|
11500
11967
|
confidenceKind: "verified-call-site",
|
|
11501
11968
|
evidence: {
|
|
11502
|
-
file:
|
|
11969
|
+
file: import_node_path47.default.relative(serviceDir, file.path),
|
|
11503
11970
|
line,
|
|
11504
11971
|
snippet: snippet(file.content, line)
|
|
11505
11972
|
}
|
|
@@ -11511,10 +11978,10 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
|
|
|
11511
11978
|
|
|
11512
11979
|
// src/extract/calls/django-orm.ts
|
|
11513
11980
|
init_cjs_shims();
|
|
11514
|
-
var
|
|
11981
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
11515
11982
|
var import_tree_sitter10 = __toESM(require("tree-sitter"), 1);
|
|
11516
11983
|
var import_tree_sitter_python6 = __toESM(require("tree-sitter-python"), 1);
|
|
11517
|
-
var
|
|
11984
|
+
var import_types37 = require("@neat.is/types");
|
|
11518
11985
|
var DJANGO_IMPORT_RE = /(?:from|import)\s+django\b/;
|
|
11519
11986
|
var PARSE_CHUNK7 = 16384;
|
|
11520
11987
|
function makePyParser4() {
|
|
@@ -11581,7 +12048,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
11581
12048
|
const tree = parseSource7(makePyParser4(), file.content);
|
|
11582
12049
|
const out = [];
|
|
11583
12050
|
const seen = /* @__PURE__ */ new Set();
|
|
11584
|
-
const defaultAppLabel =
|
|
12051
|
+
const defaultAppLabel = import_node_path48.default.basename(import_node_path48.default.dirname(file.path));
|
|
11585
12052
|
walk4(tree.rootNode, (node) => {
|
|
11586
12053
|
if (node.type !== "class_definition") return;
|
|
11587
12054
|
if (!extendsDjangoModel(node)) return;
|
|
@@ -11594,12 +12061,12 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
11594
12061
|
seen.add(table);
|
|
11595
12062
|
const line = node.startPosition.row + 1;
|
|
11596
12063
|
out.push({
|
|
11597
|
-
infraId: (0,
|
|
12064
|
+
infraId: (0, import_types37.infraId)("sql-table", table),
|
|
11598
12065
|
name: table,
|
|
11599
12066
|
kind: "sql-table",
|
|
11600
12067
|
edgeType: "CALLS",
|
|
11601
12068
|
confidenceKind: "verified-call-site",
|
|
11602
|
-
evidence: { file:
|
|
12069
|
+
evidence: { file: import_node_path48.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
11603
12070
|
});
|
|
11604
12071
|
});
|
|
11605
12072
|
return out;
|
|
@@ -11607,10 +12074,10 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
11607
12074
|
|
|
11608
12075
|
// src/extract/calls/drizzle.ts
|
|
11609
12076
|
init_cjs_shims();
|
|
11610
|
-
var
|
|
12077
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
11611
12078
|
var import_tree_sitter11 = __toESM(require("tree-sitter"), 1);
|
|
11612
12079
|
var import_tree_sitter_javascript7 = __toESM(require("tree-sitter-javascript"), 1);
|
|
11613
|
-
var
|
|
12080
|
+
var import_types38 = require("@neat.is/types");
|
|
11614
12081
|
var DRIZZLE_IMPORT_RE = /drizzle-orm/;
|
|
11615
12082
|
var TABLE_BUILDERS = /* @__PURE__ */ new Set(["pgTable", "mysqlTable", "sqliteTable"]);
|
|
11616
12083
|
function parserForExt3(ext) {
|
|
@@ -11685,7 +12152,7 @@ function columnsFromObject(obj) {
|
|
|
11685
12152
|
}
|
|
11686
12153
|
function drizzleEndpointsFromFile(file, serviceDir) {
|
|
11687
12154
|
if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
|
|
11688
|
-
const tree = parseSource3(parserForExt3(
|
|
12155
|
+
const tree = parseSource3(parserForExt3(import_node_path49.default.extname(file.path)), file.content);
|
|
11689
12156
|
const out = [];
|
|
11690
12157
|
const seen = /* @__PURE__ */ new Set();
|
|
11691
12158
|
const walk9 = (node) => {
|
|
@@ -11701,14 +12168,14 @@ function drizzleEndpointsFromFile(file, serviceDir) {
|
|
|
11701
12168
|
const columns = columnsFromObject(obj);
|
|
11702
12169
|
const line = node.startPosition.row + 1;
|
|
11703
12170
|
out.push({
|
|
11704
|
-
infraId: (0,
|
|
12171
|
+
infraId: (0, import_types38.infraId)("sql-table", tableName),
|
|
11705
12172
|
name: tableName,
|
|
11706
12173
|
kind: "sql-table",
|
|
11707
12174
|
edgeType: "CALLS",
|
|
11708
12175
|
confidenceKind: "structural",
|
|
11709
12176
|
columns,
|
|
11710
12177
|
evidence: {
|
|
11711
|
-
file:
|
|
12178
|
+
file: import_node_path49.default.relative(serviceDir, file.path),
|
|
11712
12179
|
line,
|
|
11713
12180
|
snippet: snippet(file.content, line)
|
|
11714
12181
|
}
|
|
@@ -11774,7 +12241,7 @@ function referencesTargetVar(call) {
|
|
|
11774
12241
|
}
|
|
11775
12242
|
function drizzleForeignKeys(file, serviceDir) {
|
|
11776
12243
|
if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
|
|
11777
|
-
const tree = parseSource3(parserForExt3(
|
|
12244
|
+
const tree = parseSource3(parserForExt3(import_node_path49.default.extname(file.path)), file.content);
|
|
11778
12245
|
const { tables, varToTable } = collectDrizzleTables(tree.rootNode);
|
|
11779
12246
|
const out = [];
|
|
11780
12247
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -11793,7 +12260,7 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
11793
12260
|
childTable: table.tableName,
|
|
11794
12261
|
parentTable,
|
|
11795
12262
|
evidence: {
|
|
11796
|
-
file:
|
|
12263
|
+
file: import_node_path49.default.relative(serviceDir, file.path),
|
|
11797
12264
|
line,
|
|
11798
12265
|
snippet: snippet(file.content, line)
|
|
11799
12266
|
}
|
|
@@ -11810,8 +12277,8 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
11810
12277
|
|
|
11811
12278
|
// src/extract/calls/prisma.ts
|
|
11812
12279
|
init_cjs_shims();
|
|
11813
|
-
var
|
|
11814
|
-
var
|
|
12280
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
12281
|
+
var import_types39 = require("@neat.is/types");
|
|
11815
12282
|
var SCALAR_TYPES = /* @__PURE__ */ new Set([
|
|
11816
12283
|
"Int",
|
|
11817
12284
|
"String",
|
|
@@ -11859,14 +12326,14 @@ function prismaColumnsFromSchema(file, serviceDir) {
|
|
|
11859
12326
|
if (seenTable.has(b.tableName)) return;
|
|
11860
12327
|
seenTable.add(b.tableName);
|
|
11861
12328
|
out.push({
|
|
11862
|
-
infraId: (0,
|
|
12329
|
+
infraId: (0, import_types39.infraId)("sql-table", b.tableName),
|
|
11863
12330
|
name: b.tableName,
|
|
11864
12331
|
kind: "sql-table",
|
|
11865
12332
|
edgeType: "CALLS",
|
|
11866
12333
|
confidenceKind: "structural",
|
|
11867
12334
|
columns: b.columns,
|
|
11868
12335
|
evidence: {
|
|
11869
|
-
file:
|
|
12336
|
+
file: import_node_path50.default.relative(serviceDir, file.path),
|
|
11870
12337
|
line: b.startLine,
|
|
11871
12338
|
snippet: snippet(content, b.startLine)
|
|
11872
12339
|
}
|
|
@@ -11927,7 +12394,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
|
|
|
11927
12394
|
}
|
|
11928
12395
|
async function prismaColumnEndpoints(serviceDir) {
|
|
11929
12396
|
const schemaPath = await findFirst(serviceDir, [
|
|
11930
|
-
|
|
12397
|
+
import_node_path50.default.join("prisma", "schema.prisma"),
|
|
11931
12398
|
"schema.prisma"
|
|
11932
12399
|
]);
|
|
11933
12400
|
if (!schemaPath) return [];
|
|
@@ -12002,7 +12469,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
|
|
|
12002
12469
|
childTable: current.table,
|
|
12003
12470
|
parentTable,
|
|
12004
12471
|
evidence: {
|
|
12005
|
-
file:
|
|
12472
|
+
file: import_node_path50.default.relative(serviceDir, file.path),
|
|
12006
12473
|
line: lineNo,
|
|
12007
12474
|
snippet: snippet(content, lineNo)
|
|
12008
12475
|
}
|
|
@@ -12017,7 +12484,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
|
|
|
12017
12484
|
}
|
|
12018
12485
|
async function prismaForeignKeys(serviceDir) {
|
|
12019
12486
|
const schemaPath = await findFirst(serviceDir, [
|
|
12020
|
-
|
|
12487
|
+
import_node_path50.default.join("prisma", "schema.prisma"),
|
|
12021
12488
|
"schema.prisma"
|
|
12022
12489
|
]);
|
|
12023
12490
|
if (!schemaPath) return [];
|
|
@@ -12028,10 +12495,10 @@ async function prismaForeignKeys(serviceDir) {
|
|
|
12028
12495
|
|
|
12029
12496
|
// src/extract/calls/activerecord.ts
|
|
12030
12497
|
init_cjs_shims();
|
|
12031
|
-
var
|
|
12498
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
12032
12499
|
var import_tree_sitter12 = __toESM(require("tree-sitter"), 1);
|
|
12033
12500
|
var import_tree_sitter_ruby3 = __toESM(require("tree-sitter-ruby"), 1);
|
|
12034
|
-
var
|
|
12501
|
+
var import_types40 = require("@neat.is/types");
|
|
12035
12502
|
var AR_SCHEMA_RE = /ActiveRecord::Schema/;
|
|
12036
12503
|
var PARSE_CHUNK8 = 16384;
|
|
12037
12504
|
function makeRubyParser2() {
|
|
@@ -12229,14 +12696,14 @@ function railsSchemaEndpointsFromFile(file, serviceDir) {
|
|
|
12229
12696
|
if (!table || seen.has(table.name)) return;
|
|
12230
12697
|
seen.add(table.name);
|
|
12231
12698
|
out.push({
|
|
12232
|
-
infraId: (0,
|
|
12699
|
+
infraId: (0, import_types40.infraId)("sql-table", table.name),
|
|
12233
12700
|
name: table.name,
|
|
12234
12701
|
kind: "sql-table",
|
|
12235
12702
|
edgeType: "CALLS",
|
|
12236
12703
|
confidenceKind: "structural",
|
|
12237
12704
|
...table.columns.length > 0 ? { columns: table.columns } : {},
|
|
12238
12705
|
evidence: {
|
|
12239
|
-
file:
|
|
12706
|
+
file: import_node_path51.default.relative(serviceDir, file.path),
|
|
12240
12707
|
line: table.line,
|
|
12241
12708
|
snippet: snippet(file.content, table.line)
|
|
12242
12709
|
}
|
|
@@ -12258,7 +12725,7 @@ function railsSchemaForeignKeys(file, serviceDir) {
|
|
|
12258
12725
|
childTable,
|
|
12259
12726
|
parentTable,
|
|
12260
12727
|
evidence: {
|
|
12261
|
-
file:
|
|
12728
|
+
file: import_node_path51.default.relative(serviceDir, file.path),
|
|
12262
12729
|
line,
|
|
12263
12730
|
snippet: snippet(file.content, line)
|
|
12264
12731
|
}
|
|
@@ -12335,13 +12802,13 @@ function railsModelEndpointsFromFile(file, serviceDir) {
|
|
|
12335
12802
|
seen.add(table);
|
|
12336
12803
|
const line = node.startPosition.row + 1;
|
|
12337
12804
|
out.push({
|
|
12338
|
-
infraId: (0,
|
|
12805
|
+
infraId: (0, import_types40.infraId)("sql-table", table),
|
|
12339
12806
|
name: table,
|
|
12340
12807
|
kind: "sql-table",
|
|
12341
12808
|
edgeType: "CALLS",
|
|
12342
12809
|
confidenceKind: "verified-call-site",
|
|
12343
12810
|
evidence: {
|
|
12344
|
-
file:
|
|
12811
|
+
file: import_node_path51.default.relative(serviceDir, file.path),
|
|
12345
12812
|
line,
|
|
12346
12813
|
snippet: snippet(file.content, line)
|
|
12347
12814
|
}
|
|
@@ -12378,7 +12845,7 @@ function railsModelForeignKeys(file, serviceDir) {
|
|
|
12378
12845
|
childTable,
|
|
12379
12846
|
parentTable,
|
|
12380
12847
|
evidence: {
|
|
12381
|
-
file:
|
|
12848
|
+
file: import_node_path51.default.relative(serviceDir, file.path),
|
|
12382
12849
|
line,
|
|
12383
12850
|
snippet: snippet(file.content, line)
|
|
12384
12851
|
}
|
|
@@ -12390,10 +12857,10 @@ function railsModelForeignKeys(file, serviceDir) {
|
|
|
12390
12857
|
|
|
12391
12858
|
// src/extract/calls/eloquent.ts
|
|
12392
12859
|
init_cjs_shims();
|
|
12393
|
-
var
|
|
12860
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
12394
12861
|
var import_tree_sitter13 = __toESM(require("tree-sitter"), 1);
|
|
12395
12862
|
var import_tree_sitter_php3 = __toESM(require("tree-sitter-php"), 1);
|
|
12396
|
-
var
|
|
12863
|
+
var import_types41 = require("@neat.is/types");
|
|
12397
12864
|
var LARAVEL_SCHEMA_RE = /\bSchema::(create|createIfNotExists|table)\b/;
|
|
12398
12865
|
var PARSE_CHUNK9 = 16384;
|
|
12399
12866
|
function makePhpParser2() {
|
|
@@ -12640,14 +13107,14 @@ function laravelMigrationEndpointsFromFile(file, serviceDir) {
|
|
|
12640
13107
|
}
|
|
12641
13108
|
}
|
|
12642
13109
|
out.push({
|
|
12643
|
-
infraId: (0,
|
|
13110
|
+
infraId: (0, import_types41.infraId)("sql-table", bp.table),
|
|
12644
13111
|
name: bp.table,
|
|
12645
13112
|
kind: "sql-table",
|
|
12646
13113
|
edgeType: "CALLS",
|
|
12647
13114
|
confidenceKind: "structural",
|
|
12648
13115
|
...columns.length > 0 ? { columns } : {},
|
|
12649
13116
|
evidence: {
|
|
12650
|
-
file:
|
|
13117
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
12651
13118
|
line: bp.line,
|
|
12652
13119
|
snippet: snippet(file.content, bp.line)
|
|
12653
13120
|
}
|
|
@@ -12669,7 +13136,7 @@ function laravelMigrationForeignKeys(file, serviceDir) {
|
|
|
12669
13136
|
childTable,
|
|
12670
13137
|
parentTable,
|
|
12671
13138
|
evidence: {
|
|
12672
|
-
file:
|
|
13139
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
12673
13140
|
line,
|
|
12674
13141
|
snippet: snippet(file.content, line)
|
|
12675
13142
|
}
|
|
@@ -12783,13 +13250,13 @@ function laravelModelEndpointsFromFile(file, serviceDir) {
|
|
|
12783
13250
|
seen.add(table);
|
|
12784
13251
|
const line = node.startPosition.row + 1;
|
|
12785
13252
|
out.push({
|
|
12786
|
-
infraId: (0,
|
|
13253
|
+
infraId: (0, import_types41.infraId)("sql-table", table),
|
|
12787
13254
|
name: table,
|
|
12788
13255
|
kind: "sql-table",
|
|
12789
13256
|
edgeType: "CALLS",
|
|
12790
13257
|
confidenceKind: "verified-call-site",
|
|
12791
13258
|
evidence: {
|
|
12792
|
-
file:
|
|
13259
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
12793
13260
|
line,
|
|
12794
13261
|
snippet: snippet(file.content, line)
|
|
12795
13262
|
}
|
|
@@ -12825,7 +13292,7 @@ function laravelModelForeignKeys(file, serviceDir) {
|
|
|
12825
13292
|
childTable,
|
|
12826
13293
|
parentTable,
|
|
12827
13294
|
evidence: {
|
|
12828
|
-
file:
|
|
13295
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
12829
13296
|
line,
|
|
12830
13297
|
snippet: snippet(file.content, line)
|
|
12831
13298
|
}
|
|
@@ -12837,10 +13304,10 @@ function laravelModelForeignKeys(file, serviceDir) {
|
|
|
12837
13304
|
|
|
12838
13305
|
// src/extract/calls/go.ts
|
|
12839
13306
|
init_cjs_shims();
|
|
12840
|
-
var
|
|
13307
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
12841
13308
|
var import_tree_sitter14 = __toESM(require("tree-sitter"), 1);
|
|
12842
13309
|
var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
|
|
12843
|
-
var
|
|
13310
|
+
var import_types42 = require("@neat.is/types");
|
|
12844
13311
|
init_otel();
|
|
12845
13312
|
var PARSE_CHUNK10 = 16384;
|
|
12846
13313
|
var DATABASE_SQL_METHODS = /* @__PURE__ */ new Set([
|
|
@@ -12912,7 +13379,7 @@ function firstStringLiteralArg(argsNode) {
|
|
|
12912
13379
|
return null;
|
|
12913
13380
|
}
|
|
12914
13381
|
function goSqlEndpointsFromFile(file, serviceDir) {
|
|
12915
|
-
if (
|
|
13382
|
+
if (import_node_path55.default.extname(file.path) !== ".go") return [];
|
|
12916
13383
|
if (!file.content.includes(DATABASE_SQL_IMPORT) && !file.content.includes(SQLX_IMPORT)) return [];
|
|
12917
13384
|
const tree = parseSource10(makeGoParser3(), file.content);
|
|
12918
13385
|
const importsDatabaseSql = goImportsAny(tree.rootNode, /* @__PURE__ */ new Set([DATABASE_SQL_IMPORT]));
|
|
@@ -12934,14 +13401,14 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
12934
13401
|
const columns = columnsFromSqlStatement(sql);
|
|
12935
13402
|
const line = node.startPosition.row + 1;
|
|
12936
13403
|
out.push({
|
|
12937
|
-
infraId: (0,
|
|
13404
|
+
infraId: (0, import_types42.infraId)("sql-table", table),
|
|
12938
13405
|
name: table,
|
|
12939
13406
|
kind: "sql-table",
|
|
12940
13407
|
edgeType: "CALLS",
|
|
12941
13408
|
confidenceKind: "verified-call-site",
|
|
12942
13409
|
...columns.length > 0 ? { columns } : {},
|
|
12943
13410
|
evidence: {
|
|
12944
|
-
file: toPosix(
|
|
13411
|
+
file: toPosix(import_node_path55.default.relative(serviceDir, file.path)),
|
|
12945
13412
|
line,
|
|
12946
13413
|
snippet: snippet(file.content, line)
|
|
12947
13414
|
}
|
|
@@ -12952,10 +13419,10 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
12952
13419
|
|
|
12953
13420
|
// src/extract/calls/gorm.ts
|
|
12954
13421
|
init_cjs_shims();
|
|
12955
|
-
var
|
|
13422
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
12956
13423
|
var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
|
|
12957
13424
|
var import_tree_sitter_go5 = __toESM(require("tree-sitter-go"), 1);
|
|
12958
|
-
var
|
|
13425
|
+
var import_types43 = require("@neat.is/types");
|
|
12959
13426
|
var GORM_IMPORT_RE = /gorm\.io\/gorm/;
|
|
12960
13427
|
var PARSE_CHUNK11 = 16384;
|
|
12961
13428
|
function makeGoParser4() {
|
|
@@ -13385,7 +13852,7 @@ function collectColumns(struct, structs, seen, prefix, out, emitted) {
|
|
|
13385
13852
|
seen.delete(struct.name);
|
|
13386
13853
|
}
|
|
13387
13854
|
function gormEndpointsFromFile(file, serviceDir) {
|
|
13388
|
-
if (
|
|
13855
|
+
if (import_node_path56.default.extname(file.path) !== ".go") return [];
|
|
13389
13856
|
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
13390
13857
|
const tree = parseSource11(makeGoParser4(), file.content);
|
|
13391
13858
|
const { structs, models, tableFor } = analyze(tree);
|
|
@@ -13400,14 +13867,14 @@ function gormEndpointsFromFile(file, serviceDir) {
|
|
|
13400
13867
|
const columns = [];
|
|
13401
13868
|
collectColumns(struct, structs, /* @__PURE__ */ new Set(), "", columns, /* @__PURE__ */ new Set());
|
|
13402
13869
|
out.push({
|
|
13403
|
-
infraId: (0,
|
|
13870
|
+
infraId: (0, import_types43.infraId)("sql-table", table),
|
|
13404
13871
|
name: table,
|
|
13405
13872
|
kind: "sql-table",
|
|
13406
13873
|
edgeType: "CALLS",
|
|
13407
13874
|
confidenceKind: "structural",
|
|
13408
13875
|
...columns.length > 0 ? { columns } : {},
|
|
13409
13876
|
evidence: {
|
|
13410
|
-
file: toPosix(
|
|
13877
|
+
file: toPosix(import_node_path56.default.relative(serviceDir, file.path)),
|
|
13411
13878
|
line: struct.line,
|
|
13412
13879
|
snippet: snippet(file.content, struct.line)
|
|
13413
13880
|
}
|
|
@@ -13416,7 +13883,7 @@ function gormEndpointsFromFile(file, serviceDir) {
|
|
|
13416
13883
|
return out;
|
|
13417
13884
|
}
|
|
13418
13885
|
function gormForeignKeys(file, serviceDir) {
|
|
13419
|
-
if (
|
|
13886
|
+
if (import_node_path56.default.extname(file.path) !== ".go") return [];
|
|
13420
13887
|
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
13421
13888
|
const tree = parseSource11(makeGoParser4(), file.content);
|
|
13422
13889
|
const { structs, models, tableFor } = analyze(tree);
|
|
@@ -13431,7 +13898,7 @@ function gormForeignKeys(file, serviceDir) {
|
|
|
13431
13898
|
childTable,
|
|
13432
13899
|
parentTable,
|
|
13433
13900
|
evidence: {
|
|
13434
|
-
file: toPosix(
|
|
13901
|
+
file: toPosix(import_node_path56.default.relative(serviceDir, file.path)),
|
|
13435
13902
|
line,
|
|
13436
13903
|
snippet: snippet(file.content, line)
|
|
13437
13904
|
}
|
|
@@ -13470,11 +13937,11 @@ function gormForeignKeys(file, serviceDir) {
|
|
|
13470
13937
|
function edgeTypeFromEndpoint(ep) {
|
|
13471
13938
|
switch (ep.edgeType) {
|
|
13472
13939
|
case "PUBLISHES_TO":
|
|
13473
|
-
return
|
|
13940
|
+
return import_types44.EdgeType.PUBLISHES_TO;
|
|
13474
13941
|
case "CONSUMES_FROM":
|
|
13475
|
-
return
|
|
13942
|
+
return import_types44.EdgeType.CONSUMES_FROM;
|
|
13476
13943
|
default:
|
|
13477
|
-
return
|
|
13944
|
+
return import_types44.EdgeType.CALLS;
|
|
13478
13945
|
}
|
|
13479
13946
|
}
|
|
13480
13947
|
function isAwsKind(kind) {
|
|
@@ -13484,7 +13951,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
13484
13951
|
let nodesAdded = 0;
|
|
13485
13952
|
let edgesAdded = 0;
|
|
13486
13953
|
for (const service of services) {
|
|
13487
|
-
const files = await loadSourceFiles(service.dir);
|
|
13954
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
13488
13955
|
const endpoints = [];
|
|
13489
13956
|
const maskedFiles = [];
|
|
13490
13957
|
for (const file of files) {
|
|
@@ -13534,7 +14001,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
13534
14001
|
if (!graph.hasNode(ep.infraId)) {
|
|
13535
14002
|
const node = {
|
|
13536
14003
|
id: ep.infraId,
|
|
13537
|
-
type:
|
|
14004
|
+
type: import_types44.NodeType.InfraNode,
|
|
13538
14005
|
name: ep.name,
|
|
13539
14006
|
// #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
|
|
13540
14007
|
// aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
|
|
@@ -13547,21 +14014,21 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
13547
14014
|
}
|
|
13548
14015
|
if (ep.columns && ep.columns.length > 0) {
|
|
13549
14016
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
13550
|
-
if (node.type ===
|
|
14017
|
+
if (node.type === import_types44.NodeType.InfraNode) {
|
|
13551
14018
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
13552
14019
|
...node,
|
|
13553
14020
|
columns: foldColumns(
|
|
13554
14021
|
node.columns,
|
|
13555
14022
|
ep.columns,
|
|
13556
|
-
|
|
13557
|
-
(0,
|
|
14023
|
+
import_types44.Provenance.EXTRACTED,
|
|
14024
|
+
(0, import_types44.confidenceForExtracted)(ep.confidenceKind)
|
|
13558
14025
|
)
|
|
13559
14026
|
});
|
|
13560
14027
|
}
|
|
13561
14028
|
}
|
|
13562
14029
|
if (ep.sdkWrites && Object.keys(ep.sdkWrites).length > 0) {
|
|
13563
14030
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
13564
|
-
if (node.type ===
|
|
14031
|
+
if (node.type === import_types44.NodeType.InfraNode) {
|
|
13565
14032
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
13566
14033
|
...node,
|
|
13567
14034
|
columns: foldSdkWrites(node.columns, ep.sdkWrites)
|
|
@@ -13569,7 +14036,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
13569
14036
|
}
|
|
13570
14037
|
}
|
|
13571
14038
|
const edgeType = edgeTypeFromEndpoint(ep);
|
|
13572
|
-
const confidence = (0,
|
|
14039
|
+
const confidence = (0, import_types44.confidenceForExtracted)(ep.confidenceKind);
|
|
13573
14040
|
const relFile = toPosix(ep.evidence.file);
|
|
13574
14041
|
const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
13575
14042
|
graph,
|
|
@@ -13579,7 +14046,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
13579
14046
|
);
|
|
13580
14047
|
nodesAdded += n;
|
|
13581
14048
|
edgesAdded += e;
|
|
13582
|
-
if (!(0,
|
|
14049
|
+
if (!(0, import_types44.passesExtractedFloor)(confidence)) {
|
|
13583
14050
|
noteExtractedDropped({
|
|
13584
14051
|
source: fileNodeId,
|
|
13585
14052
|
target: ep.infraId,
|
|
@@ -13599,7 +14066,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
13599
14066
|
source: fileNodeId,
|
|
13600
14067
|
target: ep.infraId,
|
|
13601
14068
|
type: edgeType,
|
|
13602
|
-
provenance:
|
|
14069
|
+
provenance: import_types44.Provenance.EXTRACTED,
|
|
13603
14070
|
confidence,
|
|
13604
14071
|
evidence: ep.evidence
|
|
13605
14072
|
};
|
|
@@ -13622,12 +14089,12 @@ async function addCallEdges(graph, services) {
|
|
|
13622
14089
|
|
|
13623
14090
|
// src/extract/table-edges.ts
|
|
13624
14091
|
init_cjs_shims();
|
|
13625
|
-
var
|
|
14092
|
+
var import_types45 = require("@neat.is/types");
|
|
13626
14093
|
async function addTableEdges(graph, services) {
|
|
13627
14094
|
let nodesAdded = 0;
|
|
13628
14095
|
let edgesAdded = 0;
|
|
13629
14096
|
for (const service of services) {
|
|
13630
|
-
const files = await loadSourceFiles(service.dir);
|
|
14097
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
13631
14098
|
const refs = [];
|
|
13632
14099
|
const modelRefs = [];
|
|
13633
14100
|
for (const file of files) {
|
|
@@ -13650,20 +14117,20 @@ async function addTableEdges(graph, services) {
|
|
|
13650
14117
|
}
|
|
13651
14118
|
refs.push(...modelRefs);
|
|
13652
14119
|
for (const ref of refs) {
|
|
13653
|
-
const childId = (0,
|
|
13654
|
-
const parentId = (0,
|
|
14120
|
+
const childId = (0, import_types45.infraId)("sql-table", ref.childTable);
|
|
14121
|
+
const parentId = (0, import_types45.infraId)("sql-table", ref.parentTable);
|
|
13655
14122
|
if (childId === parentId) continue;
|
|
13656
14123
|
nodesAdded += ensureTableNode(graph, childId, ref.childTable);
|
|
13657
14124
|
nodesAdded += ensureTableNode(graph, parentId, ref.parentTable);
|
|
13658
|
-
const edgeId = (0,
|
|
14125
|
+
const edgeId = (0, import_types45.extractedEdgeId)(childId, parentId, import_types45.EdgeType.REFERENCES);
|
|
13659
14126
|
if (graph.hasEdge(edgeId)) continue;
|
|
13660
14127
|
const edge = {
|
|
13661
14128
|
id: edgeId,
|
|
13662
14129
|
source: childId,
|
|
13663
14130
|
target: parentId,
|
|
13664
|
-
type:
|
|
13665
|
-
provenance:
|
|
13666
|
-
confidence: (0,
|
|
14131
|
+
type: import_types45.EdgeType.REFERENCES,
|
|
14132
|
+
provenance: import_types45.Provenance.EXTRACTED,
|
|
14133
|
+
confidence: (0, import_types45.confidenceForExtracted)("structural"),
|
|
13667
14134
|
evidence: ref.evidence
|
|
13668
14135
|
};
|
|
13669
14136
|
graph.addEdgeWithKey(edgeId, childId, parentId, edge);
|
|
@@ -13676,7 +14143,7 @@ function ensureTableNode(graph, id, name) {
|
|
|
13676
14143
|
if (graph.hasNode(id)) return 0;
|
|
13677
14144
|
const node = {
|
|
13678
14145
|
id,
|
|
13679
|
-
type:
|
|
14146
|
+
type: import_types45.NodeType.InfraNode,
|
|
13680
14147
|
name,
|
|
13681
14148
|
provider: "self",
|
|
13682
14149
|
kind: "sql-table"
|
|
@@ -13690,16 +14157,16 @@ init_cjs_shims();
|
|
|
13690
14157
|
|
|
13691
14158
|
// src/extract/infra/docker-compose.ts
|
|
13692
14159
|
init_cjs_shims();
|
|
13693
|
-
var
|
|
13694
|
-
var
|
|
14160
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
14161
|
+
var import_types47 = require("@neat.is/types");
|
|
13695
14162
|
|
|
13696
14163
|
// src/extract/infra/shared.ts
|
|
13697
14164
|
init_cjs_shims();
|
|
13698
|
-
var
|
|
14165
|
+
var import_types46 = require("@neat.is/types");
|
|
13699
14166
|
function makeInfraNode(kind, name, provider = "self", extras) {
|
|
13700
14167
|
return {
|
|
13701
|
-
id: (0,
|
|
13702
|
-
type:
|
|
14168
|
+
id: (0, import_types46.infraId)(kind, name),
|
|
14169
|
+
type: import_types46.NodeType.InfraNode,
|
|
13703
14170
|
name,
|
|
13704
14171
|
provider,
|
|
13705
14172
|
kind,
|
|
@@ -13743,8 +14210,8 @@ function emitPlatformResourceEdge(graph, anchorId, edgeType, kind, name, provide
|
|
|
13743
14210
|
source: anchorId,
|
|
13744
14211
|
target: node.id,
|
|
13745
14212
|
type: edgeType,
|
|
13746
|
-
provenance:
|
|
13747
|
-
confidence: (0,
|
|
14213
|
+
provenance: import_types46.Provenance.EXTRACTED,
|
|
14214
|
+
confidence: (0, import_types46.confidenceForExtracted)("structural"),
|
|
13748
14215
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
13749
14216
|
};
|
|
13750
14217
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -13761,7 +14228,7 @@ function dependsOnList(value) {
|
|
|
13761
14228
|
}
|
|
13762
14229
|
function serviceNameToServiceNode(name, services) {
|
|
13763
14230
|
for (const s of services) {
|
|
13764
|
-
if (s.node.name === name ||
|
|
14231
|
+
if (s.node.name === name || import_node_path57.default.basename(s.dir) === name) return s.node.id;
|
|
13765
14232
|
}
|
|
13766
14233
|
return null;
|
|
13767
14234
|
}
|
|
@@ -13770,7 +14237,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
13770
14237
|
let edgesAdded = 0;
|
|
13771
14238
|
let composePath = null;
|
|
13772
14239
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
13773
|
-
const abs =
|
|
14240
|
+
const abs = import_node_path57.default.join(scanPath, name);
|
|
13774
14241
|
if (await exists2(abs)) {
|
|
13775
14242
|
composePath = abs;
|
|
13776
14243
|
break;
|
|
@@ -13783,13 +14250,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
13783
14250
|
} catch (err) {
|
|
13784
14251
|
recordExtractionError(
|
|
13785
14252
|
"infra docker-compose",
|
|
13786
|
-
|
|
14253
|
+
import_node_path57.default.relative(scanPath, composePath),
|
|
13787
14254
|
err
|
|
13788
14255
|
);
|
|
13789
14256
|
return { nodesAdded, edgesAdded };
|
|
13790
14257
|
}
|
|
13791
14258
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
13792
|
-
const evidenceFile =
|
|
14259
|
+
const evidenceFile = import_node_path57.default.relative(scanPath, composePath).split(import_node_path57.default.sep).join("/");
|
|
13793
14260
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
13794
14261
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
13795
14262
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -13811,15 +14278,15 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
13811
14278
|
for (const dep of dependsOnList(svc.depends_on)) {
|
|
13812
14279
|
const targetId = composeNameToNodeId.get(dep);
|
|
13813
14280
|
if (!targetId) continue;
|
|
13814
|
-
const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId,
|
|
14281
|
+
const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types47.EdgeType.DEPENDS_ON);
|
|
13815
14282
|
if (graph.hasEdge(edgeId)) continue;
|
|
13816
14283
|
const edge = {
|
|
13817
14284
|
id: edgeId,
|
|
13818
14285
|
source: sourceId,
|
|
13819
14286
|
target: targetId,
|
|
13820
|
-
type:
|
|
13821
|
-
provenance:
|
|
13822
|
-
confidence: (0,
|
|
14287
|
+
type: import_types47.EdgeType.DEPENDS_ON,
|
|
14288
|
+
provenance: import_types47.Provenance.EXTRACTED,
|
|
14289
|
+
confidence: (0, import_types47.confidenceForExtracted)("structural"),
|
|
13823
14290
|
evidence: { file: evidenceFile }
|
|
13824
14291
|
};
|
|
13825
14292
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -13831,9 +14298,9 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
13831
14298
|
|
|
13832
14299
|
// src/extract/infra/dockerfile.ts
|
|
13833
14300
|
init_cjs_shims();
|
|
13834
|
-
var
|
|
13835
|
-
var
|
|
13836
|
-
var
|
|
14301
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
14302
|
+
var import_node_fs26 = require("fs");
|
|
14303
|
+
var import_types48 = require("@neat.is/types");
|
|
13837
14304
|
function readDockerfile(content) {
|
|
13838
14305
|
let image = null;
|
|
13839
14306
|
const ports = [];
|
|
@@ -13862,15 +14329,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13862
14329
|
let nodesAdded = 0;
|
|
13863
14330
|
let edgesAdded = 0;
|
|
13864
14331
|
for (const service of services) {
|
|
13865
|
-
const dockerfilePath =
|
|
14332
|
+
const dockerfilePath = import_node_path58.default.join(service.dir, "Dockerfile");
|
|
13866
14333
|
if (!await exists2(dockerfilePath)) continue;
|
|
13867
14334
|
let content;
|
|
13868
14335
|
try {
|
|
13869
|
-
content = await
|
|
14336
|
+
content = await import_node_fs26.promises.readFile(dockerfilePath, "utf8");
|
|
13870
14337
|
} catch (err) {
|
|
13871
14338
|
recordExtractionError(
|
|
13872
14339
|
"infra dockerfile",
|
|
13873
|
-
|
|
14340
|
+
import_node_path58.default.relative(scanPath, dockerfilePath),
|
|
13874
14341
|
err
|
|
13875
14342
|
);
|
|
13876
14343
|
continue;
|
|
@@ -13882,8 +14349,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13882
14349
|
graph.addNode(node.id, node);
|
|
13883
14350
|
nodesAdded++;
|
|
13884
14351
|
}
|
|
13885
|
-
const relDockerfile = toPosix(
|
|
13886
|
-
const evidenceFile = toPosix(
|
|
14352
|
+
const relDockerfile = toPosix(import_node_path58.default.relative(service.dir, dockerfilePath));
|
|
14353
|
+
const evidenceFile = toPosix(import_node_path58.default.relative(scanPath, dockerfilePath));
|
|
13887
14354
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
13888
14355
|
graph,
|
|
13889
14356
|
service.pkg.name,
|
|
@@ -13892,15 +14359,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13892
14359
|
);
|
|
13893
14360
|
nodesAdded += fn;
|
|
13894
14361
|
edgesAdded += fe;
|
|
13895
|
-
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id,
|
|
14362
|
+
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types48.EdgeType.RUNS_ON);
|
|
13896
14363
|
if (!graph.hasEdge(edgeId)) {
|
|
13897
14364
|
const edge = {
|
|
13898
14365
|
id: edgeId,
|
|
13899
14366
|
source: fileNodeId,
|
|
13900
14367
|
target: node.id,
|
|
13901
|
-
type:
|
|
13902
|
-
provenance:
|
|
13903
|
-
confidence: (0,
|
|
14368
|
+
type: import_types48.EdgeType.RUNS_ON,
|
|
14369
|
+
provenance: import_types48.Provenance.EXTRACTED,
|
|
14370
|
+
confidence: (0, import_types48.confidenceForExtracted)("structural"),
|
|
13904
14371
|
evidence: {
|
|
13905
14372
|
file: evidenceFile,
|
|
13906
14373
|
...facts.entrypoint ? { snippet: facts.entrypoint.slice(0, 120) } : {}
|
|
@@ -13915,15 +14382,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13915
14382
|
graph.addNode(portNode.id, portNode);
|
|
13916
14383
|
nodesAdded++;
|
|
13917
14384
|
}
|
|
13918
|
-
const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id,
|
|
14385
|
+
const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types48.EdgeType.CONNECTS_TO);
|
|
13919
14386
|
if (graph.hasEdge(portEdgeId)) continue;
|
|
13920
14387
|
const portEdge = {
|
|
13921
14388
|
id: portEdgeId,
|
|
13922
14389
|
source: fileNodeId,
|
|
13923
14390
|
target: portNode.id,
|
|
13924
|
-
type:
|
|
13925
|
-
provenance:
|
|
13926
|
-
confidence: (0,
|
|
14391
|
+
type: import_types48.EdgeType.CONNECTS_TO,
|
|
14392
|
+
provenance: import_types48.Provenance.EXTRACTED,
|
|
14393
|
+
confidence: (0, import_types48.confidenceForExtracted)("structural"),
|
|
13927
14394
|
evidence: { file: evidenceFile, snippet: `EXPOSE ${port}` }
|
|
13928
14395
|
};
|
|
13929
14396
|
graph.addEdgeWithKey(portEdgeId, portEdge.source, portEdge.target, portEdge);
|
|
@@ -13935,23 +14402,23 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
13935
14402
|
|
|
13936
14403
|
// src/extract/infra/terraform.ts
|
|
13937
14404
|
init_cjs_shims();
|
|
13938
|
-
var
|
|
13939
|
-
var
|
|
13940
|
-
var
|
|
14405
|
+
var import_node_fs27 = require("fs");
|
|
14406
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
14407
|
+
var import_types49 = require("@neat.is/types");
|
|
13941
14408
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
13942
14409
|
var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
|
|
13943
14410
|
async function walkTfFiles(start, depth = 0, max = 5) {
|
|
13944
14411
|
if (depth > max) return [];
|
|
13945
14412
|
const out = [];
|
|
13946
|
-
const entries = await
|
|
14413
|
+
const entries = await import_node_fs27.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
13947
14414
|
for (const entry of entries) {
|
|
13948
14415
|
if (entry.isDirectory()) {
|
|
13949
14416
|
if (IGNORED_DIRS.has(entry.name) || entry.name === ".terraform") continue;
|
|
13950
|
-
const child =
|
|
14417
|
+
const child = import_node_path59.default.join(start, entry.name);
|
|
13951
14418
|
if (await isPythonVenvDir(child)) continue;
|
|
13952
14419
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
13953
14420
|
} else if (entry.isFile() && entry.name.endsWith(".tf")) {
|
|
13954
|
-
out.push(
|
|
14421
|
+
out.push(import_node_path59.default.join(start, entry.name));
|
|
13955
14422
|
}
|
|
13956
14423
|
}
|
|
13957
14424
|
return out;
|
|
@@ -13982,8 +14449,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
13982
14449
|
let edgesAdded = 0;
|
|
13983
14450
|
const files = await walkTfFiles(scanPath);
|
|
13984
14451
|
for (const file of files) {
|
|
13985
|
-
const content = await
|
|
13986
|
-
const evidenceFile = toPosix(
|
|
14452
|
+
const content = await import_node_fs27.promises.readFile(file, "utf8");
|
|
14453
|
+
const evidenceFile = toPosix(import_node_path59.default.relative(scanPath, file));
|
|
13987
14454
|
const resources = [];
|
|
13988
14455
|
const byKey = /* @__PURE__ */ new Map();
|
|
13989
14456
|
RESOURCE_RE.lastIndex = 0;
|
|
@@ -14018,16 +14485,16 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
14018
14485
|
if (!target) continue;
|
|
14019
14486
|
if (seen.has(target.nodeId)) continue;
|
|
14020
14487
|
seen.add(target.nodeId);
|
|
14021
|
-
const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId,
|
|
14488
|
+
const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types49.EdgeType.DEPENDS_ON);
|
|
14022
14489
|
if (graph.hasEdge(edgeId)) continue;
|
|
14023
14490
|
const line = lineAt2(content, resource.bodyOffset + ref.index);
|
|
14024
14491
|
const edge = {
|
|
14025
14492
|
id: edgeId,
|
|
14026
14493
|
source: resource.nodeId,
|
|
14027
14494
|
target: target.nodeId,
|
|
14028
|
-
type:
|
|
14029
|
-
provenance:
|
|
14030
|
-
confidence: (0,
|
|
14495
|
+
type: import_types49.EdgeType.DEPENDS_ON,
|
|
14496
|
+
provenance: import_types49.Provenance.EXTRACTED,
|
|
14497
|
+
confidence: (0, import_types49.confidenceForExtracted)("structural"),
|
|
14031
14498
|
evidence: { file: evidenceFile, line, snippet: key }
|
|
14032
14499
|
};
|
|
14033
14500
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -14040,8 +14507,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
14040
14507
|
|
|
14041
14508
|
// src/extract/infra/k8s.ts
|
|
14042
14509
|
init_cjs_shims();
|
|
14043
|
-
var
|
|
14044
|
-
var
|
|
14510
|
+
var import_node_fs28 = require("fs");
|
|
14511
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
14045
14512
|
var import_yaml3 = require("yaml");
|
|
14046
14513
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
14047
14514
|
Service: "k8s-service",
|
|
@@ -14055,15 +14522,15 @@ var K8S_KIND_TO_INFRA_KIND = {
|
|
|
14055
14522
|
async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
14056
14523
|
if (depth > max) return [];
|
|
14057
14524
|
const out = [];
|
|
14058
|
-
const entries = await
|
|
14525
|
+
const entries = await import_node_fs28.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
14059
14526
|
for (const entry of entries) {
|
|
14060
14527
|
if (entry.isDirectory()) {
|
|
14061
14528
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
14062
|
-
const child =
|
|
14529
|
+
const child = import_node_path60.default.join(start, entry.name);
|
|
14063
14530
|
if (await isPythonVenvDir(child)) continue;
|
|
14064
14531
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
14065
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
14066
|
-
out.push(
|
|
14532
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path60.default.extname(entry.name))) {
|
|
14533
|
+
out.push(import_node_path60.default.join(start, entry.name));
|
|
14067
14534
|
}
|
|
14068
14535
|
}
|
|
14069
14536
|
return out;
|
|
@@ -14072,7 +14539,7 @@ async function addK8sResources(graph, scanPath) {
|
|
|
14072
14539
|
let nodesAdded = 0;
|
|
14073
14540
|
const files = await walkYamlFiles2(scanPath);
|
|
14074
14541
|
for (const file of files) {
|
|
14075
|
-
const content = await
|
|
14542
|
+
const content = await import_node_fs28.promises.readFile(file, "utf8");
|
|
14076
14543
|
let docs;
|
|
14077
14544
|
try {
|
|
14078
14545
|
docs = (0, import_yaml3.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
@@ -14096,17 +14563,17 @@ async function addK8sResources(graph, scanPath) {
|
|
|
14096
14563
|
|
|
14097
14564
|
// src/extract/infra/cloudflare.ts
|
|
14098
14565
|
init_cjs_shims();
|
|
14099
|
-
var
|
|
14100
|
-
var
|
|
14101
|
-
var
|
|
14102
|
-
var
|
|
14566
|
+
var import_node_fs29 = require("fs");
|
|
14567
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
14568
|
+
var import_smol_toml3 = require("smol-toml");
|
|
14569
|
+
var import_types50 = require("@neat.is/types");
|
|
14103
14570
|
var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
|
|
14104
14571
|
async function readWranglerConfig(dir) {
|
|
14105
14572
|
for (const filename of WRANGLER_FILENAMES) {
|
|
14106
|
-
const abs =
|
|
14573
|
+
const abs = import_node_path61.default.join(dir, filename);
|
|
14107
14574
|
if (!await exists2(abs)) continue;
|
|
14108
|
-
const raw = await
|
|
14109
|
-
const config = filename === "wrangler.toml" ? (0,
|
|
14575
|
+
const raw = await import_node_fs29.promises.readFile(abs, "utf8");
|
|
14576
|
+
const config = filename === "wrangler.toml" ? (0, import_smol_toml3.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
14110
14577
|
return { config, relFile: filename, raw };
|
|
14111
14578
|
}
|
|
14112
14579
|
return null;
|
|
@@ -14147,8 +14614,8 @@ function addResourceEdge(graph, anchorId, edgeType, kind, name, evidenceFile, li
|
|
|
14147
14614
|
source: anchorId,
|
|
14148
14615
|
target: node.id,
|
|
14149
14616
|
type: edgeType,
|
|
14150
|
-
provenance:
|
|
14151
|
-
confidence: (0,
|
|
14617
|
+
provenance: import_types50.Provenance.EXTRACTED,
|
|
14618
|
+
confidence: (0, import_types50.confidenceForExtracted)("structural"),
|
|
14152
14619
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
14153
14620
|
};
|
|
14154
14621
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -14166,11 +14633,11 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14166
14633
|
try {
|
|
14167
14634
|
read = await readWranglerConfig(service.dir);
|
|
14168
14635
|
} catch (err) {
|
|
14169
|
-
recordExtractionError("infra cloudflare",
|
|
14636
|
+
recordExtractionError("infra cloudflare", import_node_path61.default.relative(scanPath, service.dir), err);
|
|
14170
14637
|
continue;
|
|
14171
14638
|
}
|
|
14172
14639
|
if (!read || !read.config.name) continue;
|
|
14173
|
-
const evidenceFile = toPosix(
|
|
14640
|
+
const evidenceFile = toPosix(import_node_path61.default.relative(scanPath, import_node_path61.default.join(service.dir, read.relFile)));
|
|
14174
14641
|
discovered.push({ service, config: read.config, relFile: read.relFile, raw: read.raw, evidenceFile });
|
|
14175
14642
|
}
|
|
14176
14643
|
for (const worker of discovered) {
|
|
@@ -14182,7 +14649,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14182
14649
|
}
|
|
14183
14650
|
let anchorId = service.node.id;
|
|
14184
14651
|
if (config.main) {
|
|
14185
|
-
const entryRelPath = toPosix(
|
|
14652
|
+
const entryRelPath = toPosix(import_node_path61.default.normalize(config.main));
|
|
14186
14653
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
14187
14654
|
graph,
|
|
14188
14655
|
service.pkg.name,
|
|
@@ -14209,15 +14676,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14209
14676
|
nodesAdded++;
|
|
14210
14677
|
}
|
|
14211
14678
|
if (runtimeNode.id !== anchorId) {
|
|
14212
|
-
const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id,
|
|
14679
|
+
const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types50.EdgeType.RUNS_ON);
|
|
14213
14680
|
if (!graph.hasEdge(runsOnId)) {
|
|
14214
14681
|
const edge = {
|
|
14215
14682
|
id: runsOnId,
|
|
14216
14683
|
source: anchorId,
|
|
14217
14684
|
target: runtimeNode.id,
|
|
14218
|
-
type:
|
|
14219
|
-
provenance:
|
|
14220
|
-
confidence: (0,
|
|
14685
|
+
type: import_types50.EdgeType.RUNS_ON,
|
|
14686
|
+
provenance: import_types50.Provenance.EXTRACTED,
|
|
14687
|
+
confidence: (0, import_types50.confidenceForExtracted)("structural"),
|
|
14221
14688
|
evidence: {
|
|
14222
14689
|
file: evidenceFile,
|
|
14223
14690
|
...config.compatibility_date ? { snippet: `compatibility_date = ${config.compatibility_date}`.slice(0, 120) } : {}
|
|
@@ -14231,7 +14698,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14231
14698
|
const result = addResourceEdge(
|
|
14232
14699
|
graph,
|
|
14233
14700
|
anchorId,
|
|
14234
|
-
|
|
14701
|
+
import_types50.EdgeType.CONNECTS_TO,
|
|
14235
14702
|
"cloudflare-route",
|
|
14236
14703
|
route,
|
|
14237
14704
|
evidenceFile,
|
|
@@ -14255,7 +14722,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14255
14722
|
const result = addResourceEdge(
|
|
14256
14723
|
graph,
|
|
14257
14724
|
anchorId,
|
|
14258
|
-
|
|
14725
|
+
import_types50.EdgeType.DEPENDS_ON,
|
|
14259
14726
|
group.kind,
|
|
14260
14727
|
name,
|
|
14261
14728
|
evidenceFile,
|
|
@@ -14269,7 +14736,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14269
14736
|
const result = addResourceEdge(
|
|
14270
14737
|
graph,
|
|
14271
14738
|
anchorId,
|
|
14272
|
-
|
|
14739
|
+
import_types50.EdgeType.DEPENDS_ON,
|
|
14273
14740
|
"cloudflare-cron",
|
|
14274
14741
|
cron,
|
|
14275
14742
|
evidenceFile,
|
|
@@ -14282,7 +14749,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14282
14749
|
const result = addResourceEdge(
|
|
14283
14750
|
graph,
|
|
14284
14751
|
anchorId,
|
|
14285
|
-
|
|
14752
|
+
import_types50.EdgeType.DEPENDS_ON,
|
|
14286
14753
|
"cloudflare-env-var",
|
|
14287
14754
|
varName,
|
|
14288
14755
|
evidenceFile,
|
|
@@ -14295,15 +14762,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14295
14762
|
if (!svc.service) continue;
|
|
14296
14763
|
const target = workerIndex.get(svc.service);
|
|
14297
14764
|
if (target && target.anchorId !== anchorId) {
|
|
14298
|
-
const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId,
|
|
14765
|
+
const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types50.EdgeType.CALLS);
|
|
14299
14766
|
if (!graph.hasEdge(edgeId)) {
|
|
14300
14767
|
const edge = {
|
|
14301
14768
|
id: edgeId,
|
|
14302
14769
|
source: anchorId,
|
|
14303
14770
|
target: target.anchorId,
|
|
14304
|
-
type:
|
|
14305
|
-
provenance:
|
|
14306
|
-
confidence: (0,
|
|
14771
|
+
type: import_types50.EdgeType.CALLS,
|
|
14772
|
+
provenance: import_types50.Provenance.EXTRACTED,
|
|
14773
|
+
confidence: (0, import_types50.confidenceForExtracted)("structural"),
|
|
14307
14774
|
evidence: { file: evidenceFile, line: lineContaining2(raw, svc.service) }
|
|
14308
14775
|
};
|
|
14309
14776
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -14314,7 +14781,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14314
14781
|
const result = addResourceEdge(
|
|
14315
14782
|
graph,
|
|
14316
14783
|
anchorId,
|
|
14317
|
-
|
|
14784
|
+
import_types50.EdgeType.DEPENDS_ON,
|
|
14318
14785
|
"cloudflare-service-binding",
|
|
14319
14786
|
svc.service,
|
|
14320
14787
|
evidenceFile,
|
|
@@ -14329,24 +14796,24 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
14329
14796
|
|
|
14330
14797
|
// src/extract/infra/vercel.ts
|
|
14331
14798
|
init_cjs_shims();
|
|
14332
|
-
var
|
|
14333
|
-
var
|
|
14334
|
-
var
|
|
14799
|
+
var import_node_fs30 = require("fs");
|
|
14800
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
14801
|
+
var import_types51 = require("@neat.is/types");
|
|
14335
14802
|
var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
|
|
14336
14803
|
async function readVercelConfig(dir) {
|
|
14337
14804
|
for (const filename of VERCEL_CONFIG_FILENAMES) {
|
|
14338
|
-
const abs =
|
|
14805
|
+
const abs = import_node_path62.default.join(dir, filename);
|
|
14339
14806
|
if (!await exists2(abs)) continue;
|
|
14340
|
-
const raw = await
|
|
14807
|
+
const raw = await import_node_fs30.promises.readFile(abs, "utf8");
|
|
14341
14808
|
const config = JSON.parse(maskCommentsInSource(raw));
|
|
14342
14809
|
return { config, relFile: filename, raw };
|
|
14343
14810
|
}
|
|
14344
14811
|
return null;
|
|
14345
14812
|
}
|
|
14346
14813
|
async function readLinkedProjectName(dir) {
|
|
14347
|
-
const abs =
|
|
14814
|
+
const abs = import_node_path62.default.join(dir, ".vercel", "project.json");
|
|
14348
14815
|
if (!await exists2(abs)) return void 0;
|
|
14349
|
-
const parsed = JSON.parse(await
|
|
14816
|
+
const parsed = JSON.parse(await import_node_fs30.promises.readFile(abs, "utf8"));
|
|
14350
14817
|
return typeof parsed.projectName === "string" ? parsed.projectName : void 0;
|
|
14351
14818
|
}
|
|
14352
14819
|
function routeSource(route) {
|
|
@@ -14362,7 +14829,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
14362
14829
|
read = await readVercelConfig(service.dir);
|
|
14363
14830
|
projectName = await readLinkedProjectName(service.dir);
|
|
14364
14831
|
} catch (err) {
|
|
14365
|
-
recordExtractionError("infra vercel",
|
|
14832
|
+
recordExtractionError("infra vercel", import_node_path62.default.relative(scanPath, service.dir), err);
|
|
14366
14833
|
continue;
|
|
14367
14834
|
}
|
|
14368
14835
|
if (!read && !projectName) continue;
|
|
@@ -14378,7 +14845,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
14378
14845
|
const anchorId = service.node.id;
|
|
14379
14846
|
if (!read) continue;
|
|
14380
14847
|
const { config, relFile, raw } = read;
|
|
14381
|
-
const evidenceFile = toPosix(
|
|
14848
|
+
const evidenceFile = toPosix(import_node_path62.default.relative(scanPath, import_node_path62.default.join(service.dir, relFile)));
|
|
14382
14849
|
const add = (edgeType, kind, name) => {
|
|
14383
14850
|
if (!name) return;
|
|
14384
14851
|
const result = emitPlatformResourceEdge(
|
|
@@ -14394,12 +14861,12 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
14394
14861
|
nodesAdded += result.nodesAdded;
|
|
14395
14862
|
edgesAdded += result.edgesAdded;
|
|
14396
14863
|
};
|
|
14397
|
-
add(
|
|
14398
|
-
for (const cron of config.crons ?? []) add(
|
|
14399
|
-
for (const varName of Object.keys(config.env ?? {})) add(
|
|
14400
|
-
for (const varName of Object.keys(config.build?.env ?? {})) add(
|
|
14864
|
+
add(import_types51.EdgeType.RUNS_ON, "vercel", "vercel");
|
|
14865
|
+
for (const cron of config.crons ?? []) add(import_types51.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
|
|
14866
|
+
for (const varName of Object.keys(config.env ?? {})) add(import_types51.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
14867
|
+
for (const varName of Object.keys(config.build?.env ?? {})) add(import_types51.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
14401
14868
|
for (const route of [...config.rewrites ?? [], ...config.redirects ?? [], ...config.routes ?? []]) {
|
|
14402
|
-
add(
|
|
14869
|
+
add(import_types51.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
|
|
14403
14870
|
}
|
|
14404
14871
|
}
|
|
14405
14872
|
return { nodesAdded, edgesAdded };
|
|
@@ -14407,17 +14874,17 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
14407
14874
|
|
|
14408
14875
|
// src/extract/infra/railway.ts
|
|
14409
14876
|
init_cjs_shims();
|
|
14410
|
-
var
|
|
14411
|
-
var
|
|
14412
|
-
var
|
|
14413
|
-
var
|
|
14877
|
+
var import_node_fs31 = require("fs");
|
|
14878
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
14879
|
+
var import_smol_toml4 = require("smol-toml");
|
|
14880
|
+
var import_types52 = require("@neat.is/types");
|
|
14414
14881
|
var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
|
|
14415
14882
|
async function readRailwayConfig(dir) {
|
|
14416
14883
|
for (const filename of RAILWAY_FILENAMES) {
|
|
14417
|
-
const abs =
|
|
14884
|
+
const abs = import_node_path63.default.join(dir, filename);
|
|
14418
14885
|
if (!await exists2(abs)) continue;
|
|
14419
|
-
const raw = await
|
|
14420
|
-
const config = filename === "railway.toml" ? (0,
|
|
14886
|
+
const raw = await import_node_fs31.promises.readFile(abs, "utf8");
|
|
14887
|
+
const config = filename === "railway.toml" ? (0, import_smol_toml4.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
14421
14888
|
return { config, relFile: filename, raw };
|
|
14422
14889
|
}
|
|
14423
14890
|
return null;
|
|
@@ -14430,7 +14897,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
14430
14897
|
try {
|
|
14431
14898
|
read = await readRailwayConfig(service.dir);
|
|
14432
14899
|
} catch (err) {
|
|
14433
|
-
recordExtractionError("infra railway",
|
|
14900
|
+
recordExtractionError("infra railway", import_node_path63.default.relative(scanPath, service.dir), err);
|
|
14434
14901
|
continue;
|
|
14435
14902
|
}
|
|
14436
14903
|
if (!read) continue;
|
|
@@ -14440,7 +14907,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
14440
14907
|
}
|
|
14441
14908
|
const anchorId = service.node.id;
|
|
14442
14909
|
const { config, relFile, raw } = read;
|
|
14443
|
-
const evidenceFile = toPosix(
|
|
14910
|
+
const evidenceFile = toPosix(import_node_path63.default.relative(scanPath, import_node_path63.default.join(service.dir, relFile)));
|
|
14444
14911
|
const add = (edgeType, kind, name) => {
|
|
14445
14912
|
if (!name) return;
|
|
14446
14913
|
const result = emitPlatformResourceEdge(
|
|
@@ -14456,25 +14923,25 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
14456
14923
|
nodesAdded += result.nodesAdded;
|
|
14457
14924
|
edgesAdded += result.edgesAdded;
|
|
14458
14925
|
};
|
|
14459
|
-
add(
|
|
14460
|
-
add(
|
|
14461
|
-
add(
|
|
14926
|
+
add(import_types52.EdgeType.RUNS_ON, "railway", "railway");
|
|
14927
|
+
add(import_types52.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
|
|
14928
|
+
add(import_types52.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
|
|
14462
14929
|
}
|
|
14463
14930
|
return { nodesAdded, edgesAdded };
|
|
14464
14931
|
}
|
|
14465
14932
|
|
|
14466
14933
|
// src/extract/infra/supabase.ts
|
|
14467
14934
|
init_cjs_shims();
|
|
14468
|
-
var
|
|
14469
|
-
var
|
|
14470
|
-
var
|
|
14471
|
-
var
|
|
14935
|
+
var import_node_fs32 = require("fs");
|
|
14936
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
14937
|
+
var import_smol_toml5 = require("smol-toml");
|
|
14938
|
+
var import_types53 = require("@neat.is/types");
|
|
14472
14939
|
async function readSupabaseConfig(dir) {
|
|
14473
|
-
const relFile =
|
|
14474
|
-
const abs =
|
|
14940
|
+
const relFile = import_node_path64.default.join("supabase", "config.toml");
|
|
14941
|
+
const abs = import_node_path64.default.join(dir, relFile);
|
|
14475
14942
|
if (!await exists2(abs)) return null;
|
|
14476
|
-
const raw = await
|
|
14477
|
-
const config = (0,
|
|
14943
|
+
const raw = await import_node_fs32.promises.readFile(abs, "utf8");
|
|
14944
|
+
const config = (0, import_smol_toml5.parse)(raw);
|
|
14478
14945
|
return { config, relFile, raw };
|
|
14479
14946
|
}
|
|
14480
14947
|
async function addSupabaseProjects(graph, services, scanPath) {
|
|
@@ -14485,7 +14952,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
14485
14952
|
try {
|
|
14486
14953
|
read = await readSupabaseConfig(service.dir);
|
|
14487
14954
|
} catch (err) {
|
|
14488
|
-
recordExtractionError("infra supabase",
|
|
14955
|
+
recordExtractionError("infra supabase", import_node_path64.default.relative(scanPath, service.dir), err);
|
|
14489
14956
|
continue;
|
|
14490
14957
|
}
|
|
14491
14958
|
if (!read) continue;
|
|
@@ -14500,7 +14967,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
14500
14967
|
});
|
|
14501
14968
|
}
|
|
14502
14969
|
const anchorId = service.node.id;
|
|
14503
|
-
const evidenceFile = toPosix(
|
|
14970
|
+
const evidenceFile = toPosix(import_node_path64.default.relative(scanPath, import_node_path64.default.join(service.dir, relFile)));
|
|
14504
14971
|
const add = (edgeType, kind, name) => {
|
|
14505
14972
|
if (!name) return;
|
|
14506
14973
|
const result = emitPlatformResourceEdge(
|
|
@@ -14516,10 +14983,10 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
14516
14983
|
nodesAdded += result.nodesAdded;
|
|
14517
14984
|
edgesAdded += result.edgesAdded;
|
|
14518
14985
|
};
|
|
14519
|
-
add(
|
|
14520
|
-
for (const fn of Object.keys(config.functions ?? {})) add(
|
|
14521
|
-
if (config.storage) add(
|
|
14522
|
-
if (config.auth) add(
|
|
14986
|
+
add(import_types53.EdgeType.RUNS_ON, "supabase", "supabase");
|
|
14987
|
+
for (const fn of Object.keys(config.functions ?? {})) add(import_types53.EdgeType.DEPENDS_ON, "supabase-function", fn);
|
|
14988
|
+
if (config.storage) add(import_types53.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
|
|
14989
|
+
if (config.auth) add(import_types53.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
|
|
14523
14990
|
}
|
|
14524
14991
|
return { nodesAdded, edgesAdded };
|
|
14525
14992
|
}
|
|
@@ -14542,10 +15009,10 @@ async function addInfra(graph, scanPath, services) {
|
|
|
14542
15009
|
|
|
14543
15010
|
// src/extract/zod-shapes.ts
|
|
14544
15011
|
init_cjs_shims();
|
|
14545
|
-
var
|
|
15012
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
14546
15013
|
var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
|
|
14547
15014
|
var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
|
|
14548
|
-
var
|
|
15015
|
+
var import_types54 = require("@neat.is/types");
|
|
14549
15016
|
var ZOD_IMPORT_RE = /\bzod\b/;
|
|
14550
15017
|
var ZOD_OBJECTS = /* @__PURE__ */ new Set(["z", "zod"]);
|
|
14551
15018
|
function parserForExt4(ext) {
|
|
@@ -14637,7 +15104,7 @@ function topLevelSchemas(root) {
|
|
|
14637
15104
|
}
|
|
14638
15105
|
function zodShapesFromFile(file, serviceDir) {
|
|
14639
15106
|
if (!ZOD_IMPORT_RE.test(file.content)) return [];
|
|
14640
|
-
const tree = parseSource3(parserForExt4(
|
|
15107
|
+
const tree = parseSource3(parserForExt4(import_node_path65.default.extname(file.path)), file.content);
|
|
14641
15108
|
const out = [];
|
|
14642
15109
|
const seen = /* @__PURE__ */ new Set();
|
|
14643
15110
|
for (const { name, call } of topLevelSchemas(tree.rootNode)) {
|
|
@@ -14651,11 +15118,11 @@ function zodShapesFromFile(file, serviceDir) {
|
|
|
14651
15118
|
seen.add(name);
|
|
14652
15119
|
const line = call.startPosition.row + 1;
|
|
14653
15120
|
out.push({
|
|
14654
|
-
infraId: (0,
|
|
15121
|
+
infraId: (0, import_types54.infraId)("zod-schema", name),
|
|
14655
15122
|
name,
|
|
14656
15123
|
fields,
|
|
14657
15124
|
evidence: {
|
|
14658
|
-
file:
|
|
15125
|
+
file: import_node_path65.default.relative(serviceDir, file.path),
|
|
14659
15126
|
line,
|
|
14660
15127
|
snippet: snippet(file.content, line)
|
|
14661
15128
|
}
|
|
@@ -14672,7 +15139,7 @@ async function addZodShapes(graph, services) {
|
|
|
14672
15139
|
...service.pkg.devDependencies ?? {}
|
|
14673
15140
|
};
|
|
14674
15141
|
if (deps["zod"] === void 0) continue;
|
|
14675
|
-
const files = await loadSourceFiles(service.dir);
|
|
15142
|
+
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
14676
15143
|
for (const file of files) {
|
|
14677
15144
|
if (isTestPath(file.path)) continue;
|
|
14678
15145
|
let shapes;
|
|
@@ -14686,7 +15153,7 @@ async function addZodShapes(graph, services) {
|
|
|
14686
15153
|
if (!graph.hasNode(shape.infraId)) {
|
|
14687
15154
|
const node = {
|
|
14688
15155
|
id: shape.infraId,
|
|
14689
|
-
type:
|
|
15156
|
+
type: import_types54.NodeType.InfraNode,
|
|
14690
15157
|
name: shape.name,
|
|
14691
15158
|
provider: "self",
|
|
14692
15159
|
kind: "zod-schema"
|
|
@@ -14696,14 +15163,14 @@ async function addZodShapes(graph, services) {
|
|
|
14696
15163
|
}
|
|
14697
15164
|
if (shape.fields.length > 0) {
|
|
14698
15165
|
const node = graph.getNodeAttributes(shape.infraId);
|
|
14699
|
-
if (node.type ===
|
|
15166
|
+
if (node.type === import_types54.NodeType.InfraNode) {
|
|
14700
15167
|
graph.replaceNodeAttributes(shape.infraId, {
|
|
14701
15168
|
...node,
|
|
14702
15169
|
columns: foldColumns(
|
|
14703
15170
|
node.columns,
|
|
14704
15171
|
shape.fields,
|
|
14705
|
-
|
|
14706
|
-
(0,
|
|
15172
|
+
import_types54.Provenance.EXTRACTED,
|
|
15173
|
+
(0, import_types54.confidenceForExtracted)("structural")
|
|
14707
15174
|
)
|
|
14708
15175
|
});
|
|
14709
15176
|
}
|
|
@@ -14717,15 +15184,15 @@ async function addZodShapes(graph, services) {
|
|
|
14717
15184
|
);
|
|
14718
15185
|
nodesAdded += n;
|
|
14719
15186
|
edgesAdded += e;
|
|
14720
|
-
const edgeId = (0,
|
|
15187
|
+
const edgeId = (0, import_types54.extractedEdgeId)(fileNodeId, shape.infraId, import_types54.EdgeType.CONTAINS);
|
|
14721
15188
|
if (!graph.hasEdge(edgeId)) {
|
|
14722
15189
|
const edge = {
|
|
14723
15190
|
id: edgeId,
|
|
14724
15191
|
source: fileNodeId,
|
|
14725
15192
|
target: shape.infraId,
|
|
14726
|
-
type:
|
|
14727
|
-
provenance:
|
|
14728
|
-
confidence: (0,
|
|
15193
|
+
type: import_types54.EdgeType.CONTAINS,
|
|
15194
|
+
provenance: import_types54.Provenance.EXTRACTED,
|
|
15195
|
+
confidence: (0, import_types54.confidenceForExtracted)("structural"),
|
|
14729
15196
|
evidence: shape.evidence
|
|
14730
15197
|
};
|
|
14731
15198
|
graph.addEdgeWithKey(edgeId, fileNodeId, shape.infraId, edge);
|
|
@@ -14739,7 +15206,7 @@ async function addZodShapes(graph, services) {
|
|
|
14739
15206
|
|
|
14740
15207
|
// src/extract/firestore-rules.ts
|
|
14741
15208
|
init_cjs_shims();
|
|
14742
|
-
var
|
|
15209
|
+
var import_types55 = require("@neat.is/types");
|
|
14743
15210
|
var FIRESTORE_COLLECTION_KIND = "firestore-collection";
|
|
14744
15211
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["write", "create", "update"]);
|
|
14745
15212
|
function stripComments(src) {
|
|
@@ -14879,7 +15346,7 @@ async function addFirestoreRules(graph, services) {
|
|
|
14879
15346
|
if (guards.size === 0) return { nodesAdded: 0, edgesAdded: 0 };
|
|
14880
15347
|
graph.forEachNode((id, attrs) => {
|
|
14881
15348
|
const node = attrs;
|
|
14882
|
-
if (node.type !==
|
|
15349
|
+
if (node.type !== import_types55.NodeType.InfraNode) return;
|
|
14883
15350
|
if (node.kind !== FIRESTORE_COLLECTION_KIND) return;
|
|
14884
15351
|
const fields = guards.get(collectionKeyFromName(node.name));
|
|
14885
15352
|
if (!fields || fields.size === 0) return;
|
|
@@ -14892,17 +15359,17 @@ async function addFirestoreRules(graph, services) {
|
|
|
14892
15359
|
}
|
|
14893
15360
|
|
|
14894
15361
|
// src/extract/index.ts
|
|
14895
|
-
var
|
|
15362
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
14896
15363
|
|
|
14897
15364
|
// src/extract/retire.ts
|
|
14898
15365
|
init_cjs_shims();
|
|
14899
|
-
var
|
|
14900
|
-
var
|
|
14901
|
-
var
|
|
15366
|
+
var import_node_fs33 = require("fs");
|
|
15367
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
15368
|
+
var import_types56 = require("@neat.is/types");
|
|
14902
15369
|
function dropOrphanedFileNodes(graph) {
|
|
14903
15370
|
const orphans = [];
|
|
14904
15371
|
graph.forEachNode((id, attrs) => {
|
|
14905
|
-
if (attrs.type !==
|
|
15372
|
+
if (attrs.type !== import_types56.NodeType.FileNode) return;
|
|
14906
15373
|
if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
|
|
14907
15374
|
orphans.push(id);
|
|
14908
15375
|
}
|
|
@@ -14915,14 +15382,14 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
14915
15382
|
const bases = [scanPath, ...serviceDirs];
|
|
14916
15383
|
graph.forEachEdge((id, attrs) => {
|
|
14917
15384
|
const edge = attrs;
|
|
14918
|
-
if (edge.provenance !==
|
|
15385
|
+
if (edge.provenance !== import_types56.Provenance.EXTRACTED) return;
|
|
14919
15386
|
const evidenceFile = edge.evidence?.file;
|
|
14920
15387
|
if (!evidenceFile) return;
|
|
14921
|
-
if (
|
|
14922
|
-
if (!(0,
|
|
15388
|
+
if (import_node_path66.default.isAbsolute(evidenceFile)) {
|
|
15389
|
+
if (!(0, import_node_fs33.existsSync)(evidenceFile)) toDrop.push(id);
|
|
14923
15390
|
return;
|
|
14924
15391
|
}
|
|
14925
|
-
const found = bases.some((base) => (0,
|
|
15392
|
+
const found = bases.some((base) => (0, import_node_fs33.existsSync)(import_node_path66.default.join(base, evidenceFile)));
|
|
14926
15393
|
if (!found) toDrop.push(id);
|
|
14927
15394
|
});
|
|
14928
15395
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -14979,7 +15446,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
14979
15446
|
}
|
|
14980
15447
|
const droppedEntries = drainDroppedExtracted();
|
|
14981
15448
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
14982
|
-
const rejectedPath =
|
|
15449
|
+
const rejectedPath = import_node_path67.default.join(import_node_path67.default.dirname(opts.errorsPath), "rejected.ndjson");
|
|
14983
15450
|
try {
|
|
14984
15451
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
14985
15452
|
} catch (err) {
|
|
@@ -15013,7 +15480,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
15013
15480
|
|
|
15014
15481
|
// src/diff.ts
|
|
15015
15482
|
init_cjs_shims();
|
|
15016
|
-
var
|
|
15483
|
+
var import_node_fs34 = require("fs");
|
|
15017
15484
|
async function loadSnapshotForDiff(target) {
|
|
15018
15485
|
if (/^https?:\/\//i.test(target)) {
|
|
15019
15486
|
const res = await fetch(target);
|
|
@@ -15022,7 +15489,7 @@ async function loadSnapshotForDiff(target) {
|
|
|
15022
15489
|
}
|
|
15023
15490
|
return await res.json();
|
|
15024
15491
|
}
|
|
15025
|
-
const raw = await
|
|
15492
|
+
const raw = await import_node_fs34.promises.readFile(target, "utf8");
|
|
15026
15493
|
return JSON.parse(raw);
|
|
15027
15494
|
}
|
|
15028
15495
|
function indexEntries(entries) {
|
|
@@ -15090,9 +15557,9 @@ function canonicalJson(value) {
|
|
|
15090
15557
|
|
|
15091
15558
|
// src/persist.ts
|
|
15092
15559
|
init_cjs_shims();
|
|
15093
|
-
var
|
|
15094
|
-
var
|
|
15095
|
-
var
|
|
15560
|
+
var import_node_fs35 = require("fs");
|
|
15561
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
15562
|
+
var import_types57 = require("@neat.is/types");
|
|
15096
15563
|
var SCHEMA_VERSION = 7;
|
|
15097
15564
|
function migrateV1ToV2(payload) {
|
|
15098
15565
|
const nodes = payload.graph.nodes;
|
|
@@ -15116,7 +15583,7 @@ function migrateV5ToV6(payload) {
|
|
|
15116
15583
|
if (Array.isArray(nodes)) {
|
|
15117
15584
|
for (const node of nodes) {
|
|
15118
15585
|
const attrs = node.attributes;
|
|
15119
|
-
if (!attrs || attrs.type !==
|
|
15586
|
+
if (!attrs || attrs.type !== import_types57.NodeType.InfraNode) continue;
|
|
15120
15587
|
if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
|
|
15121
15588
|
if (!Array.isArray(attrs.columns)) attrs.columns = [];
|
|
15122
15589
|
}
|
|
@@ -15132,12 +15599,12 @@ function migrateV2ToV3(payload) {
|
|
|
15132
15599
|
for (const edge of edges) {
|
|
15133
15600
|
const attrs = edge.attributes;
|
|
15134
15601
|
if (!attrs || attrs.provenance !== "FRONTIER") continue;
|
|
15135
|
-
attrs.provenance =
|
|
15602
|
+
attrs.provenance = import_types57.Provenance.OBSERVED;
|
|
15136
15603
|
const type = typeof attrs.type === "string" ? attrs.type : void 0;
|
|
15137
15604
|
const source = typeof attrs.source === "string" ? attrs.source : void 0;
|
|
15138
15605
|
const target = typeof attrs.target === "string" ? attrs.target : void 0;
|
|
15139
15606
|
if (type && source && target) {
|
|
15140
|
-
const newId = (0,
|
|
15607
|
+
const newId = (0, import_types57.observedEdgeId)(source, target, type);
|
|
15141
15608
|
attrs.id = newId;
|
|
15142
15609
|
if (edge.key) edge.key = newId;
|
|
15143
15610
|
}
|
|
@@ -15146,7 +15613,7 @@ function migrateV2ToV3(payload) {
|
|
|
15146
15613
|
return { ...payload, schemaVersion: 3 };
|
|
15147
15614
|
}
|
|
15148
15615
|
async function ensureDir(filePath) {
|
|
15149
|
-
await
|
|
15616
|
+
await import_node_fs35.promises.mkdir(import_node_path68.default.dirname(filePath), { recursive: true });
|
|
15150
15617
|
}
|
|
15151
15618
|
async function saveGraphToDisk(graph, outPath) {
|
|
15152
15619
|
await ensureDir(outPath);
|
|
@@ -15156,13 +15623,13 @@ async function saveGraphToDisk(graph, outPath) {
|
|
|
15156
15623
|
graph: graph.export()
|
|
15157
15624
|
};
|
|
15158
15625
|
const tmp = `${outPath}.tmp`;
|
|
15159
|
-
await
|
|
15160
|
-
await
|
|
15626
|
+
await import_node_fs35.promises.writeFile(tmp, JSON.stringify(payload), "utf8");
|
|
15627
|
+
await import_node_fs35.promises.rename(tmp, outPath);
|
|
15161
15628
|
}
|
|
15162
15629
|
async function loadGraphFromDisk(graph, outPath) {
|
|
15163
15630
|
let raw;
|
|
15164
15631
|
try {
|
|
15165
|
-
raw = await
|
|
15632
|
+
raw = await import_node_fs35.promises.readFile(outPath, "utf8");
|
|
15166
15633
|
} catch (err) {
|
|
15167
15634
|
if (err.code === "ENOENT") return;
|
|
15168
15635
|
throw err;
|
|
@@ -15236,23 +15703,23 @@ function startPersistLoop(graph, outPath, opts = {}) {
|
|
|
15236
15703
|
|
|
15237
15704
|
// src/projects.ts
|
|
15238
15705
|
init_cjs_shims();
|
|
15239
|
-
var
|
|
15706
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
15240
15707
|
function pathsForProject(project, baseDir) {
|
|
15241
15708
|
if (project === DEFAULT_PROJECT) {
|
|
15242
15709
|
return {
|
|
15243
|
-
snapshotPath:
|
|
15244
|
-
errorsPath:
|
|
15245
|
-
staleEventsPath:
|
|
15246
|
-
embeddingsCachePath:
|
|
15247
|
-
policyViolationsPath:
|
|
15710
|
+
snapshotPath: import_node_path69.default.join(baseDir, "graph.json"),
|
|
15711
|
+
errorsPath: import_node_path69.default.join(baseDir, "errors.ndjson"),
|
|
15712
|
+
staleEventsPath: import_node_path69.default.join(baseDir, "stale-events.ndjson"),
|
|
15713
|
+
embeddingsCachePath: import_node_path69.default.join(baseDir, "embeddings.json"),
|
|
15714
|
+
policyViolationsPath: import_node_path69.default.join(baseDir, "policy-violations.ndjson")
|
|
15248
15715
|
};
|
|
15249
15716
|
}
|
|
15250
15717
|
return {
|
|
15251
|
-
snapshotPath:
|
|
15252
|
-
errorsPath:
|
|
15253
|
-
staleEventsPath:
|
|
15254
|
-
embeddingsCachePath:
|
|
15255
|
-
policyViolationsPath:
|
|
15718
|
+
snapshotPath: import_node_path69.default.join(baseDir, `${project}.json`),
|
|
15719
|
+
errorsPath: import_node_path69.default.join(baseDir, `errors.${project}.ndjson`),
|
|
15720
|
+
staleEventsPath: import_node_path69.default.join(baseDir, `stale-events.${project}.ndjson`),
|
|
15721
|
+
embeddingsCachePath: import_node_path69.default.join(baseDir, `embeddings.${project}.json`),
|
|
15722
|
+
policyViolationsPath: import_node_path69.default.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
15256
15723
|
};
|
|
15257
15724
|
}
|
|
15258
15725
|
var Projects = class {
|
|
@@ -15292,20 +15759,20 @@ function parseExtraProjects(raw) {
|
|
|
15292
15759
|
|
|
15293
15760
|
// src/registry.ts
|
|
15294
15761
|
init_cjs_shims();
|
|
15295
|
-
var
|
|
15762
|
+
var import_node_fs36 = require("fs");
|
|
15296
15763
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
15297
|
-
var
|
|
15298
|
-
var
|
|
15764
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
15765
|
+
var import_types58 = require("@neat.is/types");
|
|
15299
15766
|
function neatHome() {
|
|
15300
15767
|
const override = process.env.NEAT_HOME;
|
|
15301
|
-
if (override && override.length > 0) return
|
|
15302
|
-
return
|
|
15768
|
+
if (override && override.length > 0) return import_node_path70.default.resolve(override);
|
|
15769
|
+
return import_node_path70.default.join(import_node_os3.default.homedir(), ".neat");
|
|
15303
15770
|
}
|
|
15304
15771
|
function registryPath() {
|
|
15305
|
-
return
|
|
15772
|
+
return import_node_path70.default.join(neatHome(), "projects.json");
|
|
15306
15773
|
}
|
|
15307
15774
|
function daemonsDir() {
|
|
15308
|
-
return
|
|
15775
|
+
return import_node_path70.default.join(neatHome(), "daemons");
|
|
15309
15776
|
}
|
|
15310
15777
|
function isFiniteInt(v) {
|
|
15311
15778
|
return typeof v === "number" && Number.isFinite(v);
|
|
@@ -15338,7 +15805,7 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
15338
15805
|
const dir = daemonsDir();
|
|
15339
15806
|
let names;
|
|
15340
15807
|
try {
|
|
15341
|
-
names = await
|
|
15808
|
+
names = await import_node_fs36.promises.readdir(dir);
|
|
15342
15809
|
} catch (err) {
|
|
15343
15810
|
if (err.code === "ENOENT") return [];
|
|
15344
15811
|
throw err;
|
|
@@ -15346,10 +15813,10 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
15346
15813
|
const out = [];
|
|
15347
15814
|
for (const name of names) {
|
|
15348
15815
|
if (!name.endsWith(".json")) continue;
|
|
15349
|
-
const file =
|
|
15816
|
+
const file = import_node_path70.default.join(dir, name);
|
|
15350
15817
|
let raw;
|
|
15351
15818
|
try {
|
|
15352
|
-
raw = await
|
|
15819
|
+
raw = await import_node_fs36.promises.readFile(file, "utf8");
|
|
15353
15820
|
} catch {
|
|
15354
15821
|
continue;
|
|
15355
15822
|
}
|
|
@@ -15377,7 +15844,7 @@ async function readRegistry() {
|
|
|
15377
15844
|
const file = registryPath();
|
|
15378
15845
|
let raw;
|
|
15379
15846
|
try {
|
|
15380
|
-
raw = await
|
|
15847
|
+
raw = await import_node_fs36.promises.readFile(file, "utf8");
|
|
15381
15848
|
} catch (err) {
|
|
15382
15849
|
if (err.code === "ENOENT") {
|
|
15383
15850
|
return { version: 1, projects: [] };
|
|
@@ -15385,7 +15852,7 @@ async function readRegistry() {
|
|
|
15385
15852
|
throw err;
|
|
15386
15853
|
}
|
|
15387
15854
|
const parsed = JSON.parse(raw);
|
|
15388
|
-
return
|
|
15855
|
+
return import_types58.RegistryFileSchema.parse(parsed);
|
|
15389
15856
|
}
|
|
15390
15857
|
async function getProject(name) {
|
|
15391
15858
|
const reg = await readRegistry();
|
|
@@ -15460,8 +15927,8 @@ init_auth();
|
|
|
15460
15927
|
// src/connectors-config.ts
|
|
15461
15928
|
init_cjs_shims();
|
|
15462
15929
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
15463
|
-
var
|
|
15464
|
-
var
|
|
15930
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
15931
|
+
var import_node_fs37 = require("fs");
|
|
15465
15932
|
var CONNECTORS_CONFIG_VERSION = 1;
|
|
15466
15933
|
var EnvRefUnsetError = class extends Error {
|
|
15467
15934
|
ref;
|
|
@@ -15475,17 +15942,17 @@ var EnvRefUnsetError = class extends Error {
|
|
|
15475
15942
|
};
|
|
15476
15943
|
function neatHome2() {
|
|
15477
15944
|
const override = process.env.NEAT_HOME;
|
|
15478
|
-
if (override && override.length > 0) return
|
|
15479
|
-
return
|
|
15945
|
+
if (override && override.length > 0) return import_node_path71.default.resolve(override);
|
|
15946
|
+
return import_node_path71.default.join(import_node_os4.default.homedir(), ".neat");
|
|
15480
15947
|
}
|
|
15481
15948
|
function connectorsConfigPath(home = neatHome2()) {
|
|
15482
|
-
return
|
|
15949
|
+
return import_node_path71.default.join(home, "connectors.json");
|
|
15483
15950
|
}
|
|
15484
15951
|
var MODE_MASK_LOOSER_THAN_0600 = 63;
|
|
15485
15952
|
async function warnIfModeLooserThan0600(file) {
|
|
15486
15953
|
if (process.platform === "win32") return;
|
|
15487
15954
|
try {
|
|
15488
|
-
const stat = await
|
|
15955
|
+
const stat = await import_node_fs37.promises.stat(file);
|
|
15489
15956
|
if ((stat.mode & MODE_MASK_LOOSER_THAN_0600) !== 0) {
|
|
15490
15957
|
const mode = (stat.mode & 511).toString(8).padStart(3, "0");
|
|
15491
15958
|
console.warn(
|
|
@@ -15499,7 +15966,7 @@ async function readConnectorsConfig(home = neatHome2()) {
|
|
|
15499
15966
|
const file = connectorsConfigPath(home);
|
|
15500
15967
|
let raw;
|
|
15501
15968
|
try {
|
|
15502
|
-
raw = await
|
|
15969
|
+
raw = await import_node_fs37.promises.readFile(file, "utf8");
|
|
15503
15970
|
} catch (err) {
|
|
15504
15971
|
if (err.code === "ENOENT") {
|
|
15505
15972
|
return { version: CONNECTORS_CONFIG_VERSION, connectors: [] };
|
|
@@ -15666,15 +16133,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
|
|
|
15666
16133
|
|
|
15667
16134
|
// src/connectors/index.ts
|
|
15668
16135
|
init_cjs_shims();
|
|
15669
|
-
var
|
|
16136
|
+
var import_types59 = require("@neat.is/types");
|
|
15670
16137
|
var NO_ENV = "unknown";
|
|
15671
16138
|
function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
15672
16139
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
15673
16140
|
const sites = [];
|
|
15674
16141
|
for (const edgeId of graph.inboundEdges(targetNodeId)) {
|
|
15675
16142
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
15676
|
-
if (edge.provenance !==
|
|
15677
|
-
const parsed = (0,
|
|
16143
|
+
if (edge.provenance !== import_types59.Provenance.EXTRACTED) continue;
|
|
16144
|
+
const parsed = (0, import_types59.parseFileId)(edge.source);
|
|
15678
16145
|
if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
|
|
15679
16146
|
const site = { relPath: edge.evidence.file };
|
|
15680
16147
|
if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
|
|
@@ -15685,7 +16152,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
|
15685
16152
|
function routeCallSiteFor(graph, targetNodeId) {
|
|
15686
16153
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
15687
16154
|
const attrs = graph.getNodeAttributes(targetNodeId);
|
|
15688
|
-
if (attrs.type !==
|
|
16155
|
+
if (attrs.type !== import_types59.NodeType.RouteNode || !attrs.path) return void 0;
|
|
15689
16156
|
const site = { relPath: attrs.path };
|
|
15690
16157
|
if (attrs.line !== void 0) site.line = attrs.line;
|
|
15691
16158
|
return site;
|
|
@@ -16142,10 +16609,10 @@ var SUPABASE_RPC_TARGET_KIND = "supabase-rpc";
|
|
|
16142
16609
|
// src/connectors/supabase/map.ts
|
|
16143
16610
|
var REST_RPC_PATH_RE = /^\/rest\/v1\/rpc\/([^/?]+)/;
|
|
16144
16611
|
var REST_TABLE_PATH_RE = /^\/rest\/v1\/([^/?]+)/;
|
|
16145
|
-
function targetFromRestPath(
|
|
16146
|
-
const rpcMatch = REST_RPC_PATH_RE.exec(
|
|
16612
|
+
function targetFromRestPath(path74) {
|
|
16613
|
+
const rpcMatch = REST_RPC_PATH_RE.exec(path74);
|
|
16147
16614
|
if (rpcMatch) return { targetKind: SUPABASE_RPC_TARGET_KIND, name: rpcMatch[1] };
|
|
16148
|
-
const tableMatch = REST_TABLE_PATH_RE.exec(
|
|
16615
|
+
const tableMatch = REST_TABLE_PATH_RE.exec(path74);
|
|
16149
16616
|
if (tableMatch) return { targetKind: SUPABASE_TABLE_TARGET_KIND, name: tableMatch[1] };
|
|
16150
16617
|
return null;
|
|
16151
16618
|
}
|
|
@@ -16256,23 +16723,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
|
|
|
16256
16723
|
|
|
16257
16724
|
// src/connectors/supabase/resolve.ts
|
|
16258
16725
|
init_cjs_shims();
|
|
16259
|
-
var
|
|
16726
|
+
var import_types61 = require("@neat.is/types");
|
|
16260
16727
|
function createSupabaseResolveTarget(graph, config) {
|
|
16261
16728
|
return (signal, _ctx) => {
|
|
16262
16729
|
if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
|
|
16263
16730
|
return null;
|
|
16264
16731
|
}
|
|
16265
|
-
const subResourceId = (0,
|
|
16732
|
+
const subResourceId = (0, import_types61.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
|
|
16266
16733
|
if (graph.hasNode(subResourceId)) {
|
|
16267
|
-
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType:
|
|
16734
|
+
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types61.EdgeType.CALLS };
|
|
16268
16735
|
}
|
|
16269
|
-
const bareResourceId = (0,
|
|
16736
|
+
const bareResourceId = (0, import_types61.infraId)(signal.targetKind, signal.targetName);
|
|
16270
16737
|
if (graph.hasNode(bareResourceId)) {
|
|
16271
|
-
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType:
|
|
16738
|
+
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types61.EdgeType.CALLS };
|
|
16272
16739
|
}
|
|
16273
|
-
const projectLevelId = (0,
|
|
16740
|
+
const projectLevelId = (0, import_types61.infraId)("supabase", config.nodeRef);
|
|
16274
16741
|
if (graph.hasNode(projectLevelId)) {
|
|
16275
|
-
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType:
|
|
16742
|
+
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types61.EdgeType.CALLS };
|
|
16276
16743
|
}
|
|
16277
16744
|
return null;
|
|
16278
16745
|
};
|
|
@@ -16365,7 +16832,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
|
|
|
16365
16832
|
|
|
16366
16833
|
// src/connectors/railway/index.ts
|
|
16367
16834
|
init_cjs_shims();
|
|
16368
|
-
var
|
|
16835
|
+
var import_types65 = require("@neat.is/types");
|
|
16369
16836
|
|
|
16370
16837
|
// src/connectors/railway/client.ts
|
|
16371
16838
|
init_cjs_shims();
|
|
@@ -16516,7 +16983,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
|
|
|
16516
16983
|
const out = [];
|
|
16517
16984
|
graph.forEachNode((_id, attrs) => {
|
|
16518
16985
|
const node = attrs;
|
|
16519
|
-
if (node.type !==
|
|
16986
|
+
if (node.type !== import_types65.NodeType.RouteNode) return;
|
|
16520
16987
|
const route = attrs;
|
|
16521
16988
|
if (route.service !== serviceName) return;
|
|
16522
16989
|
out.push({
|
|
@@ -16620,12 +17087,12 @@ function createRailwayResolveTarget(config) {
|
|
|
16620
17087
|
const serviceName = config.serviceNameById[config.serviceId];
|
|
16621
17088
|
if (!serviceName) return null;
|
|
16622
17089
|
if (signal.targetKind === ROUTE_TARGET_KIND) {
|
|
16623
|
-
return { targetNodeId: signal.targetName, serviceName, edgeType:
|
|
17090
|
+
return { targetNodeId: signal.targetName, serviceName, edgeType: import_types65.EdgeType.CALLS };
|
|
16624
17091
|
}
|
|
16625
17092
|
if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
|
|
16626
17093
|
const peerName = config.serviceNameById[signal.targetName];
|
|
16627
17094
|
if (!peerName) return null;
|
|
16628
|
-
return { targetNodeId: (0,
|
|
17095
|
+
return { targetNodeId: (0, import_types65.serviceId)(peerName), serviceName, edgeType: import_types65.EdgeType.CONNECTS_TO };
|
|
16629
17096
|
}
|
|
16630
17097
|
return null;
|
|
16631
17098
|
};
|
|
@@ -16749,9 +17216,9 @@ function parseFirebaseTargetName(targetName) {
|
|
|
16749
17216
|
const secondSep = rest.indexOf(FIELD_SEP);
|
|
16750
17217
|
if (secondSep === -1) return null;
|
|
16751
17218
|
const method = rest.slice(0, secondSep);
|
|
16752
|
-
const
|
|
16753
|
-
if (!resourceName || !method || !
|
|
16754
|
-
return { resourceName, method, path:
|
|
17219
|
+
const path74 = rest.slice(secondSep + 1);
|
|
17220
|
+
if (!resourceName || !method || !path74) return null;
|
|
17221
|
+
return { resourceName, method, path: path74 };
|
|
16755
17222
|
}
|
|
16756
17223
|
function resourceNameFor(type, labels) {
|
|
16757
17224
|
if (!labels) return null;
|
|
@@ -16789,14 +17256,14 @@ function mapLogEntryToSignal(entry) {
|
|
|
16789
17256
|
if (!req) return null;
|
|
16790
17257
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
16791
17258
|
const method = req.requestMethod.toUpperCase();
|
|
16792
|
-
const
|
|
16793
|
-
if (
|
|
17259
|
+
const path74 = pathFromRequestUrl(req.requestUrl);
|
|
17260
|
+
if (path74 === null) return null;
|
|
16794
17261
|
const timestamp = entry.timestamp;
|
|
16795
17262
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
16796
17263
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD2;
|
|
16797
17264
|
return {
|
|
16798
17265
|
targetKind: resourceType,
|
|
16799
|
-
targetName: packFirebaseTargetName({ resourceName, method, path:
|
|
17266
|
+
targetName: packFirebaseTargetName({ resourceName, method, path: path74 }),
|
|
16800
17267
|
callCount: 1,
|
|
16801
17268
|
errorCount: isError ? 1 : 0,
|
|
16802
17269
|
lastObservedIso: timestamp
|
|
@@ -16813,7 +17280,7 @@ function mapLogEntriesToSignals(entries) {
|
|
|
16813
17280
|
|
|
16814
17281
|
// src/connectors/firebase/resolve.ts
|
|
16815
17282
|
init_cjs_shims();
|
|
16816
|
-
var
|
|
17283
|
+
var import_types66 = require("@neat.is/types");
|
|
16817
17284
|
function neatServiceNameFor(resourceType, resourceName, serviceMap) {
|
|
16818
17285
|
switch (resourceType) {
|
|
16819
17286
|
case "cloud_function":
|
|
@@ -16828,7 +17295,7 @@ function routeEntriesFor(graph, serviceName) {
|
|
|
16828
17295
|
const entries = [];
|
|
16829
17296
|
graph.forEachNode((_id, attrs) => {
|
|
16830
17297
|
const node = attrs;
|
|
16831
|
-
if (node.type !==
|
|
17298
|
+
if (node.type !== import_types66.NodeType.RouteNode) return;
|
|
16832
17299
|
const route = attrs;
|
|
16833
17300
|
if (route.service !== serviceName) return;
|
|
16834
17301
|
entries.push({
|
|
@@ -16860,7 +17327,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
|
|
|
16860
17327
|
return {
|
|
16861
17328
|
targetNodeId: match.routeNodeId,
|
|
16862
17329
|
serviceName,
|
|
16863
|
-
edgeType:
|
|
17330
|
+
edgeType: import_types66.EdgeType.CALLS
|
|
16864
17331
|
};
|
|
16865
17332
|
};
|
|
16866
17333
|
}
|
|
@@ -16887,7 +17354,7 @@ init_cjs_shims();
|
|
|
16887
17354
|
|
|
16888
17355
|
// src/connectors/cloudflare/connector.ts
|
|
16889
17356
|
init_cjs_shims();
|
|
16890
|
-
var
|
|
17357
|
+
var import_types68 = require("@neat.is/types");
|
|
16891
17358
|
|
|
16892
17359
|
// src/connectors/cloudflare/client.ts
|
|
16893
17360
|
init_cjs_shims();
|
|
@@ -17003,7 +17470,7 @@ function mapEventToSignal(event) {
|
|
|
17003
17470
|
if (Number.isNaN(observedAt.getTime())) return null;
|
|
17004
17471
|
const statusCode = metadata?.statusCode;
|
|
17005
17472
|
const isError = typeof statusCode === "number" && statusCode >= ERROR_STATUS_THRESHOLD3;
|
|
17006
|
-
const
|
|
17473
|
+
const path74 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
|
|
17007
17474
|
return {
|
|
17008
17475
|
targetKind: CLOUDFLARE_TARGET_KIND,
|
|
17009
17476
|
targetName: scriptName,
|
|
@@ -17011,7 +17478,7 @@ function mapEventToSignal(event) {
|
|
|
17011
17478
|
errorCount: isError ? 1 : 0,
|
|
17012
17479
|
lastObservedIso: observedAt.toISOString(),
|
|
17013
17480
|
method,
|
|
17014
|
-
...
|
|
17481
|
+
...path74 ? { path: path74 } : {},
|
|
17015
17482
|
...typeof statusCode === "number" ? { statusCode } : {},
|
|
17016
17483
|
...typeof metadata?.duration === "number" ? { duration: metadata.duration } : {}
|
|
17017
17484
|
};
|
|
@@ -17051,19 +17518,19 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
17051
17518
|
graph.forEachNode((id, attrs) => {
|
|
17052
17519
|
if (found) return;
|
|
17053
17520
|
const a = attrs;
|
|
17054
|
-
if (a.type ===
|
|
17521
|
+
if (a.type === import_types68.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
|
|
17055
17522
|
found = id;
|
|
17056
17523
|
}
|
|
17057
17524
|
});
|
|
17058
17525
|
return found;
|
|
17059
17526
|
}
|
|
17060
|
-
function findMatchingRouteNode(graph, serviceName, method,
|
|
17061
|
-
const normalizedPath = normalizePathTemplate(
|
|
17527
|
+
function findMatchingRouteNode(graph, serviceName, method, path74) {
|
|
17528
|
+
const normalizedPath = normalizePathTemplate(path74);
|
|
17062
17529
|
let found = null;
|
|
17063
17530
|
graph.forEachNode((id, attrs) => {
|
|
17064
17531
|
if (found) return;
|
|
17065
17532
|
const a = attrs;
|
|
17066
|
-
if (a.type !==
|
|
17533
|
+
if (a.type !== import_types68.NodeType.RouteNode || a.service !== serviceName) return;
|
|
17067
17534
|
if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
|
|
17068
17535
|
const routeMethod = (a.method ?? "").toUpperCase();
|
|
17069
17536
|
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
@@ -17075,18 +17542,18 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
17075
17542
|
return (signal) => {
|
|
17076
17543
|
if (signal.targetKind !== CLOUDFLARE_TARGET_KIND) return null;
|
|
17077
17544
|
const scriptName = signal.targetName;
|
|
17078
|
-
const { method, path:
|
|
17545
|
+
const { method, path: path74 } = signal;
|
|
17079
17546
|
const resolveRouteGrain = (serviceName, wholeFileId) => {
|
|
17080
|
-
if (!method || !
|
|
17081
|
-
return findMatchingRouteNode(graph, serviceName, method,
|
|
17547
|
+
if (!method || !path74) return wholeFileId;
|
|
17548
|
+
return findMatchingRouteNode(graph, serviceName, method, path74) ?? wholeFileId;
|
|
17082
17549
|
};
|
|
17083
17550
|
const mapping = config.workers?.[scriptName];
|
|
17084
17551
|
if (mapping) {
|
|
17085
|
-
const wholeFileId = (0,
|
|
17552
|
+
const wholeFileId = (0, import_types68.fileId)(mapping.service, mapping.entryFile);
|
|
17086
17553
|
return {
|
|
17087
17554
|
targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
|
|
17088
17555
|
serviceName: mapping.service,
|
|
17089
|
-
edgeType:
|
|
17556
|
+
edgeType: import_types68.EdgeType.CALLS
|
|
17090
17557
|
};
|
|
17091
17558
|
}
|
|
17092
17559
|
const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
|
|
@@ -17095,13 +17562,13 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
17095
17562
|
return {
|
|
17096
17563
|
targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
|
|
17097
17564
|
serviceName: fileNode.service,
|
|
17098
|
-
edgeType:
|
|
17565
|
+
edgeType: import_types68.EdgeType.CALLS
|
|
17099
17566
|
};
|
|
17100
17567
|
}
|
|
17101
17568
|
return {
|
|
17102
|
-
targetNodeId: (0,
|
|
17569
|
+
targetNodeId: (0, import_types68.infraId)("cloudflare-worker", scriptName),
|
|
17103
17570
|
serviceName: scriptName,
|
|
17104
|
-
edgeType:
|
|
17571
|
+
edgeType: import_types68.EdgeType.CALLS,
|
|
17105
17572
|
ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
|
|
17106
17573
|
};
|
|
17107
17574
|
};
|
|
@@ -17297,14 +17764,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
|
|
|
17297
17764
|
|
|
17298
17765
|
// src/connectors/neon/resolve.ts
|
|
17299
17766
|
init_cjs_shims();
|
|
17300
|
-
var
|
|
17767
|
+
var import_types72 = require("@neat.is/types");
|
|
17301
17768
|
function createNeonResolveTarget(config) {
|
|
17302
17769
|
return (signal) => {
|
|
17303
17770
|
if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
17304
17771
|
return {
|
|
17305
|
-
targetNodeId: (0,
|
|
17772
|
+
targetNodeId: (0, import_types72.infraId)("sql-table", signal.targetName),
|
|
17306
17773
|
serviceName: config.serviceName,
|
|
17307
|
-
edgeType:
|
|
17774
|
+
edgeType: import_types72.EdgeType.CALLS,
|
|
17308
17775
|
ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
|
|
17309
17776
|
};
|
|
17310
17777
|
};
|
|
@@ -17430,9 +17897,9 @@ function parseCloudRunTargetName(targetName) {
|
|
|
17430
17897
|
const secondSep = rest.indexOf(FIELD_SEP2);
|
|
17431
17898
|
if (secondSep === -1) return null;
|
|
17432
17899
|
const method = rest.slice(0, secondSep);
|
|
17433
|
-
const
|
|
17434
|
-
if (!serviceName || !method || !
|
|
17435
|
-
return { serviceName, method, path:
|
|
17900
|
+
const path74 = rest.slice(secondSep + 1);
|
|
17901
|
+
if (!serviceName || !method || !path74) return null;
|
|
17902
|
+
return { serviceName, method, path: path74 };
|
|
17436
17903
|
}
|
|
17437
17904
|
|
|
17438
17905
|
// src/connectors/cloud-run/map.ts
|
|
@@ -17461,14 +17928,14 @@ function mapLogEntryToSignal2(entry) {
|
|
|
17461
17928
|
if (!req) return null;
|
|
17462
17929
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
17463
17930
|
const method = req.requestMethod.toUpperCase();
|
|
17464
|
-
const
|
|
17465
|
-
if (
|
|
17931
|
+
const path74 = pathFromRequestUrl2(req.requestUrl);
|
|
17932
|
+
if (path74 === null) return null;
|
|
17466
17933
|
const timestamp = entry.timestamp;
|
|
17467
17934
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
17468
17935
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD4;
|
|
17469
17936
|
return {
|
|
17470
17937
|
targetKind: CLOUD_RUN_TARGET_KIND,
|
|
17471
|
-
targetName: packCloudRunTargetName({ serviceName, method, path:
|
|
17938
|
+
targetName: packCloudRunTargetName({ serviceName, method, path: path74 }),
|
|
17472
17939
|
callCount: 1,
|
|
17473
17940
|
errorCount: isError ? 1 : 0,
|
|
17474
17941
|
lastObservedIso: timestamp
|
|
@@ -17485,14 +17952,14 @@ function mapLogEntriesToSignals2(entries) {
|
|
|
17485
17952
|
|
|
17486
17953
|
// src/connectors/cloud-run/resolve.ts
|
|
17487
17954
|
init_cjs_shims();
|
|
17488
|
-
var
|
|
17955
|
+
var import_types76 = require("@neat.is/types");
|
|
17489
17956
|
var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
|
|
17490
17957
|
function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
|
|
17491
17958
|
let found = null;
|
|
17492
17959
|
graph.forEachNode((_id, attrs) => {
|
|
17493
17960
|
if (found) return;
|
|
17494
17961
|
const node = attrs;
|
|
17495
|
-
if (node.type !==
|
|
17962
|
+
if (node.type !== import_types76.NodeType.RouteNode) return;
|
|
17496
17963
|
const route = attrs;
|
|
17497
17964
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
17498
17965
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -17507,23 +17974,23 @@ function createCloudRunResolveTarget(graph, config) {
|
|
|
17507
17974
|
if (signal.targetKind !== CLOUD_RUN_TARGET_KIND) return null;
|
|
17508
17975
|
const identity = parseCloudRunTargetName(signal.targetName);
|
|
17509
17976
|
if (!identity) return null;
|
|
17510
|
-
const { serviceName: gcpServiceName, method, path:
|
|
17977
|
+
const { serviceName: gcpServiceName, method, path: path74 } = identity;
|
|
17511
17978
|
const mappedService = config.serviceMap?.[gcpServiceName];
|
|
17512
17979
|
if (mappedService) {
|
|
17513
17980
|
const routeNodeId = findMatchingRouteNode2(
|
|
17514
17981
|
graph,
|
|
17515
17982
|
mappedService,
|
|
17516
17983
|
method,
|
|
17517
|
-
normalizePathTemplate(
|
|
17984
|
+
normalizePathTemplate(path74)
|
|
17518
17985
|
);
|
|
17519
17986
|
if (routeNodeId) {
|
|
17520
|
-
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType:
|
|
17987
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types76.EdgeType.CALLS };
|
|
17521
17988
|
}
|
|
17522
17989
|
}
|
|
17523
17990
|
return {
|
|
17524
|
-
targetNodeId: (0,
|
|
17991
|
+
targetNodeId: (0, import_types76.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
|
|
17525
17992
|
serviceName: mappedService ?? gcpServiceName,
|
|
17526
|
-
edgeType:
|
|
17993
|
+
edgeType: import_types76.EdgeType.CALLS,
|
|
17527
17994
|
ensureInfraNode: {
|
|
17528
17995
|
kind: CLOUD_RUN_SERVICE_INFRA_KIND,
|
|
17529
17996
|
name: gcpServiceName,
|
|
@@ -17564,7 +18031,7 @@ function createCloudRunConnector(graph, config = {}) {
|
|
|
17564
18031
|
|
|
17565
18032
|
// src/connectors/render/index.ts
|
|
17566
18033
|
init_cjs_shims();
|
|
17567
|
-
var
|
|
18034
|
+
var import_types79 = require("@neat.is/types");
|
|
17568
18035
|
|
|
17569
18036
|
// src/connectors/render/types.ts
|
|
17570
18037
|
init_cjs_shims();
|
|
@@ -17642,7 +18109,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
17642
18109
|
const out = [];
|
|
17643
18110
|
graph.forEachNode((_id, attrs) => {
|
|
17644
18111
|
const node = attrs;
|
|
17645
|
-
if (node.type !==
|
|
18112
|
+
if (node.type !== import_types79.NodeType.RouteNode) return;
|
|
17646
18113
|
const route = attrs;
|
|
17647
18114
|
if (route.service !== serviceName) return;
|
|
17648
18115
|
out.push({
|
|
@@ -17727,7 +18194,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
|
|
|
17727
18194
|
function createRenderResolveTarget(config) {
|
|
17728
18195
|
return (signal) => {
|
|
17729
18196
|
if (signal.targetKind === ROUTE_TARGET_KIND2) {
|
|
17730
|
-
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType:
|
|
18197
|
+
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types79.EdgeType.CALLS };
|
|
17731
18198
|
}
|
|
17732
18199
|
return null;
|
|
17733
18200
|
};
|
|
@@ -17865,21 +18332,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
|
|
|
17865
18332
|
|
|
17866
18333
|
// src/connectors/planetscale/resolve.ts
|
|
17867
18334
|
init_cjs_shims();
|
|
17868
|
-
var
|
|
18335
|
+
var import_types83 = require("@neat.is/types");
|
|
17869
18336
|
var PLANETSCALE_DATABASE_KIND = "planetscale-database";
|
|
17870
18337
|
function createPlanetscaleResolveTarget(graph, config) {
|
|
17871
18338
|
const databaseName = `${config.organization}/${config.database}`;
|
|
17872
18339
|
return (signal, _ctx) => {
|
|
17873
18340
|
if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
17874
|
-
const tableId = (0,
|
|
18341
|
+
const tableId = (0, import_types83.infraId)("sql-table", signal.targetName);
|
|
17875
18342
|
if (graph.hasNode(tableId)) {
|
|
17876
|
-
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType:
|
|
18343
|
+
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types83.EdgeType.CALLS };
|
|
17877
18344
|
}
|
|
17878
|
-
const providerId = (0,
|
|
18345
|
+
const providerId = (0, import_types83.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
|
|
17879
18346
|
return {
|
|
17880
18347
|
targetNodeId: providerId,
|
|
17881
18348
|
serviceName: config.serviceName,
|
|
17882
|
-
edgeType:
|
|
18349
|
+
edgeType: import_types83.EdgeType.CALLS,
|
|
17883
18350
|
ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
|
|
17884
18351
|
};
|
|
17885
18352
|
};
|
|
@@ -18144,7 +18611,7 @@ function mapBuildsToSignals(builds, serviceName) {
|
|
|
18144
18611
|
|
|
18145
18612
|
// src/connectors/eas/resolve.ts
|
|
18146
18613
|
init_cjs_shims();
|
|
18147
|
-
var
|
|
18614
|
+
var import_types88 = require("@neat.is/types");
|
|
18148
18615
|
var NO_ENV2 = "unknown";
|
|
18149
18616
|
var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
|
|
18150
18617
|
var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
|
|
@@ -18160,8 +18627,8 @@ function configBasenamesForPhase(phase) {
|
|
|
18160
18627
|
function configNodeService(graph, configNodeId) {
|
|
18161
18628
|
for (const edgeId of graph.inboundEdges(configNodeId)) {
|
|
18162
18629
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
18163
|
-
if (edge.type !==
|
|
18164
|
-
const parsed = (0,
|
|
18630
|
+
if (edge.type !== import_types88.EdgeType.CONFIGURED_BY) continue;
|
|
18631
|
+
const parsed = (0, import_types88.parseFileId)(edge.source);
|
|
18165
18632
|
if (parsed) return parsed.service;
|
|
18166
18633
|
}
|
|
18167
18634
|
return null;
|
|
@@ -18172,7 +18639,7 @@ function findConfigNode(graph, basenames, serviceName) {
|
|
|
18172
18639
|
graph.forEachNode((id, attrs) => {
|
|
18173
18640
|
if (scoped) return;
|
|
18174
18641
|
const node = attrs;
|
|
18175
|
-
if (node.type !==
|
|
18642
|
+
if (node.type !== import_types88.NodeType.ConfigNode) return;
|
|
18176
18643
|
if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
|
|
18177
18644
|
if (anyMatch === null) anyMatch = id;
|
|
18178
18645
|
if (configNodeService(graph, id) === serviceName) scoped = id;
|
|
@@ -18189,13 +18656,13 @@ function createEasResolveTarget(graph) {
|
|
|
18189
18656
|
if (basenames.length > 0) {
|
|
18190
18657
|
const configNodeId = findConfigNode(graph, basenames, serviceName);
|
|
18191
18658
|
if (configNodeId) {
|
|
18192
|
-
return { targetNodeId: configNodeId, serviceName, edgeType:
|
|
18659
|
+
return { targetNodeId: configNodeId, serviceName, edgeType: import_types88.EdgeType.CALLS };
|
|
18193
18660
|
}
|
|
18194
18661
|
}
|
|
18195
18662
|
return {
|
|
18196
18663
|
targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
|
|
18197
18664
|
serviceName,
|
|
18198
|
-
edgeType:
|
|
18665
|
+
edgeType: import_types88.EdgeType.CALLS
|
|
18199
18666
|
};
|
|
18200
18667
|
};
|
|
18201
18668
|
}
|
|
@@ -18874,11 +19341,11 @@ function registerRoutes(scope, ctx) {
|
|
|
18874
19341
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
18875
19342
|
const parsed = [];
|
|
18876
19343
|
for (const c of candidates) {
|
|
18877
|
-
const r =
|
|
19344
|
+
const r = import_types91.DivergenceTypeSchema.safeParse(c);
|
|
18878
19345
|
if (!r.success) {
|
|
18879
19346
|
return reply.code(400).send({
|
|
18880
19347
|
error: `unknown divergence type "${c}"`,
|
|
18881
|
-
allowed:
|
|
19348
|
+
allowed: import_types91.DivergenceTypeSchema.options
|
|
18882
19349
|
});
|
|
18883
19350
|
}
|
|
18884
19351
|
parsed.push(r.data);
|
|
@@ -19220,7 +19687,7 @@ function registerRoutes(scope, ctx) {
|
|
|
19220
19687
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
19221
19688
|
let violations = await log.readAll();
|
|
19222
19689
|
if (req.query.severity) {
|
|
19223
|
-
const sev =
|
|
19690
|
+
const sev = import_types91.PolicySeveritySchema.safeParse(req.query.severity);
|
|
19224
19691
|
if (!sev.success) {
|
|
19225
19692
|
return reply.code(400).send({
|
|
19226
19693
|
error: "invalid severity",
|
|
@@ -19259,7 +19726,7 @@ function registerRoutes(scope, ctx) {
|
|
|
19259
19726
|
scope.post("/policies/check", async (req, reply) => {
|
|
19260
19727
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
19261
19728
|
if (!proj) return;
|
|
19262
|
-
const parsed =
|
|
19729
|
+
const parsed = import_types91.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
19263
19730
|
if (!parsed.success) {
|
|
19264
19731
|
return reply.code(400).send({
|
|
19265
19732
|
error: "invalid /policies/check body",
|
|
@@ -19580,8 +20047,8 @@ init_otel_grpc();
|
|
|
19580
20047
|
|
|
19581
20048
|
// src/search.ts
|
|
19582
20049
|
init_cjs_shims();
|
|
19583
|
-
var
|
|
19584
|
-
var
|
|
20050
|
+
var import_node_fs38 = require("fs");
|
|
20051
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
19585
20052
|
var import_node_crypto4 = require("crypto");
|
|
19586
20053
|
var DEFAULT_LIMIT = 10;
|
|
19587
20054
|
var NOMIC_DIM = 768;
|
|
@@ -19735,7 +20202,7 @@ async function pickEmbedder() {
|
|
|
19735
20202
|
}
|
|
19736
20203
|
async function readCache(cachePath) {
|
|
19737
20204
|
try {
|
|
19738
|
-
const raw = await
|
|
20205
|
+
const raw = await import_node_fs38.promises.readFile(cachePath, "utf8");
|
|
19739
20206
|
const parsed = JSON.parse(raw);
|
|
19740
20207
|
if (parsed.version !== 1) return null;
|
|
19741
20208
|
return parsed;
|
|
@@ -19744,8 +20211,8 @@ async function readCache(cachePath) {
|
|
|
19744
20211
|
}
|
|
19745
20212
|
}
|
|
19746
20213
|
async function writeCache(cachePath, cache) {
|
|
19747
|
-
await
|
|
19748
|
-
await
|
|
20214
|
+
await import_node_fs38.promises.mkdir(import_node_path72.default.dirname(cachePath), { recursive: true });
|
|
20215
|
+
await import_node_fs38.promises.writeFile(cachePath, JSON.stringify(cache));
|
|
19749
20216
|
}
|
|
19750
20217
|
var VectorIndex = class {
|
|
19751
20218
|
constructor(embedder, cachePath) {
|
|
@@ -19959,14 +20426,14 @@ async function bootProject(registry, name, scanPath, baseDir) {
|
|
|
19959
20426
|
async function main() {
|
|
19960
20427
|
const baseDirEnv = process.env.NEAT_OUT_DIR;
|
|
19961
20428
|
const legacyOutPath = process.env.NEAT_OUT_PATH;
|
|
19962
|
-
const baseDir = baseDirEnv ?
|
|
19963
|
-
const defaultScanPath =
|
|
20429
|
+
const baseDir = baseDirEnv ? import_node_path73.default.resolve(baseDirEnv) : legacyOutPath ? import_node_path73.default.resolve(import_node_path73.default.dirname(legacyOutPath)) : import_node_path73.default.resolve("./neat-out");
|
|
20430
|
+
const defaultScanPath = import_node_path73.default.resolve(process.env.NEAT_SCAN_PATH ?? "./demo");
|
|
19964
20431
|
const registry = new Projects();
|
|
19965
20432
|
await bootProject(registry, DEFAULT_PROJECT, defaultScanPath, baseDir);
|
|
19966
20433
|
for (const name of parseExtraProjects(process.env.NEAT_PROJECTS)) {
|
|
19967
20434
|
const envKey = `NEAT_PROJECT_SCAN_PATH_${name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`;
|
|
19968
20435
|
const projectScan = process.env[envKey];
|
|
19969
|
-
await bootProject(registry, name, projectScan ?
|
|
20436
|
+
await bootProject(registry, name, projectScan ? import_node_path73.default.resolve(projectScan) : void 0, baseDir);
|
|
19970
20437
|
}
|
|
19971
20438
|
const host = process.env.HOST ?? "0.0.0.0";
|
|
19972
20439
|
const port = Number(process.env.PORT ?? 8080);
|