@neat.is/core 0.5.2 → 0.5.4-dev.20260721
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-I72HTUOG.js → chunk-4RU3AAOI.js} +2 -2
- package/dist/{chunk-CFDPIMRP.js → chunk-I4NZ7PSN.js} +3 -2
- package/dist/chunk-I4NZ7PSN.js.map +1 -0
- package/dist/{chunk-BI3XKGVG.js → chunk-PEFX3DBR.js} +473 -127
- package/dist/chunk-PEFX3DBR.js.map +1 -0
- package/dist/{chunk-DPEPI2N6.js → chunk-VR73QNJD.js} +293 -22
- package/dist/chunk-VR73QNJD.js.map +1 -0
- package/dist/cli.cjs +1371 -479
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +343 -75
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +879 -310
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +888 -319
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-IDMIH6ZY.js → otel-grpc-TEGOXE6T.js} +3 -3
- package/dist/server.cjs +553 -192
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-BI3XKGVG.js.map +0 -1
- package/dist/chunk-CFDPIMRP.js.map +0 -1
- package/dist/chunk-DPEPI2N6.js.map +0 -1
- /package/dist/{chunk-I72HTUOG.js.map → chunk-4RU3AAOI.js.map} +0 -0
- /package/dist/{otel-grpc-IDMIH6ZY.js.map → otel-grpc-TEGOXE6T.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 path52 = (req.url.split("?")[0] ?? "").replace(/\/+$/, "");
|
|
63
|
+
if (exactUnauthPaths.has(path52) || PROJECT_SCOPED_UNAUTH_PATTERN.test(path52)) {
|
|
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_path48.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
196
|
+
return import_node_path48.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_path48, 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_path48 = __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);
|
|
@@ -360,8 +360,8 @@ function websocketChannelPathOf(attrs) {
|
|
|
360
360
|
const v = attrs[key];
|
|
361
361
|
if (typeof v === "string" && v.length > 0) {
|
|
362
362
|
const q = v.indexOf("?");
|
|
363
|
-
const
|
|
364
|
-
if (
|
|
363
|
+
const path52 = q === -1 ? v : v.slice(0, q);
|
|
364
|
+
if (path52.length > 0) return path52;
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
367
|
return void 0;
|
|
@@ -396,6 +396,7 @@ function parseOtlpRequest(body) {
|
|
|
396
396
|
attributes: attrs,
|
|
397
397
|
dbSystem: typeof attrs["db.system"] === "string" ? attrs["db.system"] : void 0,
|
|
398
398
|
dbName: typeof attrs["db.name"] === "string" ? attrs["db.name"] : void 0,
|
|
399
|
+
dbCollection: typeof attrs["db.collection.name"] === "string" ? attrs["db.collection.name"] : typeof attrs["db.mongodb.collection"] === "string" ? attrs["db.mongodb.collection"] : void 0,
|
|
399
400
|
messagingSystem: typeof attrs["messaging.system"] === "string" ? attrs["messaging.system"] : void 0,
|
|
400
401
|
messagingDestination: messagingDestinationOf(attrs),
|
|
401
402
|
graphqlOperationName: typeof attrs["graphql.operation.name"] === "string" && attrs["graphql.operation.name"].length > 0 ? attrs["graphql.operation.name"] : void 0,
|
|
@@ -415,10 +416,10 @@ function parseOtlpRequest(body) {
|
|
|
415
416
|
return out;
|
|
416
417
|
}
|
|
417
418
|
function loadProtoRoot() {
|
|
418
|
-
const here =
|
|
419
|
-
const protoRoot =
|
|
419
|
+
const here = import_node_path49.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
420
|
+
const protoRoot = import_node_path49.default.resolve(here, "..", "proto");
|
|
420
421
|
const root = new import_protobufjs.default.Root();
|
|
421
|
-
root.resolvePath = (_origin, target) =>
|
|
422
|
+
root.resolvePath = (_origin, target) => import_node_path49.default.resolve(protoRoot, target);
|
|
422
423
|
root.loadSync(
|
|
423
424
|
"opentelemetry/proto/collector/trace/v1/trace_service.proto",
|
|
424
425
|
{ keepCase: true }
|
|
@@ -630,12 +631,12 @@ async function buildOtelReceiver(opts) {
|
|
|
630
631
|
};
|
|
631
632
|
return decorated;
|
|
632
633
|
}
|
|
633
|
-
var
|
|
634
|
+
var import_node_path49, import_node_url2, import_fastify2, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody;
|
|
634
635
|
var init_otel = __esm({
|
|
635
636
|
"src/otel.ts"() {
|
|
636
637
|
"use strict";
|
|
637
638
|
init_cjs_shims();
|
|
638
|
-
|
|
639
|
+
import_node_path49 = __toESM(require("path"), 1);
|
|
639
640
|
import_node_url2 = require("url");
|
|
640
641
|
import_fastify2 = __toESM(require("fastify"), 1);
|
|
641
642
|
import_protobufjs = __toESM(require("protobufjs"), 1);
|
|
@@ -651,7 +652,7 @@ var init_otel = __esm({
|
|
|
651
652
|
|
|
652
653
|
// src/server.ts
|
|
653
654
|
init_cjs_shims();
|
|
654
|
-
var
|
|
655
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
655
656
|
|
|
656
657
|
// src/graph.ts
|
|
657
658
|
init_cjs_shims();
|
|
@@ -675,7 +676,7 @@ function getGraph(project = DEFAULT_PROJECT) {
|
|
|
675
676
|
init_cjs_shims();
|
|
676
677
|
var import_fastify = __toESM(require("fastify"), 1);
|
|
677
678
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
678
|
-
var
|
|
679
|
+
var import_types34 = require("@neat.is/types");
|
|
679
680
|
|
|
680
681
|
// src/extend/index.ts
|
|
681
682
|
init_cjs_shims();
|
|
@@ -777,11 +778,42 @@ async function readPackageJson(scanPath) {
|
|
|
777
778
|
const raw = await import_node_fs2.promises.readFile(pkgPath, "utf8");
|
|
778
779
|
return JSON.parse(raw);
|
|
779
780
|
}
|
|
781
|
+
var HOOK_WALK_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
782
|
+
"node_modules",
|
|
783
|
+
"dist",
|
|
784
|
+
"build",
|
|
785
|
+
"out",
|
|
786
|
+
"coverage",
|
|
787
|
+
"neat-out"
|
|
788
|
+
]);
|
|
780
789
|
async function findHookFiles(scanPath) {
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
790
|
+
const found = [];
|
|
791
|
+
const walk3 = async (dir) => {
|
|
792
|
+
const entries = await import_node_fs2.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
793
|
+
for (const entry of entries) {
|
|
794
|
+
if (entry.isDirectory()) {
|
|
795
|
+
if (entry.name.startsWith(".") || HOOK_WALK_SKIP_DIRS.has(entry.name)) continue;
|
|
796
|
+
await walk3(import_node_path2.default.join(dir, entry.name));
|
|
797
|
+
} else if (entry.isFile()) {
|
|
798
|
+
if ((entry.name.startsWith("instrumentation") || entry.name.startsWith("otel-init")) && /\.(ts|js|cjs|mjs)$/.test(entry.name)) {
|
|
799
|
+
const rel = import_node_path2.default.relative(scanPath, import_node_path2.default.join(dir, entry.name));
|
|
800
|
+
found.push(rel.split(import_node_path2.default.sep).join("/"));
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
};
|
|
805
|
+
await walk3(scanPath);
|
|
806
|
+
return found.sort();
|
|
807
|
+
}
|
|
808
|
+
async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
|
|
809
|
+
let fallback = null;
|
|
810
|
+
for (const file of hookFiles) {
|
|
811
|
+
const content = await import_node_fs2.promises.readFile(import_node_path2.default.join(scanPath, file), "utf8");
|
|
812
|
+
const patched = splicedContent(content, snippet2);
|
|
813
|
+
if (patched !== null) return { file, content, patched };
|
|
814
|
+
if (fallback === null) fallback = { file, content };
|
|
815
|
+
}
|
|
816
|
+
return { file: fallback.file, content: fallback.content, patched: null };
|
|
785
817
|
}
|
|
786
818
|
function extendLogPath() {
|
|
787
819
|
return process.env.NEAT_EXTEND_LOG ?? import_node_path2.default.join(import_node_os.default.homedir(), ".neat", "extend-log.ndjson");
|
|
@@ -874,7 +906,13 @@ async function applyExtension(ctx, args, options) {
|
|
|
874
906
|
return { library: args.library, filesTouched: [], depsAdded: [], installOutput: "", alreadyApplied: true };
|
|
875
907
|
}
|
|
876
908
|
}
|
|
877
|
-
const
|
|
909
|
+
const primary = await pickPrimaryHookFile(ctx.scanPath, hookFiles, args.registration_snippet);
|
|
910
|
+
if (primary.patched === null) {
|
|
911
|
+
throw new Error(
|
|
912
|
+
`Could not find instrumentation insertion point in ${hookFiles.join(", ")}. Expected __INSTRUMENTATION_BLOCK__, instrumentations.push(, or new NodeSDK(.`
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
const primaryFile = primary.file;
|
|
878
916
|
const primaryPath = import_node_path2.default.join(ctx.scanPath, primaryFile);
|
|
879
917
|
const filesTouched = [];
|
|
880
918
|
const depsAdded = [];
|
|
@@ -886,14 +924,7 @@ async function applyExtension(ctx, args, options) {
|
|
|
886
924
|
filesTouched.push("package.json");
|
|
887
925
|
depsAdded.push(`${args.instrumentation_package}@${args.version}`);
|
|
888
926
|
}
|
|
889
|
-
|
|
890
|
-
const patched = splicedContent(hookContent, args.registration_snippet);
|
|
891
|
-
if (!patched) {
|
|
892
|
-
throw new Error(
|
|
893
|
-
`Could not find instrumentation insertion point in ${primaryFile}. Expected __INSTRUMENTATION_BLOCK__, instrumentations.push(, or new NodeSDK(.`
|
|
894
|
-
);
|
|
895
|
-
}
|
|
896
|
-
await import_node_fs2.promises.writeFile(primaryPath, patched, "utf8");
|
|
927
|
+
await import_node_fs2.promises.writeFile(primaryPath, primary.patched, "utf8");
|
|
897
928
|
filesTouched.push(primaryFile);
|
|
898
929
|
const cmd = await detectPackageManager(ctx.scanPath);
|
|
899
930
|
const installer = options?.runInstall ?? runPackageManagerInstall;
|
|
@@ -935,7 +966,7 @@ async function dryRunExtension(ctx, args) {
|
|
|
935
966
|
};
|
|
936
967
|
}
|
|
937
968
|
}
|
|
938
|
-
const
|
|
969
|
+
const primary = await pickPrimaryHookFile(ctx.scanPath, hookFiles, args.registration_snippet);
|
|
939
970
|
const filesTouched = [];
|
|
940
971
|
const depsToAdd = [];
|
|
941
972
|
let packageJsonPatch = {};
|
|
@@ -946,10 +977,8 @@ async function dryRunExtension(ctx, args) {
|
|
|
946
977
|
depsToAdd.push(`${args.instrumentation_package}@${args.version}`);
|
|
947
978
|
filesTouched.push("package.json");
|
|
948
979
|
}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
if (patched) {
|
|
952
|
-
filesTouched.push(primaryFile);
|
|
980
|
+
if (primary.patched !== null) {
|
|
981
|
+
filesTouched.push(primary.file);
|
|
953
982
|
templatePatch = `+ ${args.registration_snippet}`;
|
|
954
983
|
} else {
|
|
955
984
|
templatePatch = "Could not find insertion point in hook file.";
|
|
@@ -1418,19 +1447,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
1418
1447
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
1419
1448
|
let best = { path: [start], edges: [] };
|
|
1420
1449
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
1421
|
-
function step(node,
|
|
1422
|
-
if (
|
|
1423
|
-
best = { path: [...
|
|
1450
|
+
function step(node, path52, edges) {
|
|
1451
|
+
if (path52.length > best.path.length) {
|
|
1452
|
+
best = { path: [...path52], edges: [...edges] };
|
|
1424
1453
|
}
|
|
1425
|
-
if (
|
|
1454
|
+
if (path52.length - 1 >= maxDepth) return;
|
|
1426
1455
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
1427
1456
|
for (const [srcId, edge] of incoming) {
|
|
1428
1457
|
if (visited.has(srcId)) continue;
|
|
1429
1458
|
visited.add(srcId);
|
|
1430
|
-
|
|
1459
|
+
path52.push(srcId);
|
|
1431
1460
|
edges.push(edge);
|
|
1432
|
-
step(srcId,
|
|
1433
|
-
|
|
1461
|
+
step(srcId, path52, edges);
|
|
1462
|
+
path52.pop();
|
|
1434
1463
|
edges.pop();
|
|
1435
1464
|
visited.delete(srcId);
|
|
1436
1465
|
}
|
|
@@ -1624,26 +1653,26 @@ function dominantFailingCall(graph, serviceId5, visited) {
|
|
|
1624
1653
|
return best;
|
|
1625
1654
|
}
|
|
1626
1655
|
function followFailingCallChain(graph, originServiceId, maxDepth) {
|
|
1627
|
-
const
|
|
1656
|
+
const path52 = [originServiceId];
|
|
1628
1657
|
const edges = [];
|
|
1629
1658
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
1630
1659
|
let current = originServiceId;
|
|
1631
1660
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
1632
1661
|
const hop = dominantFailingCall(graph, current, visited);
|
|
1633
1662
|
if (!hop) break;
|
|
1634
|
-
|
|
1663
|
+
path52.push(hop.nextService);
|
|
1635
1664
|
edges.push(hop.edge);
|
|
1636
1665
|
visited.add(hop.nextService);
|
|
1637
1666
|
current = hop.nextService;
|
|
1638
1667
|
}
|
|
1639
1668
|
if (edges.length === 0) return null;
|
|
1640
|
-
return { path:
|
|
1669
|
+
return { path: path52, edges, culprit: current };
|
|
1641
1670
|
}
|
|
1642
1671
|
function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
1643
1672
|
const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
|
|
1644
1673
|
if (!chain) return null;
|
|
1645
1674
|
const culprit = chain.culprit;
|
|
1646
|
-
const
|
|
1675
|
+
const path52 = [...chain.path];
|
|
1647
1676
|
const edgeProvenances = chain.edges.map((e) => e.provenance);
|
|
1648
1677
|
const baseConfidence = confidenceFromMix(chain.edges);
|
|
1649
1678
|
const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
|
|
@@ -1651,14 +1680,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
1651
1680
|
if (loc) {
|
|
1652
1681
|
let rootCauseNode = culprit;
|
|
1653
1682
|
if (loc.fileNode) {
|
|
1654
|
-
|
|
1683
|
+
path52.push(loc.fileNode);
|
|
1655
1684
|
edgeProvenances.push(import_types.Provenance.OBSERVED);
|
|
1656
1685
|
rootCauseNode = loc.fileNode;
|
|
1657
1686
|
}
|
|
1658
1687
|
return import_types.RootCauseResultSchema.parse({
|
|
1659
1688
|
rootCauseNode,
|
|
1660
1689
|
rootCauseReason: loc.rootCauseReason,
|
|
1661
|
-
traversalPath:
|
|
1690
|
+
traversalPath: path52,
|
|
1662
1691
|
edgeProvenances,
|
|
1663
1692
|
confidence,
|
|
1664
1693
|
...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
|
|
@@ -1670,7 +1699,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
1670
1699
|
return import_types.RootCauseResultSchema.parse({
|
|
1671
1700
|
rootCauseNode: culprit,
|
|
1672
1701
|
rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
|
|
1673
|
-
traversalPath:
|
|
1702
|
+
traversalPath: path52,
|
|
1674
1703
|
edgeProvenances,
|
|
1675
1704
|
confidence,
|
|
1676
1705
|
fixRecommendation: `Inspect ${culpritName}'s failing handler`
|
|
@@ -3094,6 +3123,19 @@ function ensureServiceNode(graph, serviceName, env) {
|
|
|
3094
3123
|
graph.addNode(id, node);
|
|
3095
3124
|
return id;
|
|
3096
3125
|
}
|
|
3126
|
+
function ensureInfraNode(graph, kind, name, provider) {
|
|
3127
|
+
const id = (0, import_types4.infraId)(kind, name);
|
|
3128
|
+
if (graph.hasNode(id)) return id;
|
|
3129
|
+
const node = {
|
|
3130
|
+
id,
|
|
3131
|
+
type: import_types4.NodeType.InfraNode,
|
|
3132
|
+
name,
|
|
3133
|
+
provider,
|
|
3134
|
+
kind
|
|
3135
|
+
};
|
|
3136
|
+
graph.addNode(id, node);
|
|
3137
|
+
return id;
|
|
3138
|
+
}
|
|
3097
3139
|
function ensureDatabaseNode(graph, host, engine) {
|
|
3098
3140
|
const id = (0, import_types4.databaseId)(host);
|
|
3099
3141
|
if (graph.hasNode(id)) return id;
|
|
@@ -3406,6 +3448,18 @@ async function handleSpan(ctx, span) {
|
|
|
3406
3448
|
callSiteEvidence
|
|
3407
3449
|
);
|
|
3408
3450
|
if (result) affectedNode = targetId;
|
|
3451
|
+
if (span.dbSystem === "mongodb" && span.dbCollection) {
|
|
3452
|
+
const collectionId = ensureInfraNode(ctx.graph, "mongodb-collection", span.dbCollection, "self");
|
|
3453
|
+
upsertObservedEdge(
|
|
3454
|
+
ctx.graph,
|
|
3455
|
+
import_types4.EdgeType.CALLS,
|
|
3456
|
+
observedSource(),
|
|
3457
|
+
collectionId,
|
|
3458
|
+
ts,
|
|
3459
|
+
isError,
|
|
3460
|
+
callSiteEvidence
|
|
3461
|
+
);
|
|
3462
|
+
}
|
|
3409
3463
|
}
|
|
3410
3464
|
} else if (span.messagingSystem && span.messagingDestination && spanMintsMessagingEdge(span.kind)) {
|
|
3411
3465
|
const targetId = ensureMessagingDestinationNode(
|
|
@@ -5150,14 +5204,21 @@ function engineFromImage(image) {
|
|
|
5150
5204
|
// src/extract/databases/dotenv.ts
|
|
5151
5205
|
var CONNECTION_KEYS = /* @__PURE__ */ new Set([
|
|
5152
5206
|
"DATABASE_URL",
|
|
5207
|
+
"DATABASE_URI",
|
|
5153
5208
|
"DB_URL",
|
|
5209
|
+
"DB_URI",
|
|
5154
5210
|
"POSTGRES_URL",
|
|
5211
|
+
"POSTGRES_URI",
|
|
5155
5212
|
"POSTGRESQL_URL",
|
|
5213
|
+
"POSTGRESQL_URI",
|
|
5156
5214
|
"MYSQL_URL",
|
|
5215
|
+
"MYSQL_URI",
|
|
5216
|
+
"MONGODB_URL",
|
|
5157
5217
|
"MONGODB_URI",
|
|
5158
5218
|
"MONGO_URL",
|
|
5159
5219
|
"MONGO_URI",
|
|
5160
|
-
"REDIS_URL"
|
|
5220
|
+
"REDIS_URL",
|
|
5221
|
+
"REDIS_URI"
|
|
5161
5222
|
]);
|
|
5162
5223
|
function parseDotenvLine(line) {
|
|
5163
5224
|
const trimmed = line.trim();
|
|
@@ -6246,7 +6307,7 @@ async function addGrpcMethods(graph, services) {
|
|
|
6246
6307
|
|
|
6247
6308
|
// src/extract/calls/index.ts
|
|
6248
6309
|
init_cjs_shims();
|
|
6249
|
-
var
|
|
6310
|
+
var import_types22 = require("@neat.is/types");
|
|
6250
6311
|
|
|
6251
6312
|
// src/extract/calls/http.ts
|
|
6252
6313
|
init_cjs_shims();
|
|
@@ -6959,15 +7020,311 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
6959
7020
|
return out;
|
|
6960
7021
|
}
|
|
6961
7022
|
|
|
7023
|
+
// src/extract/calls/mongoose.ts
|
|
7024
|
+
init_cjs_shims();
|
|
7025
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
7026
|
+
var import_types21 = require("@neat.is/types");
|
|
7027
|
+
var MONGOOSE_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongoose['"`]/;
|
|
7028
|
+
var MONGODB_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongodb['"`]/;
|
|
7029
|
+
var PLURALIZE_DISABLED_RE = /\bpluralize\s*\(\s*(?:null|false)\s*\)/;
|
|
7030
|
+
var UNCOUNTABLES = /* @__PURE__ */ new Set([
|
|
7031
|
+
"advice",
|
|
7032
|
+
"energy",
|
|
7033
|
+
"excretion",
|
|
7034
|
+
"digestion",
|
|
7035
|
+
"cooperation",
|
|
7036
|
+
"health",
|
|
7037
|
+
"justice",
|
|
7038
|
+
"labour",
|
|
7039
|
+
"machinery",
|
|
7040
|
+
"equipment",
|
|
7041
|
+
"information",
|
|
7042
|
+
"pollution",
|
|
7043
|
+
"sewage",
|
|
7044
|
+
"paper",
|
|
7045
|
+
"money",
|
|
7046
|
+
"species",
|
|
7047
|
+
"series",
|
|
7048
|
+
"rain",
|
|
7049
|
+
"rice",
|
|
7050
|
+
"fish",
|
|
7051
|
+
"sheep",
|
|
7052
|
+
"moose",
|
|
7053
|
+
"deer",
|
|
7054
|
+
"news",
|
|
7055
|
+
"expertise",
|
|
7056
|
+
"status",
|
|
7057
|
+
"media"
|
|
7058
|
+
]);
|
|
7059
|
+
var PLURALIZE_RULES = [
|
|
7060
|
+
[/human$/gi, "humans"],
|
|
7061
|
+
[/(m)an$/gi, "$1en"],
|
|
7062
|
+
[/(pe)rson$/gi, "$1ople"],
|
|
7063
|
+
[/(child)$/gi, "$1ren"],
|
|
7064
|
+
[/^(ox)$/gi, "$1en"],
|
|
7065
|
+
[/(ax|test)is$/gi, "$1es"],
|
|
7066
|
+
[/(octop|vir)us$/gi, "$1i"],
|
|
7067
|
+
[/(alias|status)$/gi, "$1es"],
|
|
7068
|
+
[/(bu)s$/gi, "$1ses"],
|
|
7069
|
+
[/(buffal|tomat|potat)o$/gi, "$1oes"],
|
|
7070
|
+
[/([ti])um$/gi, "$1a"],
|
|
7071
|
+
[/sis$/gi, "ses"],
|
|
7072
|
+
[/(?:([^f])fe|([lr])f)$/gi, "$1$2ves"],
|
|
7073
|
+
[/(hive)$/gi, "$1s"],
|
|
7074
|
+
[/([^aeiouy]|qu)y$/gi, "$1ies"],
|
|
7075
|
+
[/(x|ch|ss|sh)$/gi, "$1es"],
|
|
7076
|
+
[/(matr|vert|ind)ix|ex$/gi, "$1ices"],
|
|
7077
|
+
[/([m|l])ouse$/gi, "$1ice"],
|
|
7078
|
+
[/(kn|w|l)ife$/gi, "$1ives"],
|
|
7079
|
+
[/(quiz)$/gi, "$1zes"],
|
|
7080
|
+
[/s$/gi, "s"],
|
|
7081
|
+
[/([^a-z])$/, "$1"],
|
|
7082
|
+
[/$/gi, "s"]
|
|
7083
|
+
];
|
|
7084
|
+
function pluralizeCollection(name) {
|
|
7085
|
+
const str = name.toLowerCase();
|
|
7086
|
+
if (UNCOUNTABLES.has(str)) return str;
|
|
7087
|
+
for (const [re, repl] of PLURALIZE_RULES) {
|
|
7088
|
+
if (str.match(re)) return str.replace(re, repl);
|
|
7089
|
+
}
|
|
7090
|
+
return str;
|
|
7091
|
+
}
|
|
7092
|
+
var MODEL_METHODS = [
|
|
7093
|
+
"find",
|
|
7094
|
+
"findOne",
|
|
7095
|
+
"findById",
|
|
7096
|
+
"findByIdAndUpdate",
|
|
7097
|
+
"findByIdAndDelete",
|
|
7098
|
+
"findOneAndUpdate",
|
|
7099
|
+
"findOneAndDelete",
|
|
7100
|
+
"findOneAndReplace",
|
|
7101
|
+
"countDocuments",
|
|
7102
|
+
"estimatedDocumentCount",
|
|
7103
|
+
"distinct",
|
|
7104
|
+
"aggregate",
|
|
7105
|
+
"exists",
|
|
7106
|
+
"where",
|
|
7107
|
+
"populate",
|
|
7108
|
+
"watch",
|
|
7109
|
+
"hydrate",
|
|
7110
|
+
"create",
|
|
7111
|
+
"insertMany",
|
|
7112
|
+
"insertOne",
|
|
7113
|
+
"updateOne",
|
|
7114
|
+
"updateMany",
|
|
7115
|
+
"replaceOne",
|
|
7116
|
+
"deleteOne",
|
|
7117
|
+
"deleteMany",
|
|
7118
|
+
"bulkWrite",
|
|
7119
|
+
"bulkSave",
|
|
7120
|
+
"save",
|
|
7121
|
+
// pre-v7, removed in current mongoose but present in older codebases:
|
|
7122
|
+
"count",
|
|
7123
|
+
"update",
|
|
7124
|
+
"remove",
|
|
7125
|
+
"findOneAndRemove",
|
|
7126
|
+
"findByIdAndRemove"
|
|
7127
|
+
];
|
|
7128
|
+
var MODEL_METHODS_ALT = MODEL_METHODS.join("|");
|
|
7129
|
+
function schemaCollectionVars(content) {
|
|
7130
|
+
const out = /* @__PURE__ */ new Map();
|
|
7131
|
+
const re = /(?:const|let|var)\s+(\w+)\s*=\s*new\s+(?:mongoose\s*\.\s*)?Schema\s*\(/g;
|
|
7132
|
+
let m;
|
|
7133
|
+
while ((m = re.exec(content)) !== null) {
|
|
7134
|
+
const windowText = content.slice(m.index, m.index + 2e3);
|
|
7135
|
+
const opt = /\bcollection\s*:\s*['"`]([\w.-]+)['"`]/.exec(windowText);
|
|
7136
|
+
if (opt) out.set(m[1], opt[1]);
|
|
7137
|
+
}
|
|
7138
|
+
return out;
|
|
7139
|
+
}
|
|
7140
|
+
function resolveModel(modelName, rest, schemaColl, pluralizeOn) {
|
|
7141
|
+
const trimmed = rest.trim();
|
|
7142
|
+
const literalThird = /,\s*['"`]([\w.-]+)['"`]\s*$/.exec(trimmed);
|
|
7143
|
+
if (literalThird) return { name: literalThird[1], kind: "mongodb-collection" };
|
|
7144
|
+
const firstIdent = /^([A-Za-z_$][\w$]*)/.exec(trimmed)?.[1];
|
|
7145
|
+
if (firstIdent && schemaColl.has(firstIdent)) {
|
|
7146
|
+
return { name: schemaColl.get(firstIdent), kind: "mongodb-collection" };
|
|
7147
|
+
}
|
|
7148
|
+
if (/,\s*[A-Za-z_$][\w$]*\s*$/.test(trimmed)) {
|
|
7149
|
+
return { name: modelName, kind: "mongodb-model" };
|
|
7150
|
+
}
|
|
7151
|
+
return { name: pluralizeOn ? pluralizeCollection(modelName) : modelName, kind: "mongodb-collection" };
|
|
7152
|
+
}
|
|
7153
|
+
function collectModelDefs(content, pluralizeOn) {
|
|
7154
|
+
const schemaColl = schemaCollectionVars(content);
|
|
7155
|
+
const out = [];
|
|
7156
|
+
const re = /(?:(?:const|let|var)\s+(\w+)\s*=\s*)?(?:await\s+)?(?:\b\w+\s*\.\s*)?\bmodel\s*\(\s*['"`]([\w$]+)['"`]\s*(?:,\s*([\s\S]{0,300}?))?\)/g;
|
|
7157
|
+
let m;
|
|
7158
|
+
while ((m = re.exec(content)) !== null) {
|
|
7159
|
+
out.push({
|
|
7160
|
+
modelName: m[2],
|
|
7161
|
+
varName: m[1] ?? null,
|
|
7162
|
+
resolved: resolveModel(m[2], m[3] ?? "", schemaColl, pluralizeOn),
|
|
7163
|
+
matchText: m[0]
|
|
7164
|
+
});
|
|
7165
|
+
}
|
|
7166
|
+
return out;
|
|
7167
|
+
}
|
|
7168
|
+
function endpoint(r, file, serviceDir, matchText) {
|
|
7169
|
+
const line = lineOf(file.content, matchText);
|
|
7170
|
+
return {
|
|
7171
|
+
infraId: (0, import_types21.infraId)(r.kind, r.name),
|
|
7172
|
+
name: r.name,
|
|
7173
|
+
kind: r.kind,
|
|
7174
|
+
edgeType: "CALLS",
|
|
7175
|
+
confidenceKind: "verified-call-site",
|
|
7176
|
+
evidence: { file: import_node_path33.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
7177
|
+
};
|
|
7178
|
+
}
|
|
7179
|
+
function mongooseEndpointsFromFile(file, serviceDir) {
|
|
7180
|
+
const hasMongoose = MONGOOSE_IMPORT_RE.test(file.content);
|
|
7181
|
+
const hasMongodb = MONGODB_IMPORT_RE.test(file.content);
|
|
7182
|
+
if (!hasMongoose && !hasMongodb) return [];
|
|
7183
|
+
const content = file.content;
|
|
7184
|
+
const out = [];
|
|
7185
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7186
|
+
const push = (r, matchText) => {
|
|
7187
|
+
const key = `${r.kind}/${r.name}`;
|
|
7188
|
+
if (seen.has(key)) return;
|
|
7189
|
+
seen.add(key);
|
|
7190
|
+
out.push(endpoint(r, file, serviceDir, matchText));
|
|
7191
|
+
};
|
|
7192
|
+
if (hasMongoose) {
|
|
7193
|
+
const pluralizeOn = !PLURALIZE_DISABLED_RE.test(content);
|
|
7194
|
+
for (const def of collectModelDefs(content, pluralizeOn)) push(def.resolved, def.matchText);
|
|
7195
|
+
}
|
|
7196
|
+
const collRe = /\.\s*collection\s*\(\s*['"`]([\w.$-]+)['"`]\s*\)/g;
|
|
7197
|
+
let c;
|
|
7198
|
+
while ((c = collRe.exec(content)) !== null) {
|
|
7199
|
+
push({ name: c[1], kind: "mongodb-collection" }, c[0]);
|
|
7200
|
+
}
|
|
7201
|
+
return out;
|
|
7202
|
+
}
|
|
7203
|
+
function parseDestructure(inner, specifier, out) {
|
|
7204
|
+
for (const raw of inner.split(",")) {
|
|
7205
|
+
const part = raw.trim();
|
|
7206
|
+
if (!part) continue;
|
|
7207
|
+
const asM = /^(\w+)\s+as\s+(\w+)$/.exec(part);
|
|
7208
|
+
const colonM = /^(\w+)\s*:\s*(\w+)$/.exec(part);
|
|
7209
|
+
if (asM) out.push({ local: asM[2], kind: "named", exportName: asM[1], specifier });
|
|
7210
|
+
else if (colonM) out.push({ local: colonM[2], kind: "named", exportName: colonM[1], specifier });
|
|
7211
|
+
else {
|
|
7212
|
+
const id = /^(\w+)$/.exec(part);
|
|
7213
|
+
if (id) out.push({ local: id[1], kind: "named", exportName: id[1], specifier });
|
|
7214
|
+
}
|
|
7215
|
+
}
|
|
7216
|
+
}
|
|
7217
|
+
function parseImportBindings(content) {
|
|
7218
|
+
const out = [];
|
|
7219
|
+
const esm = /import\s+([^;'"`\n]+?)\s+from\s*['"`]([^'"`]+)['"`]/g;
|
|
7220
|
+
let m;
|
|
7221
|
+
while ((m = esm.exec(content)) !== null) {
|
|
7222
|
+
const clause = m[1].trim();
|
|
7223
|
+
const spec = m[2];
|
|
7224
|
+
const ns = /^\*\s+as\s+(\w+)$/.exec(clause);
|
|
7225
|
+
if (ns) {
|
|
7226
|
+
out.push({ local: ns[1], kind: "namespace", specifier: spec });
|
|
7227
|
+
continue;
|
|
7228
|
+
}
|
|
7229
|
+
const named = /\{([^}]*)\}/.exec(clause);
|
|
7230
|
+
if (named) parseDestructure(named[1], spec, out);
|
|
7231
|
+
const def = /^(\w+)\s*(?:,|$)/.exec(clause);
|
|
7232
|
+
if (def && !clause.startsWith("{")) out.push({ local: def[1], kind: "default", specifier: spec });
|
|
7233
|
+
}
|
|
7234
|
+
const cjs = /(?:const|let|var)\s+(\{[^}]*\}|\w+)\s*=\s*require\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
7235
|
+
while ((m = cjs.exec(content)) !== null) {
|
|
7236
|
+
const lhs = m[1];
|
|
7237
|
+
const spec = m[2];
|
|
7238
|
+
if (lhs.startsWith("{")) parseDestructure(lhs.slice(1, -1), spec, out);
|
|
7239
|
+
else out.push({ local: lhs, kind: "whole", specifier: spec });
|
|
7240
|
+
}
|
|
7241
|
+
return out;
|
|
7242
|
+
}
|
|
7243
|
+
function fileExportsOf(content, pluralizeOn) {
|
|
7244
|
+
const defs = collectModelDefs(content, pluralizeOn).filter((d) => d.resolved.kind === "mongodb-collection");
|
|
7245
|
+
if (defs.length === 0) return null;
|
|
7246
|
+
const byVar = /* @__PURE__ */ new Map();
|
|
7247
|
+
for (const d of defs) if (d.varName) byVar.set(d.varName, d.resolved.name);
|
|
7248
|
+
const byName = new Map(byVar);
|
|
7249
|
+
let def;
|
|
7250
|
+
const named = /(?:module\.exports|export\s+default)\s*=\s*(\w+)\b/.exec(content);
|
|
7251
|
+
if (named && byVar.has(named[1])) def = byVar.get(named[1]);
|
|
7252
|
+
if (!def) {
|
|
7253
|
+
const inline = /(?:module\.exports|export\s+default)\s*=\s*(?:await\s+)?(?:\w+\s*\.\s*)?model\s*\(\s*['"`]([\w$]+)['"`]/.exec(content);
|
|
7254
|
+
if (inline) def = pluralizeOn ? pluralizeCollection(inline[1]) : inline[1];
|
|
7255
|
+
}
|
|
7256
|
+
if (!def && byVar.size === 1) def = [...byVar.values()][0];
|
|
7257
|
+
return { byName, ...def ? { default: def } : {} };
|
|
7258
|
+
}
|
|
7259
|
+
async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
7260
|
+
const mongooseFiles = files.filter((f) => MONGOOSE_IMPORT_RE.test(f.content));
|
|
7261
|
+
if (mongooseFiles.length === 0) return [];
|
|
7262
|
+
const pluralizeOn = !files.some((f) => PLURALIZE_DISABLED_RE.test(f.content));
|
|
7263
|
+
const registry = /* @__PURE__ */ new Map();
|
|
7264
|
+
for (const f of mongooseFiles) {
|
|
7265
|
+
const fx = fileExportsOf(f.content, pluralizeOn);
|
|
7266
|
+
if (fx) registry.set(toPosix2(import_node_path33.default.relative(serviceDir, f.path)), fx);
|
|
7267
|
+
}
|
|
7268
|
+
if (registry.size === 0) return [];
|
|
7269
|
+
const out = [];
|
|
7270
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7271
|
+
for (const f of files) {
|
|
7272
|
+
const bindings = parseImportBindings(f.content);
|
|
7273
|
+
if (bindings.length === 0) continue;
|
|
7274
|
+
const directColl = /* @__PURE__ */ new Map();
|
|
7275
|
+
const nsExports = /* @__PURE__ */ new Map();
|
|
7276
|
+
for (const b of bindings) {
|
|
7277
|
+
const resolvedRel = await resolveJsImport(b.specifier, import_node_path33.default.dirname(f.path), serviceDir, null);
|
|
7278
|
+
if (!resolvedRel) continue;
|
|
7279
|
+
const fx = registry.get(resolvedRel);
|
|
7280
|
+
if (!fx) continue;
|
|
7281
|
+
if (b.kind === "named" && b.exportName) {
|
|
7282
|
+
const coll = fx.byName.get(b.exportName);
|
|
7283
|
+
if (coll) directColl.set(b.local, coll);
|
|
7284
|
+
} else if (b.kind === "default") {
|
|
7285
|
+
if (fx.default) directColl.set(b.local, fx.default);
|
|
7286
|
+
} else {
|
|
7287
|
+
if (fx.default) directColl.set(b.local, fx.default);
|
|
7288
|
+
nsExports.set(b.local, fx);
|
|
7289
|
+
}
|
|
7290
|
+
}
|
|
7291
|
+
if (directColl.size === 0 && nsExports.size === 0) continue;
|
|
7292
|
+
const localDefs = new Set(
|
|
7293
|
+
collectModelDefs(f.content, pluralizeOn).map((d) => d.varName).filter((v) => v !== null)
|
|
7294
|
+
);
|
|
7295
|
+
const emit = (collection, matchText) => {
|
|
7296
|
+
const key = `${f.path}::${collection}`;
|
|
7297
|
+
if (seen.has(key)) return;
|
|
7298
|
+
seen.add(key);
|
|
7299
|
+
out.push(endpoint({ name: collection, kind: "mongodb-collection" }, f, serviceDir, matchText));
|
|
7300
|
+
};
|
|
7301
|
+
for (const [local, collection] of directColl) {
|
|
7302
|
+
if (localDefs.has(local)) continue;
|
|
7303
|
+
const qre = new RegExp(`\\b${local}\\s*\\.\\s*(?:${MODEL_METHODS_ALT})\\s*\\(`, "g");
|
|
7304
|
+
let qm;
|
|
7305
|
+
while ((qm = qre.exec(f.content)) !== null) emit(collection, qm[0]);
|
|
7306
|
+
}
|
|
7307
|
+
for (const [local, fx] of nsExports) {
|
|
7308
|
+
const qre = new RegExp(`\\b${local}\\s*\\.\\s*(\\w+)\\s*\\.\\s*(?:${MODEL_METHODS_ALT})\\s*\\(`, "g");
|
|
7309
|
+
let qm;
|
|
7310
|
+
while ((qm = qre.exec(f.content)) !== null) {
|
|
7311
|
+
const coll = fx.byName.get(qm[1]);
|
|
7312
|
+
if (coll) emit(coll, qm[0]);
|
|
7313
|
+
}
|
|
7314
|
+
}
|
|
7315
|
+
}
|
|
7316
|
+
return out;
|
|
7317
|
+
}
|
|
7318
|
+
|
|
6962
7319
|
// src/extract/calls/index.ts
|
|
6963
7320
|
function edgeTypeFromEndpoint(ep) {
|
|
6964
7321
|
switch (ep.edgeType) {
|
|
6965
7322
|
case "PUBLISHES_TO":
|
|
6966
|
-
return
|
|
7323
|
+
return import_types22.EdgeType.PUBLISHES_TO;
|
|
6967
7324
|
case "CONSUMES_FROM":
|
|
6968
|
-
return
|
|
7325
|
+
return import_types22.EdgeType.CONSUMES_FROM;
|
|
6969
7326
|
default:
|
|
6970
|
-
return
|
|
7327
|
+
return import_types22.EdgeType.CALLS;
|
|
6971
7328
|
}
|
|
6972
7329
|
}
|
|
6973
7330
|
function isAwsKind(kind) {
|
|
@@ -6979,23 +7336,27 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
6979
7336
|
for (const service of services) {
|
|
6980
7337
|
const files = await loadSourceFiles(service.dir);
|
|
6981
7338
|
const endpoints = [];
|
|
7339
|
+
const maskedFiles = [];
|
|
6982
7340
|
for (const file of files) {
|
|
6983
7341
|
if (isTestPath(file.path)) continue;
|
|
6984
7342
|
const masked = maskCommentsInSource(file.content);
|
|
6985
7343
|
const maskedFile = { path: file.path, content: masked };
|
|
7344
|
+
maskedFiles.push(maskedFile);
|
|
6986
7345
|
endpoints.push(...kafkaEndpointsFromFile(maskedFile, service.dir));
|
|
6987
7346
|
endpoints.push(...redisEndpointsFromFile(maskedFile, service.dir));
|
|
6988
7347
|
endpoints.push(...awsEndpointsFromFile(maskedFile, service.dir));
|
|
6989
7348
|
endpoints.push(...grpcEndpointsFromFile(maskedFile, service.dir));
|
|
6990
7349
|
endpoints.push(...supabaseEndpointsFromFile(maskedFile, service.dir));
|
|
7350
|
+
endpoints.push(...mongooseEndpointsFromFile(maskedFile, service.dir));
|
|
6991
7351
|
}
|
|
7352
|
+
endpoints.push(...await mongooseCrossFileEndpoints(maskedFiles, service.dir));
|
|
6992
7353
|
if (endpoints.length === 0) continue;
|
|
6993
7354
|
const seenEdges = /* @__PURE__ */ new Set();
|
|
6994
7355
|
for (const ep of endpoints) {
|
|
6995
7356
|
if (!graph.hasNode(ep.infraId)) {
|
|
6996
7357
|
const node = {
|
|
6997
7358
|
id: ep.infraId,
|
|
6998
|
-
type:
|
|
7359
|
+
type: import_types22.NodeType.InfraNode,
|
|
6999
7360
|
name: ep.name,
|
|
7000
7361
|
// #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
|
|
7001
7362
|
// aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
|
|
@@ -7007,7 +7368,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
7007
7368
|
nodesAdded++;
|
|
7008
7369
|
}
|
|
7009
7370
|
const edgeType = edgeTypeFromEndpoint(ep);
|
|
7010
|
-
const confidence = (0,
|
|
7371
|
+
const confidence = (0, import_types22.confidenceForExtracted)(ep.confidenceKind);
|
|
7011
7372
|
const relFile = toPosix2(ep.evidence.file);
|
|
7012
7373
|
const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
7013
7374
|
graph,
|
|
@@ -7017,7 +7378,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
7017
7378
|
);
|
|
7018
7379
|
nodesAdded += n;
|
|
7019
7380
|
edgesAdded += e;
|
|
7020
|
-
if (!(0,
|
|
7381
|
+
if (!(0, import_types22.passesExtractedFloor)(confidence)) {
|
|
7021
7382
|
noteExtractedDropped({
|
|
7022
7383
|
source: fileNodeId,
|
|
7023
7384
|
target: ep.infraId,
|
|
@@ -7037,7 +7398,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
7037
7398
|
source: fileNodeId,
|
|
7038
7399
|
target: ep.infraId,
|
|
7039
7400
|
type: edgeType,
|
|
7040
|
-
provenance:
|
|
7401
|
+
provenance: import_types22.Provenance.EXTRACTED,
|
|
7041
7402
|
confidence,
|
|
7042
7403
|
evidence: ep.evidence
|
|
7043
7404
|
};
|
|
@@ -7063,16 +7424,16 @@ init_cjs_shims();
|
|
|
7063
7424
|
|
|
7064
7425
|
// src/extract/infra/docker-compose.ts
|
|
7065
7426
|
init_cjs_shims();
|
|
7066
|
-
var
|
|
7067
|
-
var
|
|
7427
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
7428
|
+
var import_types24 = require("@neat.is/types");
|
|
7068
7429
|
|
|
7069
7430
|
// src/extract/infra/shared.ts
|
|
7070
7431
|
init_cjs_shims();
|
|
7071
|
-
var
|
|
7432
|
+
var import_types23 = require("@neat.is/types");
|
|
7072
7433
|
function makeInfraNode(kind, name, provider = "self", extras) {
|
|
7073
7434
|
return {
|
|
7074
|
-
id: (0,
|
|
7075
|
-
type:
|
|
7435
|
+
id: (0, import_types23.infraId)(kind, name),
|
|
7436
|
+
type: import_types23.NodeType.InfraNode,
|
|
7076
7437
|
name,
|
|
7077
7438
|
provider,
|
|
7078
7439
|
kind,
|
|
@@ -7116,8 +7477,8 @@ function emitPlatformResourceEdge(graph, anchorId, edgeType, kind, name, provide
|
|
|
7116
7477
|
source: anchorId,
|
|
7117
7478
|
target: node.id,
|
|
7118
7479
|
type: edgeType,
|
|
7119
|
-
provenance:
|
|
7120
|
-
confidence: (0,
|
|
7480
|
+
provenance: import_types23.Provenance.EXTRACTED,
|
|
7481
|
+
confidence: (0, import_types23.confidenceForExtracted)("structural"),
|
|
7121
7482
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
7122
7483
|
};
|
|
7123
7484
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -7134,7 +7495,7 @@ function dependsOnList(value) {
|
|
|
7134
7495
|
}
|
|
7135
7496
|
function serviceNameToServiceNode(name, services) {
|
|
7136
7497
|
for (const s of services) {
|
|
7137
|
-
if (s.node.name === name ||
|
|
7498
|
+
if (s.node.name === name || import_node_path34.default.basename(s.dir) === name) return s.node.id;
|
|
7138
7499
|
}
|
|
7139
7500
|
return null;
|
|
7140
7501
|
}
|
|
@@ -7143,7 +7504,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
7143
7504
|
let edgesAdded = 0;
|
|
7144
7505
|
let composePath = null;
|
|
7145
7506
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
7146
|
-
const abs =
|
|
7507
|
+
const abs = import_node_path34.default.join(scanPath, name);
|
|
7147
7508
|
if (await exists2(abs)) {
|
|
7148
7509
|
composePath = abs;
|
|
7149
7510
|
break;
|
|
@@ -7156,13 +7517,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
7156
7517
|
} catch (err) {
|
|
7157
7518
|
recordExtractionError(
|
|
7158
7519
|
"infra docker-compose",
|
|
7159
|
-
|
|
7520
|
+
import_node_path34.default.relative(scanPath, composePath),
|
|
7160
7521
|
err
|
|
7161
7522
|
);
|
|
7162
7523
|
return { nodesAdded, edgesAdded };
|
|
7163
7524
|
}
|
|
7164
7525
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
7165
|
-
const evidenceFile =
|
|
7526
|
+
const evidenceFile = import_node_path34.default.relative(scanPath, composePath).split(import_node_path34.default.sep).join("/");
|
|
7166
7527
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
7167
7528
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
7168
7529
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -7184,15 +7545,15 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
7184
7545
|
for (const dep of dependsOnList(svc.depends_on)) {
|
|
7185
7546
|
const targetId = composeNameToNodeId.get(dep);
|
|
7186
7547
|
if (!targetId) continue;
|
|
7187
|
-
const edgeId = (0, import_types5.extractedEdgeId)(sourceId, targetId,
|
|
7548
|
+
const edgeId = (0, import_types5.extractedEdgeId)(sourceId, targetId, import_types24.EdgeType.DEPENDS_ON);
|
|
7188
7549
|
if (graph.hasEdge(edgeId)) continue;
|
|
7189
7550
|
const edge = {
|
|
7190
7551
|
id: edgeId,
|
|
7191
7552
|
source: sourceId,
|
|
7192
7553
|
target: targetId,
|
|
7193
|
-
type:
|
|
7194
|
-
provenance:
|
|
7195
|
-
confidence: (0,
|
|
7554
|
+
type: import_types24.EdgeType.DEPENDS_ON,
|
|
7555
|
+
provenance: import_types24.Provenance.EXTRACTED,
|
|
7556
|
+
confidence: (0, import_types24.confidenceForExtracted)("structural"),
|
|
7196
7557
|
evidence: { file: evidenceFile }
|
|
7197
7558
|
};
|
|
7198
7559
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -7204,9 +7565,9 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
7204
7565
|
|
|
7205
7566
|
// src/extract/infra/dockerfile.ts
|
|
7206
7567
|
init_cjs_shims();
|
|
7207
|
-
var
|
|
7568
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
7208
7569
|
var import_node_fs18 = require("fs");
|
|
7209
|
-
var
|
|
7570
|
+
var import_types25 = require("@neat.is/types");
|
|
7210
7571
|
function readDockerfile(content) {
|
|
7211
7572
|
let image = null;
|
|
7212
7573
|
const ports = [];
|
|
@@ -7235,7 +7596,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
7235
7596
|
let nodesAdded = 0;
|
|
7236
7597
|
let edgesAdded = 0;
|
|
7237
7598
|
for (const service of services) {
|
|
7238
|
-
const dockerfilePath =
|
|
7599
|
+
const dockerfilePath = import_node_path35.default.join(service.dir, "Dockerfile");
|
|
7239
7600
|
if (!await exists2(dockerfilePath)) continue;
|
|
7240
7601
|
let content;
|
|
7241
7602
|
try {
|
|
@@ -7243,7 +7604,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
7243
7604
|
} catch (err) {
|
|
7244
7605
|
recordExtractionError(
|
|
7245
7606
|
"infra dockerfile",
|
|
7246
|
-
|
|
7607
|
+
import_node_path35.default.relative(scanPath, dockerfilePath),
|
|
7247
7608
|
err
|
|
7248
7609
|
);
|
|
7249
7610
|
continue;
|
|
@@ -7255,8 +7616,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
7255
7616
|
graph.addNode(node.id, node);
|
|
7256
7617
|
nodesAdded++;
|
|
7257
7618
|
}
|
|
7258
|
-
const relDockerfile = toPosix2(
|
|
7259
|
-
const evidenceFile = toPosix2(
|
|
7619
|
+
const relDockerfile = toPosix2(import_node_path35.default.relative(service.dir, dockerfilePath));
|
|
7620
|
+
const evidenceFile = toPosix2(import_node_path35.default.relative(scanPath, dockerfilePath));
|
|
7260
7621
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
7261
7622
|
graph,
|
|
7262
7623
|
service.pkg.name,
|
|
@@ -7265,15 +7626,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
7265
7626
|
);
|
|
7266
7627
|
nodesAdded += fn;
|
|
7267
7628
|
edgesAdded += fe;
|
|
7268
|
-
const edgeId = (0, import_types5.extractedEdgeId)(fileNodeId, node.id,
|
|
7629
|
+
const edgeId = (0, import_types5.extractedEdgeId)(fileNodeId, node.id, import_types25.EdgeType.RUNS_ON);
|
|
7269
7630
|
if (!graph.hasEdge(edgeId)) {
|
|
7270
7631
|
const edge = {
|
|
7271
7632
|
id: edgeId,
|
|
7272
7633
|
source: fileNodeId,
|
|
7273
7634
|
target: node.id,
|
|
7274
|
-
type:
|
|
7275
|
-
provenance:
|
|
7276
|
-
confidence: (0,
|
|
7635
|
+
type: import_types25.EdgeType.RUNS_ON,
|
|
7636
|
+
provenance: import_types25.Provenance.EXTRACTED,
|
|
7637
|
+
confidence: (0, import_types25.confidenceForExtracted)("structural"),
|
|
7277
7638
|
evidence: {
|
|
7278
7639
|
file: evidenceFile,
|
|
7279
7640
|
...facts.entrypoint ? { snippet: facts.entrypoint.slice(0, 120) } : {}
|
|
@@ -7288,15 +7649,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
7288
7649
|
graph.addNode(portNode.id, portNode);
|
|
7289
7650
|
nodesAdded++;
|
|
7290
7651
|
}
|
|
7291
|
-
const portEdgeId = (0, import_types5.extractedEdgeId)(fileNodeId, portNode.id,
|
|
7652
|
+
const portEdgeId = (0, import_types5.extractedEdgeId)(fileNodeId, portNode.id, import_types25.EdgeType.CONNECTS_TO);
|
|
7292
7653
|
if (graph.hasEdge(portEdgeId)) continue;
|
|
7293
7654
|
const portEdge = {
|
|
7294
7655
|
id: portEdgeId,
|
|
7295
7656
|
source: fileNodeId,
|
|
7296
7657
|
target: portNode.id,
|
|
7297
|
-
type:
|
|
7298
|
-
provenance:
|
|
7299
|
-
confidence: (0,
|
|
7658
|
+
type: import_types25.EdgeType.CONNECTS_TO,
|
|
7659
|
+
provenance: import_types25.Provenance.EXTRACTED,
|
|
7660
|
+
confidence: (0, import_types25.confidenceForExtracted)("structural"),
|
|
7300
7661
|
evidence: { file: evidenceFile, snippet: `EXPOSE ${port}` }
|
|
7301
7662
|
};
|
|
7302
7663
|
graph.addEdgeWithKey(portEdgeId, portEdge.source, portEdge.target, portEdge);
|
|
@@ -7309,8 +7670,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
7309
7670
|
// src/extract/infra/terraform.ts
|
|
7310
7671
|
init_cjs_shims();
|
|
7311
7672
|
var import_node_fs19 = require("fs");
|
|
7312
|
-
var
|
|
7313
|
-
var
|
|
7673
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
7674
|
+
var import_types26 = require("@neat.is/types");
|
|
7314
7675
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
7315
7676
|
var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
|
|
7316
7677
|
async function walkTfFiles(start, depth = 0, max = 5) {
|
|
@@ -7320,11 +7681,11 @@ async function walkTfFiles(start, depth = 0, max = 5) {
|
|
|
7320
7681
|
for (const entry of entries) {
|
|
7321
7682
|
if (entry.isDirectory()) {
|
|
7322
7683
|
if (IGNORED_DIRS.has(entry.name) || entry.name === ".terraform") continue;
|
|
7323
|
-
const child =
|
|
7684
|
+
const child = import_node_path36.default.join(start, entry.name);
|
|
7324
7685
|
if (await isPythonVenvDir(child)) continue;
|
|
7325
7686
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
7326
7687
|
} else if (entry.isFile() && entry.name.endsWith(".tf")) {
|
|
7327
|
-
out.push(
|
|
7688
|
+
out.push(import_node_path36.default.join(start, entry.name));
|
|
7328
7689
|
}
|
|
7329
7690
|
}
|
|
7330
7691
|
return out;
|
|
@@ -7356,7 +7717,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
7356
7717
|
const files = await walkTfFiles(scanPath);
|
|
7357
7718
|
for (const file of files) {
|
|
7358
7719
|
const content = await import_node_fs19.promises.readFile(file, "utf8");
|
|
7359
|
-
const evidenceFile = toPosix2(
|
|
7720
|
+
const evidenceFile = toPosix2(import_node_path36.default.relative(scanPath, file));
|
|
7360
7721
|
const resources = [];
|
|
7361
7722
|
const byKey = /* @__PURE__ */ new Map();
|
|
7362
7723
|
RESOURCE_RE.lastIndex = 0;
|
|
@@ -7391,16 +7752,16 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
7391
7752
|
if (!target) continue;
|
|
7392
7753
|
if (seen.has(target.nodeId)) continue;
|
|
7393
7754
|
seen.add(target.nodeId);
|
|
7394
|
-
const edgeId = (0, import_types5.extractedEdgeId)(resource.nodeId, target.nodeId,
|
|
7755
|
+
const edgeId = (0, import_types5.extractedEdgeId)(resource.nodeId, target.nodeId, import_types26.EdgeType.DEPENDS_ON);
|
|
7395
7756
|
if (graph.hasEdge(edgeId)) continue;
|
|
7396
7757
|
const line = lineAt2(content, resource.bodyOffset + ref.index);
|
|
7397
7758
|
const edge = {
|
|
7398
7759
|
id: edgeId,
|
|
7399
7760
|
source: resource.nodeId,
|
|
7400
7761
|
target: target.nodeId,
|
|
7401
|
-
type:
|
|
7402
|
-
provenance:
|
|
7403
|
-
confidence: (0,
|
|
7762
|
+
type: import_types26.EdgeType.DEPENDS_ON,
|
|
7763
|
+
provenance: import_types26.Provenance.EXTRACTED,
|
|
7764
|
+
confidence: (0, import_types26.confidenceForExtracted)("structural"),
|
|
7404
7765
|
evidence: { file: evidenceFile, line, snippet: key }
|
|
7405
7766
|
};
|
|
7406
7767
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -7414,7 +7775,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
7414
7775
|
// src/extract/infra/k8s.ts
|
|
7415
7776
|
init_cjs_shims();
|
|
7416
7777
|
var import_node_fs20 = require("fs");
|
|
7417
|
-
var
|
|
7778
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
7418
7779
|
var import_yaml3 = require("yaml");
|
|
7419
7780
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
7420
7781
|
Service: "k8s-service",
|
|
@@ -7432,11 +7793,11 @@ async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
|
7432
7793
|
for (const entry of entries) {
|
|
7433
7794
|
if (entry.isDirectory()) {
|
|
7434
7795
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
7435
|
-
const child =
|
|
7796
|
+
const child = import_node_path37.default.join(start, entry.name);
|
|
7436
7797
|
if (await isPythonVenvDir(child)) continue;
|
|
7437
7798
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
7438
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
7439
|
-
out.push(
|
|
7799
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path37.default.extname(entry.name))) {
|
|
7800
|
+
out.push(import_node_path37.default.join(start, entry.name));
|
|
7440
7801
|
}
|
|
7441
7802
|
}
|
|
7442
7803
|
return out;
|
|
@@ -7470,13 +7831,13 @@ async function addK8sResources(graph, scanPath) {
|
|
|
7470
7831
|
// src/extract/infra/cloudflare.ts
|
|
7471
7832
|
init_cjs_shims();
|
|
7472
7833
|
var import_node_fs21 = require("fs");
|
|
7473
|
-
var
|
|
7834
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
7474
7835
|
var import_smol_toml2 = require("smol-toml");
|
|
7475
|
-
var
|
|
7836
|
+
var import_types27 = require("@neat.is/types");
|
|
7476
7837
|
var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
|
|
7477
7838
|
async function readWranglerConfig(dir) {
|
|
7478
7839
|
for (const filename of WRANGLER_FILENAMES) {
|
|
7479
|
-
const abs =
|
|
7840
|
+
const abs = import_node_path38.default.join(dir, filename);
|
|
7480
7841
|
if (!await exists2(abs)) continue;
|
|
7481
7842
|
const raw = await import_node_fs21.promises.readFile(abs, "utf8");
|
|
7482
7843
|
const config = filename === "wrangler.toml" ? (0, import_smol_toml2.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
@@ -7520,8 +7881,8 @@ function addResourceEdge(graph, anchorId, edgeType, kind, name, evidenceFile, li
|
|
|
7520
7881
|
source: anchorId,
|
|
7521
7882
|
target: node.id,
|
|
7522
7883
|
type: edgeType,
|
|
7523
|
-
provenance:
|
|
7524
|
-
confidence: (0,
|
|
7884
|
+
provenance: import_types27.Provenance.EXTRACTED,
|
|
7885
|
+
confidence: (0, import_types27.confidenceForExtracted)("structural"),
|
|
7525
7886
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
7526
7887
|
};
|
|
7527
7888
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -7539,11 +7900,11 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7539
7900
|
try {
|
|
7540
7901
|
read = await readWranglerConfig(service.dir);
|
|
7541
7902
|
} catch (err) {
|
|
7542
|
-
recordExtractionError("infra cloudflare",
|
|
7903
|
+
recordExtractionError("infra cloudflare", import_node_path38.default.relative(scanPath, service.dir), err);
|
|
7543
7904
|
continue;
|
|
7544
7905
|
}
|
|
7545
7906
|
if (!read || !read.config.name) continue;
|
|
7546
|
-
const evidenceFile = toPosix2(
|
|
7907
|
+
const evidenceFile = toPosix2(import_node_path38.default.relative(scanPath, import_node_path38.default.join(service.dir, read.relFile)));
|
|
7547
7908
|
discovered.push({ service, config: read.config, relFile: read.relFile, raw: read.raw, evidenceFile });
|
|
7548
7909
|
}
|
|
7549
7910
|
for (const worker of discovered) {
|
|
@@ -7555,7 +7916,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7555
7916
|
}
|
|
7556
7917
|
let anchorId = service.node.id;
|
|
7557
7918
|
if (config.main) {
|
|
7558
|
-
const entryRelPath = toPosix2(
|
|
7919
|
+
const entryRelPath = toPosix2(import_node_path38.default.normalize(config.main));
|
|
7559
7920
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
7560
7921
|
graph,
|
|
7561
7922
|
service.pkg.name,
|
|
@@ -7582,15 +7943,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7582
7943
|
nodesAdded++;
|
|
7583
7944
|
}
|
|
7584
7945
|
if (runtimeNode.id !== anchorId) {
|
|
7585
|
-
const runsOnId = (0, import_types5.extractedEdgeId)(anchorId, runtimeNode.id,
|
|
7946
|
+
const runsOnId = (0, import_types5.extractedEdgeId)(anchorId, runtimeNode.id, import_types27.EdgeType.RUNS_ON);
|
|
7586
7947
|
if (!graph.hasEdge(runsOnId)) {
|
|
7587
7948
|
const edge = {
|
|
7588
7949
|
id: runsOnId,
|
|
7589
7950
|
source: anchorId,
|
|
7590
7951
|
target: runtimeNode.id,
|
|
7591
|
-
type:
|
|
7592
|
-
provenance:
|
|
7593
|
-
confidence: (0,
|
|
7952
|
+
type: import_types27.EdgeType.RUNS_ON,
|
|
7953
|
+
provenance: import_types27.Provenance.EXTRACTED,
|
|
7954
|
+
confidence: (0, import_types27.confidenceForExtracted)("structural"),
|
|
7594
7955
|
evidence: {
|
|
7595
7956
|
file: evidenceFile,
|
|
7596
7957
|
...config.compatibility_date ? { snippet: `compatibility_date = ${config.compatibility_date}`.slice(0, 120) } : {}
|
|
@@ -7604,7 +7965,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7604
7965
|
const result = addResourceEdge(
|
|
7605
7966
|
graph,
|
|
7606
7967
|
anchorId,
|
|
7607
|
-
|
|
7968
|
+
import_types27.EdgeType.CONNECTS_TO,
|
|
7608
7969
|
"cloudflare-route",
|
|
7609
7970
|
route,
|
|
7610
7971
|
evidenceFile,
|
|
@@ -7628,7 +7989,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7628
7989
|
const result = addResourceEdge(
|
|
7629
7990
|
graph,
|
|
7630
7991
|
anchorId,
|
|
7631
|
-
|
|
7992
|
+
import_types27.EdgeType.DEPENDS_ON,
|
|
7632
7993
|
group.kind,
|
|
7633
7994
|
name,
|
|
7634
7995
|
evidenceFile,
|
|
@@ -7642,7 +8003,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7642
8003
|
const result = addResourceEdge(
|
|
7643
8004
|
graph,
|
|
7644
8005
|
anchorId,
|
|
7645
|
-
|
|
8006
|
+
import_types27.EdgeType.DEPENDS_ON,
|
|
7646
8007
|
"cloudflare-cron",
|
|
7647
8008
|
cron,
|
|
7648
8009
|
evidenceFile,
|
|
@@ -7655,7 +8016,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7655
8016
|
const result = addResourceEdge(
|
|
7656
8017
|
graph,
|
|
7657
8018
|
anchorId,
|
|
7658
|
-
|
|
8019
|
+
import_types27.EdgeType.DEPENDS_ON,
|
|
7659
8020
|
"cloudflare-env-var",
|
|
7660
8021
|
varName,
|
|
7661
8022
|
evidenceFile,
|
|
@@ -7668,15 +8029,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7668
8029
|
if (!svc.service) continue;
|
|
7669
8030
|
const target = workerIndex.get(svc.service);
|
|
7670
8031
|
if (target && target.anchorId !== anchorId) {
|
|
7671
|
-
const edgeId = (0, import_types5.extractedEdgeId)(anchorId, target.anchorId,
|
|
8032
|
+
const edgeId = (0, import_types5.extractedEdgeId)(anchorId, target.anchorId, import_types27.EdgeType.CALLS);
|
|
7672
8033
|
if (!graph.hasEdge(edgeId)) {
|
|
7673
8034
|
const edge = {
|
|
7674
8035
|
id: edgeId,
|
|
7675
8036
|
source: anchorId,
|
|
7676
8037
|
target: target.anchorId,
|
|
7677
|
-
type:
|
|
7678
|
-
provenance:
|
|
7679
|
-
confidence: (0,
|
|
8038
|
+
type: import_types27.EdgeType.CALLS,
|
|
8039
|
+
provenance: import_types27.Provenance.EXTRACTED,
|
|
8040
|
+
confidence: (0, import_types27.confidenceForExtracted)("structural"),
|
|
7680
8041
|
evidence: { file: evidenceFile, line: lineContaining2(raw, svc.service) }
|
|
7681
8042
|
};
|
|
7682
8043
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -7687,7 +8048,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7687
8048
|
const result = addResourceEdge(
|
|
7688
8049
|
graph,
|
|
7689
8050
|
anchorId,
|
|
7690
|
-
|
|
8051
|
+
import_types27.EdgeType.DEPENDS_ON,
|
|
7691
8052
|
"cloudflare-service-binding",
|
|
7692
8053
|
svc.service,
|
|
7693
8054
|
evidenceFile,
|
|
@@ -7703,12 +8064,12 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
7703
8064
|
// src/extract/infra/vercel.ts
|
|
7704
8065
|
init_cjs_shims();
|
|
7705
8066
|
var import_node_fs22 = require("fs");
|
|
7706
|
-
var
|
|
7707
|
-
var
|
|
8067
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
8068
|
+
var import_types28 = require("@neat.is/types");
|
|
7708
8069
|
var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
|
|
7709
8070
|
async function readVercelConfig(dir) {
|
|
7710
8071
|
for (const filename of VERCEL_CONFIG_FILENAMES) {
|
|
7711
|
-
const abs =
|
|
8072
|
+
const abs = import_node_path39.default.join(dir, filename);
|
|
7712
8073
|
if (!await exists2(abs)) continue;
|
|
7713
8074
|
const raw = await import_node_fs22.promises.readFile(abs, "utf8");
|
|
7714
8075
|
const config = JSON.parse(maskCommentsInSource(raw));
|
|
@@ -7717,7 +8078,7 @@ async function readVercelConfig(dir) {
|
|
|
7717
8078
|
return null;
|
|
7718
8079
|
}
|
|
7719
8080
|
async function readLinkedProjectName(dir) {
|
|
7720
|
-
const abs =
|
|
8081
|
+
const abs = import_node_path39.default.join(dir, ".vercel", "project.json");
|
|
7721
8082
|
if (!await exists2(abs)) return void 0;
|
|
7722
8083
|
const parsed = JSON.parse(await import_node_fs22.promises.readFile(abs, "utf8"));
|
|
7723
8084
|
return typeof parsed.projectName === "string" ? parsed.projectName : void 0;
|
|
@@ -7735,7 +8096,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
7735
8096
|
read = await readVercelConfig(service.dir);
|
|
7736
8097
|
projectName = await readLinkedProjectName(service.dir);
|
|
7737
8098
|
} catch (err) {
|
|
7738
|
-
recordExtractionError("infra vercel",
|
|
8099
|
+
recordExtractionError("infra vercel", import_node_path39.default.relative(scanPath, service.dir), err);
|
|
7739
8100
|
continue;
|
|
7740
8101
|
}
|
|
7741
8102
|
if (!read && !projectName) continue;
|
|
@@ -7751,7 +8112,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
7751
8112
|
const anchorId = service.node.id;
|
|
7752
8113
|
if (!read) continue;
|
|
7753
8114
|
const { config, relFile, raw } = read;
|
|
7754
|
-
const evidenceFile = toPosix2(
|
|
8115
|
+
const evidenceFile = toPosix2(import_node_path39.default.relative(scanPath, import_node_path39.default.join(service.dir, relFile)));
|
|
7755
8116
|
const add = (edgeType, kind, name) => {
|
|
7756
8117
|
if (!name) return;
|
|
7757
8118
|
const result = emitPlatformResourceEdge(
|
|
@@ -7767,12 +8128,12 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
7767
8128
|
nodesAdded += result.nodesAdded;
|
|
7768
8129
|
edgesAdded += result.edgesAdded;
|
|
7769
8130
|
};
|
|
7770
|
-
add(
|
|
7771
|
-
for (const cron of config.crons ?? []) add(
|
|
7772
|
-
for (const varName of Object.keys(config.env ?? {})) add(
|
|
7773
|
-
for (const varName of Object.keys(config.build?.env ?? {})) add(
|
|
8131
|
+
add(import_types28.EdgeType.RUNS_ON, "vercel", "vercel");
|
|
8132
|
+
for (const cron of config.crons ?? []) add(import_types28.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
|
|
8133
|
+
for (const varName of Object.keys(config.env ?? {})) add(import_types28.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
8134
|
+
for (const varName of Object.keys(config.build?.env ?? {})) add(import_types28.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
7774
8135
|
for (const route of [...config.rewrites ?? [], ...config.redirects ?? [], ...config.routes ?? []]) {
|
|
7775
|
-
add(
|
|
8136
|
+
add(import_types28.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
|
|
7776
8137
|
}
|
|
7777
8138
|
}
|
|
7778
8139
|
return { nodesAdded, edgesAdded };
|
|
@@ -7781,13 +8142,13 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
7781
8142
|
// src/extract/infra/railway.ts
|
|
7782
8143
|
init_cjs_shims();
|
|
7783
8144
|
var import_node_fs23 = require("fs");
|
|
7784
|
-
var
|
|
8145
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
7785
8146
|
var import_smol_toml3 = require("smol-toml");
|
|
7786
|
-
var
|
|
8147
|
+
var import_types29 = require("@neat.is/types");
|
|
7787
8148
|
var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
|
|
7788
8149
|
async function readRailwayConfig(dir) {
|
|
7789
8150
|
for (const filename of RAILWAY_FILENAMES) {
|
|
7790
|
-
const abs =
|
|
8151
|
+
const abs = import_node_path40.default.join(dir, filename);
|
|
7791
8152
|
if (!await exists2(abs)) continue;
|
|
7792
8153
|
const raw = await import_node_fs23.promises.readFile(abs, "utf8");
|
|
7793
8154
|
const config = filename === "railway.toml" ? (0, import_smol_toml3.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
@@ -7803,7 +8164,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
7803
8164
|
try {
|
|
7804
8165
|
read = await readRailwayConfig(service.dir);
|
|
7805
8166
|
} catch (err) {
|
|
7806
|
-
recordExtractionError("infra railway",
|
|
8167
|
+
recordExtractionError("infra railway", import_node_path40.default.relative(scanPath, service.dir), err);
|
|
7807
8168
|
continue;
|
|
7808
8169
|
}
|
|
7809
8170
|
if (!read) continue;
|
|
@@ -7813,7 +8174,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
7813
8174
|
}
|
|
7814
8175
|
const anchorId = service.node.id;
|
|
7815
8176
|
const { config, relFile, raw } = read;
|
|
7816
|
-
const evidenceFile = toPosix2(
|
|
8177
|
+
const evidenceFile = toPosix2(import_node_path40.default.relative(scanPath, import_node_path40.default.join(service.dir, relFile)));
|
|
7817
8178
|
const add = (edgeType, kind, name) => {
|
|
7818
8179
|
if (!name) return;
|
|
7819
8180
|
const result = emitPlatformResourceEdge(
|
|
@@ -7829,9 +8190,9 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
7829
8190
|
nodesAdded += result.nodesAdded;
|
|
7830
8191
|
edgesAdded += result.edgesAdded;
|
|
7831
8192
|
};
|
|
7832
|
-
add(
|
|
7833
|
-
add(
|
|
7834
|
-
add(
|
|
8193
|
+
add(import_types29.EdgeType.RUNS_ON, "railway", "railway");
|
|
8194
|
+
add(import_types29.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
|
|
8195
|
+
add(import_types29.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
|
|
7835
8196
|
}
|
|
7836
8197
|
return { nodesAdded, edgesAdded };
|
|
7837
8198
|
}
|
|
@@ -7839,12 +8200,12 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
7839
8200
|
// src/extract/infra/supabase.ts
|
|
7840
8201
|
init_cjs_shims();
|
|
7841
8202
|
var import_node_fs24 = require("fs");
|
|
7842
|
-
var
|
|
8203
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
7843
8204
|
var import_smol_toml4 = require("smol-toml");
|
|
7844
|
-
var
|
|
8205
|
+
var import_types30 = require("@neat.is/types");
|
|
7845
8206
|
async function readSupabaseConfig(dir) {
|
|
7846
|
-
const relFile =
|
|
7847
|
-
const abs =
|
|
8207
|
+
const relFile = import_node_path41.default.join("supabase", "config.toml");
|
|
8208
|
+
const abs = import_node_path41.default.join(dir, relFile);
|
|
7848
8209
|
if (!await exists2(abs)) return null;
|
|
7849
8210
|
const raw = await import_node_fs24.promises.readFile(abs, "utf8");
|
|
7850
8211
|
const config = (0, import_smol_toml4.parse)(raw);
|
|
@@ -7858,7 +8219,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
7858
8219
|
try {
|
|
7859
8220
|
read = await readSupabaseConfig(service.dir);
|
|
7860
8221
|
} catch (err) {
|
|
7861
|
-
recordExtractionError("infra supabase",
|
|
8222
|
+
recordExtractionError("infra supabase", import_node_path41.default.relative(scanPath, service.dir), err);
|
|
7862
8223
|
continue;
|
|
7863
8224
|
}
|
|
7864
8225
|
if (!read) continue;
|
|
@@ -7873,7 +8234,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
7873
8234
|
});
|
|
7874
8235
|
}
|
|
7875
8236
|
const anchorId = service.node.id;
|
|
7876
|
-
const evidenceFile = toPosix2(
|
|
8237
|
+
const evidenceFile = toPosix2(import_node_path41.default.relative(scanPath, import_node_path41.default.join(service.dir, relFile)));
|
|
7877
8238
|
const add = (edgeType, kind, name) => {
|
|
7878
8239
|
if (!name) return;
|
|
7879
8240
|
const result = emitPlatformResourceEdge(
|
|
@@ -7889,10 +8250,10 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
7889
8250
|
nodesAdded += result.nodesAdded;
|
|
7890
8251
|
edgesAdded += result.edgesAdded;
|
|
7891
8252
|
};
|
|
7892
|
-
add(
|
|
7893
|
-
for (const fn of Object.keys(config.functions ?? {})) add(
|
|
7894
|
-
if (config.storage) add(
|
|
7895
|
-
if (config.auth) add(
|
|
8253
|
+
add(import_types30.EdgeType.RUNS_ON, "supabase", "supabase");
|
|
8254
|
+
for (const fn of Object.keys(config.functions ?? {})) add(import_types30.EdgeType.DEPENDS_ON, "supabase-function", fn);
|
|
8255
|
+
if (config.storage) add(import_types30.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
|
|
8256
|
+
if (config.auth) add(import_types30.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
|
|
7896
8257
|
}
|
|
7897
8258
|
return { nodesAdded, edgesAdded };
|
|
7898
8259
|
}
|
|
@@ -7914,17 +8275,17 @@ async function addInfra(graph, scanPath, services) {
|
|
|
7914
8275
|
}
|
|
7915
8276
|
|
|
7916
8277
|
// src/extract/index.ts
|
|
7917
|
-
var
|
|
8278
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
7918
8279
|
|
|
7919
8280
|
// src/extract/retire.ts
|
|
7920
8281
|
init_cjs_shims();
|
|
7921
8282
|
var import_node_fs25 = require("fs");
|
|
7922
|
-
var
|
|
7923
|
-
var
|
|
8283
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
8284
|
+
var import_types31 = require("@neat.is/types");
|
|
7924
8285
|
function dropOrphanedFileNodes(graph) {
|
|
7925
8286
|
const orphans = [];
|
|
7926
8287
|
graph.forEachNode((id, attrs) => {
|
|
7927
|
-
if (attrs.type !==
|
|
8288
|
+
if (attrs.type !== import_types31.NodeType.FileNode) return;
|
|
7928
8289
|
if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
|
|
7929
8290
|
orphans.push(id);
|
|
7930
8291
|
}
|
|
@@ -7937,14 +8298,14 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
7937
8298
|
const bases = [scanPath, ...serviceDirs];
|
|
7938
8299
|
graph.forEachEdge((id, attrs) => {
|
|
7939
8300
|
const edge = attrs;
|
|
7940
|
-
if (edge.provenance !==
|
|
8301
|
+
if (edge.provenance !== import_types31.Provenance.EXTRACTED) return;
|
|
7941
8302
|
const evidenceFile = edge.evidence?.file;
|
|
7942
8303
|
if (!evidenceFile) return;
|
|
7943
|
-
if (
|
|
8304
|
+
if (import_node_path42.default.isAbsolute(evidenceFile)) {
|
|
7944
8305
|
if (!(0, import_node_fs25.existsSync)(evidenceFile)) toDrop.push(id);
|
|
7945
8306
|
return;
|
|
7946
8307
|
}
|
|
7947
|
-
const found = bases.some((base) => (0, import_node_fs25.existsSync)(
|
|
8308
|
+
const found = bases.some((base) => (0, import_node_fs25.existsSync)(import_node_path42.default.join(base, evidenceFile)));
|
|
7948
8309
|
if (!found) toDrop.push(id);
|
|
7949
8310
|
});
|
|
7950
8311
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -7986,7 +8347,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
7986
8347
|
}
|
|
7987
8348
|
const droppedEntries = drainDroppedExtracted();
|
|
7988
8349
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
7989
|
-
const rejectedPath =
|
|
8350
|
+
const rejectedPath = import_node_path43.default.join(import_node_path43.default.dirname(opts.errorsPath), "rejected.ndjson");
|
|
7990
8351
|
try {
|
|
7991
8352
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
7992
8353
|
} catch (err) {
|
|
@@ -8098,8 +8459,8 @@ function canonicalJson(value) {
|
|
|
8098
8459
|
// src/persist.ts
|
|
8099
8460
|
init_cjs_shims();
|
|
8100
8461
|
var import_node_fs27 = require("fs");
|
|
8101
|
-
var
|
|
8102
|
-
var
|
|
8462
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
8463
|
+
var import_types32 = require("@neat.is/types");
|
|
8103
8464
|
var SCHEMA_VERSION = 4;
|
|
8104
8465
|
function migrateV1ToV2(payload) {
|
|
8105
8466
|
const nodes = payload.graph.nodes;
|
|
@@ -8121,12 +8482,12 @@ function migrateV2ToV3(payload) {
|
|
|
8121
8482
|
for (const edge of edges) {
|
|
8122
8483
|
const attrs = edge.attributes;
|
|
8123
8484
|
if (!attrs || attrs.provenance !== "FRONTIER") continue;
|
|
8124
|
-
attrs.provenance =
|
|
8485
|
+
attrs.provenance = import_types32.Provenance.OBSERVED;
|
|
8125
8486
|
const type = typeof attrs.type === "string" ? attrs.type : void 0;
|
|
8126
8487
|
const source = typeof attrs.source === "string" ? attrs.source : void 0;
|
|
8127
8488
|
const target = typeof attrs.target === "string" ? attrs.target : void 0;
|
|
8128
8489
|
if (type && source && target) {
|
|
8129
|
-
const newId = (0,
|
|
8490
|
+
const newId = (0, import_types32.observedEdgeId)(source, target, type);
|
|
8130
8491
|
attrs.id = newId;
|
|
8131
8492
|
if (edge.key) edge.key = newId;
|
|
8132
8493
|
}
|
|
@@ -8135,7 +8496,7 @@ function migrateV2ToV3(payload) {
|
|
|
8135
8496
|
return { ...payload, schemaVersion: 3 };
|
|
8136
8497
|
}
|
|
8137
8498
|
async function ensureDir(filePath) {
|
|
8138
|
-
await import_node_fs27.promises.mkdir(
|
|
8499
|
+
await import_node_fs27.promises.mkdir(import_node_path44.default.dirname(filePath), { recursive: true });
|
|
8139
8500
|
}
|
|
8140
8501
|
async function saveGraphToDisk(graph, outPath) {
|
|
8141
8502
|
await ensureDir(outPath);
|
|
@@ -8216,23 +8577,23 @@ function startPersistLoop(graph, outPath, opts = {}) {
|
|
|
8216
8577
|
|
|
8217
8578
|
// src/projects.ts
|
|
8218
8579
|
init_cjs_shims();
|
|
8219
|
-
var
|
|
8580
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
8220
8581
|
function pathsForProject(project, baseDir) {
|
|
8221
8582
|
if (project === DEFAULT_PROJECT) {
|
|
8222
8583
|
return {
|
|
8223
|
-
snapshotPath:
|
|
8224
|
-
errorsPath:
|
|
8225
|
-
staleEventsPath:
|
|
8226
|
-
embeddingsCachePath:
|
|
8227
|
-
policyViolationsPath:
|
|
8584
|
+
snapshotPath: import_node_path45.default.join(baseDir, "graph.json"),
|
|
8585
|
+
errorsPath: import_node_path45.default.join(baseDir, "errors.ndjson"),
|
|
8586
|
+
staleEventsPath: import_node_path45.default.join(baseDir, "stale-events.ndjson"),
|
|
8587
|
+
embeddingsCachePath: import_node_path45.default.join(baseDir, "embeddings.json"),
|
|
8588
|
+
policyViolationsPath: import_node_path45.default.join(baseDir, "policy-violations.ndjson")
|
|
8228
8589
|
};
|
|
8229
8590
|
}
|
|
8230
8591
|
return {
|
|
8231
|
-
snapshotPath:
|
|
8232
|
-
errorsPath:
|
|
8233
|
-
staleEventsPath:
|
|
8234
|
-
embeddingsCachePath:
|
|
8235
|
-
policyViolationsPath:
|
|
8592
|
+
snapshotPath: import_node_path45.default.join(baseDir, `${project}.json`),
|
|
8593
|
+
errorsPath: import_node_path45.default.join(baseDir, `errors.${project}.ndjson`),
|
|
8594
|
+
staleEventsPath: import_node_path45.default.join(baseDir, `stale-events.${project}.ndjson`),
|
|
8595
|
+
embeddingsCachePath: import_node_path45.default.join(baseDir, `embeddings.${project}.json`),
|
|
8596
|
+
policyViolationsPath: import_node_path45.default.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
8236
8597
|
};
|
|
8237
8598
|
}
|
|
8238
8599
|
var Projects = class {
|
|
@@ -8274,15 +8635,15 @@ function parseExtraProjects(raw) {
|
|
|
8274
8635
|
init_cjs_shims();
|
|
8275
8636
|
var import_node_fs28 = require("fs");
|
|
8276
8637
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
8277
|
-
var
|
|
8278
|
-
var
|
|
8638
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
8639
|
+
var import_types33 = require("@neat.is/types");
|
|
8279
8640
|
function neatHome() {
|
|
8280
8641
|
const override = process.env.NEAT_HOME;
|
|
8281
|
-
if (override && override.length > 0) return
|
|
8282
|
-
return
|
|
8642
|
+
if (override && override.length > 0) return import_node_path46.default.resolve(override);
|
|
8643
|
+
return import_node_path46.default.join(import_node_os3.default.homedir(), ".neat");
|
|
8283
8644
|
}
|
|
8284
8645
|
function registryPath() {
|
|
8285
|
-
return
|
|
8646
|
+
return import_node_path46.default.join(neatHome(), "projects.json");
|
|
8286
8647
|
}
|
|
8287
8648
|
async function readRegistry() {
|
|
8288
8649
|
const file = registryPath();
|
|
@@ -8296,7 +8657,7 @@ async function readRegistry() {
|
|
|
8296
8657
|
throw err;
|
|
8297
8658
|
}
|
|
8298
8659
|
const parsed = JSON.parse(raw);
|
|
8299
|
-
return
|
|
8660
|
+
return import_types33.RegistryFileSchema.parse(parsed);
|
|
8300
8661
|
}
|
|
8301
8662
|
async function getProject(name) {
|
|
8302
8663
|
const reg = await readRegistry();
|
|
@@ -8371,16 +8732,16 @@ init_auth();
|
|
|
8371
8732
|
// src/connectors-config.ts
|
|
8372
8733
|
init_cjs_shims();
|
|
8373
8734
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
8374
|
-
var
|
|
8735
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
8375
8736
|
var import_node_fs29 = require("fs");
|
|
8376
8737
|
var CONNECTORS_CONFIG_VERSION = 1;
|
|
8377
8738
|
function neatHome2() {
|
|
8378
8739
|
const override = process.env.NEAT_HOME;
|
|
8379
|
-
if (override && override.length > 0) return
|
|
8380
|
-
return
|
|
8740
|
+
if (override && override.length > 0) return import_node_path47.default.resolve(override);
|
|
8741
|
+
return import_node_path47.default.join(import_node_os4.default.homedir(), ".neat");
|
|
8381
8742
|
}
|
|
8382
8743
|
function connectorsConfigPath(home = neatHome2()) {
|
|
8383
|
-
return
|
|
8744
|
+
return import_node_path47.default.join(home, "connectors.json");
|
|
8384
8745
|
}
|
|
8385
8746
|
var MODE_MASK_LOOSER_THAN_0600 = 63;
|
|
8386
8747
|
async function warnIfModeLooserThan0600(file) {
|
|
@@ -8679,11 +9040,11 @@ function registerRoutes(scope, ctx) {
|
|
|
8679
9040
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
8680
9041
|
const parsed = [];
|
|
8681
9042
|
for (const c of candidates) {
|
|
8682
|
-
const r =
|
|
9043
|
+
const r = import_types34.DivergenceTypeSchema.safeParse(c);
|
|
8683
9044
|
if (!r.success) {
|
|
8684
9045
|
return reply.code(400).send({
|
|
8685
9046
|
error: `unknown divergence type "${c}"`,
|
|
8686
|
-
allowed:
|
|
9047
|
+
allowed: import_types34.DivergenceTypeSchema.options
|
|
8687
9048
|
});
|
|
8688
9049
|
}
|
|
8689
9050
|
parsed.push(r.data);
|
|
@@ -8954,7 +9315,7 @@ function registerRoutes(scope, ctx) {
|
|
|
8954
9315
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
8955
9316
|
let violations = await log.readAll();
|
|
8956
9317
|
if (req.query.severity) {
|
|
8957
|
-
const sev =
|
|
9318
|
+
const sev = import_types34.PolicySeveritySchema.safeParse(req.query.severity);
|
|
8958
9319
|
if (!sev.success) {
|
|
8959
9320
|
return reply.code(400).send({
|
|
8960
9321
|
error: "invalid severity",
|
|
@@ -8993,7 +9354,7 @@ function registerRoutes(scope, ctx) {
|
|
|
8993
9354
|
scope.post("/policies/check", async (req, reply) => {
|
|
8994
9355
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
8995
9356
|
if (!proj) return;
|
|
8996
|
-
const parsed =
|
|
9357
|
+
const parsed = import_types34.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
8997
9358
|
if (!parsed.success) {
|
|
8998
9359
|
return reply.code(400).send({
|
|
8999
9360
|
error: "invalid /policies/check body",
|
|
@@ -9127,7 +9488,7 @@ function registerRoutes(scope, ctx) {
|
|
|
9127
9488
|
});
|
|
9128
9489
|
}
|
|
9129
9490
|
async function buildApi(opts) {
|
|
9130
|
-
const app = (0, import_fastify.default)({ logger: false });
|
|
9491
|
+
const app = (0, import_fastify.default)({ logger: false, routerOptions: { maxParamLength: 1024 } });
|
|
9131
9492
|
await app.register(import_cors.default, { origin: true });
|
|
9132
9493
|
const env = readAuthEnv();
|
|
9133
9494
|
const authToken = opts.authToken ?? env.authToken;
|
|
@@ -9259,7 +9620,7 @@ init_otel_grpc();
|
|
|
9259
9620
|
// src/search.ts
|
|
9260
9621
|
init_cjs_shims();
|
|
9261
9622
|
var import_node_fs30 = require("fs");
|
|
9262
|
-
var
|
|
9623
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
9263
9624
|
var import_node_crypto3 = require("crypto");
|
|
9264
9625
|
var DEFAULT_LIMIT = 10;
|
|
9265
9626
|
var NOMIC_DIM = 768;
|
|
@@ -9422,7 +9783,7 @@ async function readCache(cachePath) {
|
|
|
9422
9783
|
}
|
|
9423
9784
|
}
|
|
9424
9785
|
async function writeCache(cachePath, cache) {
|
|
9425
|
-
await import_node_fs30.promises.mkdir(
|
|
9786
|
+
await import_node_fs30.promises.mkdir(import_node_path50.default.dirname(cachePath), { recursive: true });
|
|
9426
9787
|
await import_node_fs30.promises.writeFile(cachePath, JSON.stringify(cache));
|
|
9427
9788
|
}
|
|
9428
9789
|
var VectorIndex = class {
|
|
@@ -9603,14 +9964,14 @@ async function bootProject(registry, name, scanPath, baseDir) {
|
|
|
9603
9964
|
async function main() {
|
|
9604
9965
|
const baseDirEnv = process.env.NEAT_OUT_DIR;
|
|
9605
9966
|
const legacyOutPath = process.env.NEAT_OUT_PATH;
|
|
9606
|
-
const baseDir = baseDirEnv ?
|
|
9607
|
-
const defaultScanPath =
|
|
9967
|
+
const baseDir = baseDirEnv ? import_node_path51.default.resolve(baseDirEnv) : legacyOutPath ? import_node_path51.default.resolve(import_node_path51.default.dirname(legacyOutPath)) : import_node_path51.default.resolve("./neat-out");
|
|
9968
|
+
const defaultScanPath = import_node_path51.default.resolve(process.env.NEAT_SCAN_PATH ?? "./demo");
|
|
9608
9969
|
const registry = new Projects();
|
|
9609
9970
|
await bootProject(registry, DEFAULT_PROJECT, defaultScanPath, baseDir);
|
|
9610
9971
|
for (const name of parseExtraProjects(process.env.NEAT_PROJECTS)) {
|
|
9611
9972
|
const envKey = `NEAT_PROJECT_SCAN_PATH_${name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`;
|
|
9612
9973
|
const projectScan = process.env[envKey];
|
|
9613
|
-
await bootProject(registry, name, projectScan ?
|
|
9974
|
+
await bootProject(registry, name, projectScan ? import_node_path51.default.resolve(projectScan) : void 0, baseDir);
|
|
9614
9975
|
}
|
|
9615
9976
|
const host = process.env.HOST ?? "0.0.0.0";
|
|
9616
9977
|
const port = Number(process.env.PORT ?? 8080);
|