@neat.is/core 0.4.31-dev.20260718 → 0.5.1-dev.20260719
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-4M2YMGUM.js → chunk-BI3XKGVG.js} +162 -34
- package/dist/chunk-BI3XKGVG.js.map +1 -0
- package/dist/{chunk-2AJHEZIB.js → chunk-O4PCNQFG.js} +39 -12
- package/dist/chunk-O4PCNQFG.js.map +1 -0
- package/dist/cli.cjs +193 -62
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +208 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +208 -55
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +158 -32
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-2AJHEZIB.js.map +0 -1
- package/dist/chunk-4M2YMGUM.js.map +0 -1
package/dist/cli.cjs
CHANGED
|
@@ -1283,7 +1283,7 @@ function databaseRootCauseShape(graph, origin, walk3) {
|
|
|
1283
1283
|
for (const id of walk3.path) {
|
|
1284
1284
|
const owner = resolveOwningService(graph, id);
|
|
1285
1285
|
if (!owner) continue;
|
|
1286
|
-
const { id:
|
|
1286
|
+
const { id: serviceId6, svc } = owner;
|
|
1287
1287
|
const deps = svc.dependencies ?? {};
|
|
1288
1288
|
for (const pair of candidatePairs) {
|
|
1289
1289
|
const declared = deps[pair.driver];
|
|
@@ -1296,7 +1296,7 @@ function databaseRootCauseShape(graph, origin, walk3) {
|
|
|
1296
1296
|
);
|
|
1297
1297
|
if (!result.compatible) {
|
|
1298
1298
|
return {
|
|
1299
|
-
rootCauseNode:
|
|
1299
|
+
rootCauseNode: serviceId6,
|
|
1300
1300
|
rootCauseReason: result.reason ?? "incompatible driver",
|
|
1301
1301
|
...result.minDriverVersion ? {
|
|
1302
1302
|
fixRecommendation: `Upgrade ${svc.name} ${pair.driver} driver to >= ${result.minDriverVersion}`
|
|
@@ -1311,7 +1311,7 @@ function serviceRootCauseShape(graph, _origin, walk3) {
|
|
|
1311
1311
|
for (const id of walk3.path) {
|
|
1312
1312
|
const owner = resolveOwningService(graph, id);
|
|
1313
1313
|
if (!owner) continue;
|
|
1314
|
-
const { id:
|
|
1314
|
+
const { id: serviceId6, svc } = owner;
|
|
1315
1315
|
const deps = svc.dependencies ?? {};
|
|
1316
1316
|
const serviceNodeEngine = svc.nodeEngine;
|
|
1317
1317
|
for (const constraint of nodeEngineConstraints()) {
|
|
@@ -1320,7 +1320,7 @@ function serviceRootCauseShape(graph, _origin, walk3) {
|
|
|
1320
1320
|
const result = checkNodeEngineConstraint(constraint, declared, serviceNodeEngine);
|
|
1321
1321
|
if (!result.compatible && result.reason) {
|
|
1322
1322
|
return {
|
|
1323
|
-
rootCauseNode:
|
|
1323
|
+
rootCauseNode: serviceId6,
|
|
1324
1324
|
rootCauseReason: result.reason,
|
|
1325
1325
|
...result.requiredNodeVersion ? {
|
|
1326
1326
|
fixRecommendation: `Bump ${svc.name}'s engines.node to >= ${result.requiredNodeVersion}`
|
|
@@ -1335,7 +1335,7 @@ function serviceRootCauseShape(graph, _origin, walk3) {
|
|
|
1335
1335
|
const result = checkPackageConflict(conflict, declared, requiredDeclared);
|
|
1336
1336
|
if (!result.compatible && result.reason) {
|
|
1337
1337
|
return {
|
|
1338
|
-
rootCauseNode:
|
|
1338
|
+
rootCauseNode: serviceId6,
|
|
1339
1339
|
rootCauseReason: result.reason,
|
|
1340
1340
|
fixRecommendation: `Upgrade ${svc.name}'s ${conflict.requires.name} to >= ${conflict.requires.minVersion}`
|
|
1341
1341
|
};
|
|
@@ -1426,9 +1426,9 @@ function rootCauseFromIncidents(nodeId, incidents, errorEvent) {
|
|
|
1426
1426
|
function isFailingCallEdge(e) {
|
|
1427
1427
|
return e.type === import_types.EdgeType.CALLS && (e.signal?.errorCount ?? 0) > 0;
|
|
1428
1428
|
}
|
|
1429
|
-
function callSourcesForService(graph,
|
|
1430
|
-
const ids = [
|
|
1431
|
-
for (const edgeId of graph.outboundEdges(
|
|
1429
|
+
function callSourcesForService(graph, serviceId6) {
|
|
1430
|
+
const ids = [serviceId6];
|
|
1431
|
+
for (const edgeId of graph.outboundEdges(serviceId6)) {
|
|
1432
1432
|
const e = graph.getEdgeAttributes(edgeId);
|
|
1433
1433
|
if (e.type !== import_types.EdgeType.CONTAINS) continue;
|
|
1434
1434
|
const tgt = graph.getNodeAttributes(e.target);
|
|
@@ -1445,9 +1445,9 @@ function failingCallDominates(e, id, curEdge, curId) {
|
|
|
1445
1445
|
}
|
|
1446
1446
|
return id < curId;
|
|
1447
1447
|
}
|
|
1448
|
-
function dominantFailingCall(graph,
|
|
1448
|
+
function dominantFailingCall(graph, serviceId6, visited) {
|
|
1449
1449
|
let best = null;
|
|
1450
|
-
for (const src of callSourcesForService(graph,
|
|
1450
|
+
for (const src of callSourcesForService(graph, serviceId6)) {
|
|
1451
1451
|
for (const edgeId of graph.outboundEdges(src)) {
|
|
1452
1452
|
const e = graph.getEdgeAttributes(edgeId);
|
|
1453
1453
|
if (!isFailingCallEdge(e)) continue;
|
|
@@ -2616,6 +2616,27 @@ function ensureLocalDatabaseNode(graph, serviceName, name, engine) {
|
|
|
2616
2616
|
graph.addNode(id, node);
|
|
2617
2617
|
return id;
|
|
2618
2618
|
}
|
|
2619
|
+
function findDeclaredDatabaseForService(graph, serviceNodeId, engine) {
|
|
2620
|
+
if (!graph.hasNode(serviceNodeId)) return null;
|
|
2621
|
+
const sources = [serviceNodeId];
|
|
2622
|
+
for (const edgeId of graph.outboundEdges(serviceNodeId)) {
|
|
2623
|
+
const e = graph.getEdgeAttributes(edgeId);
|
|
2624
|
+
if (e.type === import_types3.EdgeType.CONTAINS) sources.push(e.target);
|
|
2625
|
+
}
|
|
2626
|
+
const matches = /* @__PURE__ */ new Set();
|
|
2627
|
+
for (const src of sources) {
|
|
2628
|
+
if (!graph.hasNode(src)) continue;
|
|
2629
|
+
for (const edgeId of graph.outboundEdges(src)) {
|
|
2630
|
+
const edge = graph.getEdgeAttributes(edgeId);
|
|
2631
|
+
if (edge.type !== import_types3.EdgeType.CONNECTS_TO || edge.provenance !== import_types3.Provenance.EXTRACTED) continue;
|
|
2632
|
+
if (!graph.hasNode(edge.target)) continue;
|
|
2633
|
+
const target = graph.getNodeAttributes(edge.target);
|
|
2634
|
+
if (target.type !== import_types3.NodeType.DatabaseNode || target.engine !== engine) continue;
|
|
2635
|
+
matches.add(edge.target);
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
return matches.size === 1 ? [...matches][0] : null;
|
|
2639
|
+
}
|
|
2619
2640
|
function ensureFrontierNode(graph, host, ts) {
|
|
2620
2641
|
const id = frontierIdFor(host);
|
|
2621
2642
|
if (graph.hasNode(id)) {
|
|
@@ -2636,6 +2657,7 @@ function ensureFrontierNode(graph, host, ts) {
|
|
|
2636
2657
|
}
|
|
2637
2658
|
function upsertObservedEdge(graph, type, source, target, ts, isError = false, evidence) {
|
|
2638
2659
|
if (!graph.hasNode(source) || !graph.hasNode(target)) return null;
|
|
2660
|
+
const grain = source.startsWith("file:") ? "file" : "service";
|
|
2639
2661
|
const id = makeObservedEdgeId(type, source, target);
|
|
2640
2662
|
if (graph.hasEdge(id)) {
|
|
2641
2663
|
const existing = graph.getEdgeAttributes(id);
|
|
@@ -2652,7 +2674,9 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
|
|
|
2652
2674
|
lastObserved: ts,
|
|
2653
2675
|
callCount: newSpanCount,
|
|
2654
2676
|
signal: newSignal,
|
|
2655
|
-
confidence: (0, import_types3.confidenceForObservedSignal)(newSignal)
|
|
2677
|
+
confidence: (0, import_types3.confidenceForObservedSignal)(newSignal),
|
|
2678
|
+
grain
|
|
2679
|
+
// backfills legacy edges that predate ADR-142
|
|
2656
2680
|
};
|
|
2657
2681
|
graph.replaceEdgeAttributes(id, updated);
|
|
2658
2682
|
return { edge: updated, created: false };
|
|
@@ -2672,6 +2696,7 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
|
|
|
2672
2696
|
lastObserved: ts,
|
|
2673
2697
|
callCount: 1,
|
|
2674
2698
|
signal,
|
|
2699
|
+
grain,
|
|
2675
2700
|
// Call-site evidence from span code.* semconv (file-awareness.md §4 + §6).
|
|
2676
2701
|
// Only set when code.filepath was present on the span — never fabricated.
|
|
2677
2702
|
...evidence ? { evidence } : {}
|
|
@@ -2874,13 +2899,18 @@ async function handleSpan(ctx, span) {
|
|
|
2874
2899
|
ensureDatabaseNode(ctx.graph, host, span.dbSystem);
|
|
2875
2900
|
targetId = (0, import_types3.databaseId)(host);
|
|
2876
2901
|
} else {
|
|
2877
|
-
const
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
localName
|
|
2882
|
-
|
|
2883
|
-
|
|
2902
|
+
const declared = findDeclaredDatabaseForService(ctx.graph, sourceId, span.dbSystem);
|
|
2903
|
+
if (declared) {
|
|
2904
|
+
targetId = declared;
|
|
2905
|
+
} else {
|
|
2906
|
+
const localName = span.dbName ?? span.dbSystem;
|
|
2907
|
+
targetId = ensureLocalDatabaseNode(
|
|
2908
|
+
ctx.graph,
|
|
2909
|
+
span.service,
|
|
2910
|
+
localName,
|
|
2911
|
+
span.dbSystem
|
|
2912
|
+
);
|
|
2913
|
+
}
|
|
2884
2914
|
}
|
|
2885
2915
|
const result = upsertObservedEdge(
|
|
2886
2916
|
ctx.graph,
|
|
@@ -3064,29 +3094,29 @@ function promoteFrontierNodes(graph, opts = {}) {
|
|
|
3064
3094
|
toPromote.push({ frontierId: id, serviceId: target });
|
|
3065
3095
|
});
|
|
3066
3096
|
let promoted = 0;
|
|
3067
|
-
for (const { frontierId: frontierId2, serviceId:
|
|
3097
|
+
for (const { frontierId: frontierId2, serviceId: serviceId6 } of toPromote) {
|
|
3068
3098
|
if (opts.policies && opts.policies.length > 0 && opts.policyCtx) {
|
|
3069
3099
|
const gate = canPromoteFrontier(graph, frontierId2, opts.policies, opts.policyCtx);
|
|
3070
3100
|
if (!gate.allowed) {
|
|
3071
3101
|
continue;
|
|
3072
3102
|
}
|
|
3073
3103
|
}
|
|
3074
|
-
rewireFrontierEdges(graph, frontierId2,
|
|
3104
|
+
rewireFrontierEdges(graph, frontierId2, serviceId6);
|
|
3075
3105
|
graph.dropNode(frontierId2);
|
|
3076
3106
|
promoted++;
|
|
3077
3107
|
}
|
|
3078
3108
|
return promoted;
|
|
3079
3109
|
}
|
|
3080
|
-
function rewireFrontierEdges(graph, frontierId2,
|
|
3110
|
+
function rewireFrontierEdges(graph, frontierId2, serviceId6) {
|
|
3081
3111
|
const inbound = [...graph.inboundEdges(frontierId2)];
|
|
3082
3112
|
const outbound = [...graph.outboundEdges(frontierId2)];
|
|
3083
3113
|
for (const edgeId of inbound) {
|
|
3084
3114
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
3085
|
-
rebuildEdge(graph, edge, edge.source,
|
|
3115
|
+
rebuildEdge(graph, edge, edge.source, serviceId6, edgeId);
|
|
3086
3116
|
}
|
|
3087
3117
|
for (const edgeId of outbound) {
|
|
3088
3118
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
3089
|
-
rebuildEdge(graph, edge,
|
|
3119
|
+
rebuildEdge(graph, edge, serviceId6, edge.target, edgeId);
|
|
3090
3120
|
}
|
|
3091
3121
|
}
|
|
3092
3122
|
function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
|
|
@@ -3894,9 +3924,9 @@ var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
|
3894
3924
|
"StatefulSet",
|
|
3895
3925
|
"DaemonSet"
|
|
3896
3926
|
]);
|
|
3897
|
-
function addAliases(graph,
|
|
3898
|
-
if (!graph.hasNode(
|
|
3899
|
-
const node = graph.getNodeAttributes(
|
|
3927
|
+
function addAliases(graph, serviceId6, candidates) {
|
|
3928
|
+
if (!graph.hasNode(serviceId6)) return;
|
|
3929
|
+
const node = graph.getNodeAttributes(serviceId6);
|
|
3900
3930
|
if (node.type !== import_types6.NodeType.ServiceNode) return;
|
|
3901
3931
|
const set = new Set(node.aliases ?? []);
|
|
3902
3932
|
for (const c of candidates) {
|
|
@@ -3906,7 +3936,7 @@ function addAliases(graph, serviceId5, candidates) {
|
|
|
3906
3936
|
}
|
|
3907
3937
|
if (set.size === 0) return;
|
|
3908
3938
|
const updated = { ...node, aliases: [...set].sort() };
|
|
3909
|
-
graph.replaceNodeAttributes(
|
|
3939
|
+
graph.replaceNodeAttributes(serviceId6, updated);
|
|
3910
3940
|
}
|
|
3911
3941
|
function indexServicesByName(services) {
|
|
3912
3942
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -3939,12 +3969,12 @@ async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
|
3939
3969
|
}
|
|
3940
3970
|
if (!compose?.services) return;
|
|
3941
3971
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
3942
|
-
const
|
|
3943
|
-
if (!
|
|
3972
|
+
const serviceId6 = serviceIndex.get(composeName);
|
|
3973
|
+
if (!serviceId6) continue;
|
|
3944
3974
|
const aliases = /* @__PURE__ */ new Set([composeName]);
|
|
3945
3975
|
if (svc.container_name) aliases.add(svc.container_name);
|
|
3946
3976
|
if (svc.hostname) aliases.add(svc.hostname);
|
|
3947
|
-
addAliases(graph,
|
|
3977
|
+
addAliases(graph, serviceId6, aliases);
|
|
3948
3978
|
}
|
|
3949
3979
|
}
|
|
3950
3980
|
var LABEL_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -4594,6 +4624,29 @@ async function readIfExists(filePath) {
|
|
|
4594
4624
|
return null;
|
|
4595
4625
|
}
|
|
4596
4626
|
}
|
|
4627
|
+
async function resolveEnvVar(serviceDir, name) {
|
|
4628
|
+
const entries = await import_node_fs13.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
4629
|
+
const envNames = entries.filter((e) => e.isFile() && (e.name === ".env" || e.name.startsWith(".env."))).map((e) => e.name);
|
|
4630
|
+
const rank = (n) => n === ".env.local" ? 0 : n === ".env" ? 1 : 2;
|
|
4631
|
+
envNames.sort((a, b) => rank(a) - rank(b) || a.localeCompare(b));
|
|
4632
|
+
for (const fileName of envNames) {
|
|
4633
|
+
const content = await readIfExists(import_node_path15.default.join(serviceDir, fileName));
|
|
4634
|
+
if (!content) continue;
|
|
4635
|
+
for (const line of content.split("\n")) {
|
|
4636
|
+
const trimmed = line.trim();
|
|
4637
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
4638
|
+
const eq = trimmed.indexOf("=");
|
|
4639
|
+
if (eq < 0) continue;
|
|
4640
|
+
if (trimmed.slice(0, eq).trim() !== name) continue;
|
|
4641
|
+
let value = trimmed.slice(eq + 1).trim();
|
|
4642
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
4643
|
+
value = value.slice(1, -1);
|
|
4644
|
+
}
|
|
4645
|
+
return value || null;
|
|
4646
|
+
}
|
|
4647
|
+
}
|
|
4648
|
+
return null;
|
|
4649
|
+
}
|
|
4597
4650
|
async function findFirst(serviceDir, candidates) {
|
|
4598
4651
|
for (const rel of candidates) {
|
|
4599
4652
|
const abs = import_node_path15.default.join(serviceDir, rel);
|
|
@@ -4691,6 +4744,14 @@ async function parse3(serviceDir) {
|
|
|
4691
4744
|
const config = parseConnectionString(urlMatch[1]);
|
|
4692
4745
|
if (config) return [{ ...config, sourceFile: schemaPath }];
|
|
4693
4746
|
}
|
|
4747
|
+
const envMatch = body.match(/url\s*=\s*env\(\s*"([^"]+)"\s*\)/);
|
|
4748
|
+
if (envMatch) {
|
|
4749
|
+
const resolved = await resolveEnvVar(serviceDir, envMatch[1]);
|
|
4750
|
+
if (resolved) {
|
|
4751
|
+
const config = parseConnectionString(resolved);
|
|
4752
|
+
if (config) return [{ ...config, sourceFile: schemaPath }];
|
|
4753
|
+
}
|
|
4754
|
+
}
|
|
4694
4755
|
return [
|
|
4695
4756
|
{
|
|
4696
4757
|
host: `${engine}-prisma`,
|
|
@@ -4734,6 +4795,15 @@ async function parse4(serviceDir) {
|
|
|
4734
4795
|
const config = parseConnectionString(urlMatch[1]);
|
|
4735
4796
|
if (config) return [{ ...config, sourceFile: filePath }];
|
|
4736
4797
|
}
|
|
4798
|
+
const urlEnvMatch = content.match(
|
|
4799
|
+
/(?:url|connectionString)\s*:\s*process\.env(?:\.([A-Za-z_$][\w$]*)|\[\s*['"]([^'"]+)['"]\s*\])/
|
|
4800
|
+
);
|
|
4801
|
+
if (urlEnvMatch) {
|
|
4802
|
+
const varName = urlEnvMatch[1] ?? urlEnvMatch[2];
|
|
4803
|
+
const resolved = varName ? await resolveEnvVar(serviceDir, varName) : null;
|
|
4804
|
+
const config = resolved ? parseConnectionString(resolved) : null;
|
|
4805
|
+
if (config) return [{ ...config, sourceFile: filePath }];
|
|
4806
|
+
}
|
|
4737
4807
|
const hostMatch = content.match(/host\s*:\s*['"`]([^'"`]+)['"`]/);
|
|
4738
4808
|
if (hostMatch) {
|
|
4739
4809
|
const portMatch = content.match(/port\s*:\s*(\d+)/);
|
|
@@ -4787,6 +4857,15 @@ async function parse5(serviceDir) {
|
|
|
4787
4857
|
const config = parseConnectionString(urlMatch[1]);
|
|
4788
4858
|
if (config) return [{ ...config, sourceFile: filePath }];
|
|
4789
4859
|
}
|
|
4860
|
+
const urlEnvMatch = content.match(
|
|
4861
|
+
/connection\s*:\s*process\.env(?:\.([A-Za-z_$][\w$]*)|\[\s*['"]([^'"]+)['"]\s*\])/
|
|
4862
|
+
);
|
|
4863
|
+
if (urlEnvMatch) {
|
|
4864
|
+
const varName = urlEnvMatch[1] ?? urlEnvMatch[2];
|
|
4865
|
+
const resolved = varName ? await resolveEnvVar(serviceDir, varName) : null;
|
|
4866
|
+
const config = resolved ? parseConnectionString(resolved) : null;
|
|
4867
|
+
if (config) return [{ ...config, sourceFile: filePath }];
|
|
4868
|
+
}
|
|
4790
4869
|
const host = content.match(/host\s*:\s*['"`]([^'"`]+)['"`]/)?.[1];
|
|
4791
4870
|
if (host) {
|
|
4792
4871
|
const port = content.match(/port\s*:\s*(\d+)/)?.[1];
|
|
@@ -6335,6 +6414,16 @@ function constructorMatchesImport(name, ctx) {
|
|
|
6335
6414
|
if (name === "createClient") return ctx.hasSupabaseJs;
|
|
6336
6415
|
return ctx.hasSupabaseSsr;
|
|
6337
6416
|
}
|
|
6417
|
+
var SUPABASE_CLIENT_ASSIGN_RE = /(?:const|let|var)\s+(\w+)\s*=\s*(?:await\s+)?(createClient|createServerClient|createBrowserClient)\s*\(/g;
|
|
6418
|
+
function supabaseClientVars(content, ctx) {
|
|
6419
|
+
const vars = /* @__PURE__ */ new Set();
|
|
6420
|
+
SUPABASE_CLIENT_ASSIGN_RE.lastIndex = 0;
|
|
6421
|
+
let m;
|
|
6422
|
+
while ((m = SUPABASE_CLIENT_ASSIGN_RE.exec(content)) !== null) {
|
|
6423
|
+
if (constructorMatchesImport(m[2], ctx)) vars.add(m[1]);
|
|
6424
|
+
}
|
|
6425
|
+
return vars;
|
|
6426
|
+
}
|
|
6338
6427
|
function supabaseEndpointsFromFile(file, serviceDir) {
|
|
6339
6428
|
const ctx = readImports2(file.content);
|
|
6340
6429
|
if (!ctx.hasSupabaseJs && !ctx.hasSupabaseSsr) return [];
|
|
@@ -6367,6 +6456,34 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
6367
6456
|
}
|
|
6368
6457
|
});
|
|
6369
6458
|
}
|
|
6459
|
+
const clientVars = supabaseClientVars(file.content, ctx);
|
|
6460
|
+
for (const clientVar of clientVars) {
|
|
6461
|
+
const accessRe = new RegExp(
|
|
6462
|
+
`\\b${clientVar}\\s*\\.\\s*(from|rpc)\\s*\\(\\s*['"\`]([\\w.-]+)['"\`]`,
|
|
6463
|
+
"g"
|
|
6464
|
+
);
|
|
6465
|
+
let am;
|
|
6466
|
+
while ((am = accessRe.exec(file.content)) !== null) {
|
|
6467
|
+
const kind = am[1] === "rpc" ? "supabase-rpc" : "supabase-table";
|
|
6468
|
+
const resource = am[2];
|
|
6469
|
+
const key = `${kind}/${resource}`;
|
|
6470
|
+
if (seen.has(key)) continue;
|
|
6471
|
+
seen.add(key);
|
|
6472
|
+
const line = lineOf(file.content, am[0]);
|
|
6473
|
+
out.push({
|
|
6474
|
+
infraId: (0, import_types19.infraId)(kind, resource),
|
|
6475
|
+
name: resource,
|
|
6476
|
+
kind,
|
|
6477
|
+
edgeType: "CALLS",
|
|
6478
|
+
confidenceKind: "verified-call-site",
|
|
6479
|
+
evidence: {
|
|
6480
|
+
file: import_node_path31.default.relative(serviceDir, file.path),
|
|
6481
|
+
line,
|
|
6482
|
+
snippet: snippet(file.content, line)
|
|
6483
|
+
}
|
|
6484
|
+
});
|
|
6485
|
+
}
|
|
6486
|
+
}
|
|
6370
6487
|
return out;
|
|
6371
6488
|
}
|
|
6372
6489
|
|
|
@@ -7448,14 +7565,23 @@ var import_types30 = require("@neat.is/types");
|
|
|
7448
7565
|
function bucketKey(source, target, type) {
|
|
7449
7566
|
return `${type}|${source}|${target}`;
|
|
7450
7567
|
}
|
|
7568
|
+
function bucketSourceFor(graph, edge) {
|
|
7569
|
+
if (edge.type !== import_types30.EdgeType.CONNECTS_TO) return edge.source;
|
|
7570
|
+
const parsed = (0, import_types30.parseFileId)(edge.source);
|
|
7571
|
+
if (!parsed || !graph.hasNode(edge.target)) return edge.source;
|
|
7572
|
+
const target = graph.getNodeAttributes(edge.target);
|
|
7573
|
+
if (target.type !== import_types30.NodeType.DatabaseNode) return edge.source;
|
|
7574
|
+
return (0, import_types30.serviceId)(parsed.service);
|
|
7575
|
+
}
|
|
7451
7576
|
function bucketEdges(graph) {
|
|
7452
7577
|
const buckets2 = /* @__PURE__ */ new Map();
|
|
7453
7578
|
graph.forEachEdge((id, attrs) => {
|
|
7454
7579
|
const e = attrs;
|
|
7455
7580
|
const parsed = (0, import_types30.parseEdgeId)(id);
|
|
7456
7581
|
const provenance = parsed?.provenance ?? e.provenance;
|
|
7457
|
-
const
|
|
7458
|
-
const
|
|
7582
|
+
const source = bucketSourceFor(graph, e);
|
|
7583
|
+
const key = bucketKey(source, e.target, e.type);
|
|
7584
|
+
const cur = buckets2.get(key) ?? { source, target: e.target, type: e.type };
|
|
7459
7585
|
switch (provenance) {
|
|
7460
7586
|
case import_types30.Provenance.EXTRACTED:
|
|
7461
7587
|
cur.extracted = e;
|
|
@@ -9955,6 +10081,7 @@ init_otel();
|
|
|
9955
10081
|
|
|
9956
10082
|
// src/connectors/index.ts
|
|
9957
10083
|
init_cjs_shims();
|
|
10084
|
+
var import_types35 = require("@neat.is/types");
|
|
9958
10085
|
|
|
9959
10086
|
// src/connectors/registry.ts
|
|
9960
10087
|
init_cjs_shims();
|
|
@@ -10430,19 +10557,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
|
|
|
10430
10557
|
|
|
10431
10558
|
// src/connectors/supabase/resolve.ts
|
|
10432
10559
|
init_cjs_shims();
|
|
10433
|
-
var
|
|
10560
|
+
var import_types37 = require("@neat.is/types");
|
|
10434
10561
|
function createSupabaseResolveTarget(graph, config) {
|
|
10435
10562
|
return (signal, _ctx) => {
|
|
10436
10563
|
if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
|
|
10437
10564
|
return null;
|
|
10438
10565
|
}
|
|
10439
|
-
const subResourceId = (0,
|
|
10566
|
+
const subResourceId = (0, import_types37.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
|
|
10440
10567
|
if (graph.hasNode(subResourceId)) {
|
|
10441
|
-
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType:
|
|
10568
|
+
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types37.EdgeType.CALLS };
|
|
10442
10569
|
}
|
|
10443
|
-
const
|
|
10570
|
+
const bareResourceId = (0, import_types37.infraId)(signal.targetKind, signal.targetName);
|
|
10571
|
+
if (graph.hasNode(bareResourceId)) {
|
|
10572
|
+
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types37.EdgeType.CALLS };
|
|
10573
|
+
}
|
|
10574
|
+
const projectLevelId = (0, import_types37.infraId)("supabase", config.nodeRef);
|
|
10444
10575
|
if (graph.hasNode(projectLevelId)) {
|
|
10445
|
-
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType:
|
|
10576
|
+
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types37.EdgeType.CALLS };
|
|
10446
10577
|
}
|
|
10447
10578
|
return null;
|
|
10448
10579
|
};
|
|
@@ -10535,7 +10666,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
|
|
|
10535
10666
|
|
|
10536
10667
|
// src/connectors/railway/index.ts
|
|
10537
10668
|
init_cjs_shims();
|
|
10538
|
-
var
|
|
10669
|
+
var import_types41 = require("@neat.is/types");
|
|
10539
10670
|
|
|
10540
10671
|
// src/connectors/railway/client.ts
|
|
10541
10672
|
init_cjs_shims();
|
|
@@ -10661,7 +10792,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
|
|
|
10661
10792
|
const out = [];
|
|
10662
10793
|
graph.forEachNode((_id, attrs) => {
|
|
10663
10794
|
const node = attrs;
|
|
10664
|
-
if (node.type !==
|
|
10795
|
+
if (node.type !== import_types41.NodeType.RouteNode) return;
|
|
10665
10796
|
const route = attrs;
|
|
10666
10797
|
if (route.service !== serviceName) return;
|
|
10667
10798
|
out.push({
|
|
@@ -10757,12 +10888,12 @@ function createRailwayResolveTarget(config) {
|
|
|
10757
10888
|
const serviceName = config.serviceNameById[config.serviceId];
|
|
10758
10889
|
if (!serviceName) return null;
|
|
10759
10890
|
if (signal.targetKind === ROUTE_TARGET_KIND) {
|
|
10760
|
-
return { targetNodeId: signal.targetName, serviceName, edgeType:
|
|
10891
|
+
return { targetNodeId: signal.targetName, serviceName, edgeType: import_types41.EdgeType.CALLS };
|
|
10761
10892
|
}
|
|
10762
10893
|
if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
|
|
10763
10894
|
const peerName = config.serviceNameById[signal.targetName];
|
|
10764
10895
|
if (!peerName) return null;
|
|
10765
|
-
return { targetNodeId: (0,
|
|
10896
|
+
return { targetNodeId: (0, import_types41.serviceId)(peerName), serviceName, edgeType: import_types41.EdgeType.CONNECTS_TO };
|
|
10766
10897
|
}
|
|
10767
10898
|
return null;
|
|
10768
10899
|
};
|
|
@@ -10949,7 +11080,7 @@ function mapLogEntriesToSignals(entries) {
|
|
|
10949
11080
|
|
|
10950
11081
|
// src/connectors/firebase/resolve.ts
|
|
10951
11082
|
init_cjs_shims();
|
|
10952
|
-
var
|
|
11083
|
+
var import_types42 = require("@neat.is/types");
|
|
10953
11084
|
function neatServiceNameFor(resourceType, resourceName, serviceMap) {
|
|
10954
11085
|
switch (resourceType) {
|
|
10955
11086
|
case "cloud_function":
|
|
@@ -10964,7 +11095,7 @@ function routeEntriesFor(graph, serviceName) {
|
|
|
10964
11095
|
const entries = [];
|
|
10965
11096
|
graph.forEachNode((_id, attrs) => {
|
|
10966
11097
|
const node = attrs;
|
|
10967
|
-
if (node.type !==
|
|
11098
|
+
if (node.type !== import_types42.NodeType.RouteNode) return;
|
|
10968
11099
|
const route = attrs;
|
|
10969
11100
|
if (route.service !== serviceName) return;
|
|
10970
11101
|
entries.push({
|
|
@@ -10996,7 +11127,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
|
|
|
10996
11127
|
return {
|
|
10997
11128
|
targetNodeId: match.routeNodeId,
|
|
10998
11129
|
serviceName,
|
|
10999
|
-
edgeType:
|
|
11130
|
+
edgeType: import_types42.EdgeType.CALLS
|
|
11000
11131
|
};
|
|
11001
11132
|
};
|
|
11002
11133
|
}
|
|
@@ -11023,7 +11154,7 @@ init_cjs_shims();
|
|
|
11023
11154
|
|
|
11024
11155
|
// src/connectors/cloudflare/connector.ts
|
|
11025
11156
|
init_cjs_shims();
|
|
11026
|
-
var
|
|
11157
|
+
var import_types44 = require("@neat.is/types");
|
|
11027
11158
|
|
|
11028
11159
|
// src/connectors/cloudflare/client.ts
|
|
11029
11160
|
init_cjs_shims();
|
|
@@ -11184,7 +11315,7 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
11184
11315
|
graph.forEachNode((id, attrs) => {
|
|
11185
11316
|
if (found) return;
|
|
11186
11317
|
const a = attrs;
|
|
11187
|
-
if (a.type ===
|
|
11318
|
+
if (a.type === import_types44.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
|
|
11188
11319
|
found = id;
|
|
11189
11320
|
}
|
|
11190
11321
|
});
|
|
@@ -11196,7 +11327,7 @@ function findMatchingRouteNode(graph, serviceName, method, path61) {
|
|
|
11196
11327
|
graph.forEachNode((id, attrs) => {
|
|
11197
11328
|
if (found) return;
|
|
11198
11329
|
const a = attrs;
|
|
11199
|
-
if (a.type !==
|
|
11330
|
+
if (a.type !== import_types44.NodeType.RouteNode || a.service !== serviceName) return;
|
|
11200
11331
|
if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
|
|
11201
11332
|
const routeMethod = (a.method ?? "").toUpperCase();
|
|
11202
11333
|
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
@@ -11215,11 +11346,11 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
11215
11346
|
};
|
|
11216
11347
|
const mapping = config.workers?.[scriptName];
|
|
11217
11348
|
if (mapping) {
|
|
11218
|
-
const wholeFileId = (0,
|
|
11349
|
+
const wholeFileId = (0, import_types44.fileId)(mapping.service, mapping.entryFile);
|
|
11219
11350
|
return {
|
|
11220
11351
|
targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
|
|
11221
11352
|
serviceName: mapping.service,
|
|
11222
|
-
edgeType:
|
|
11353
|
+
edgeType: import_types44.EdgeType.CALLS
|
|
11223
11354
|
};
|
|
11224
11355
|
}
|
|
11225
11356
|
const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
|
|
@@ -11228,13 +11359,13 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
11228
11359
|
return {
|
|
11229
11360
|
targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
|
|
11230
11361
|
serviceName: fileNode.service,
|
|
11231
|
-
edgeType:
|
|
11362
|
+
edgeType: import_types44.EdgeType.CALLS
|
|
11232
11363
|
};
|
|
11233
11364
|
}
|
|
11234
11365
|
return {
|
|
11235
|
-
targetNodeId: (0,
|
|
11366
|
+
targetNodeId: (0, import_types44.infraId)("cloudflare-worker", scriptName),
|
|
11236
11367
|
serviceName: scriptName,
|
|
11237
|
-
edgeType:
|
|
11368
|
+
edgeType: import_types44.EdgeType.CALLS,
|
|
11238
11369
|
ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
|
|
11239
11370
|
};
|
|
11240
11371
|
};
|
|
@@ -11448,7 +11579,7 @@ var import_node_fs32 = require("fs");
|
|
|
11448
11579
|
var import_node_path51 = __toESM(require("path"), 1);
|
|
11449
11580
|
|
|
11450
11581
|
// src/daemon.ts
|
|
11451
|
-
var
|
|
11582
|
+
var import_types47 = require("@neat.is/types");
|
|
11452
11583
|
function daemonJsonPath(scanPath) {
|
|
11453
11584
|
return import_node_path52.default.join(scanPath, "neat-out", "daemon.json");
|
|
11454
11585
|
}
|
|
@@ -15444,7 +15575,7 @@ var import_node_path59 = __toESM(require("path"), 1);
|
|
|
15444
15575
|
|
|
15445
15576
|
// src/cli-client.ts
|
|
15446
15577
|
init_cjs_shims();
|
|
15447
|
-
var
|
|
15578
|
+
var import_types48 = require("@neat.is/types");
|
|
15448
15579
|
var HttpError = class extends Error {
|
|
15449
15580
|
constructor(status2, message, responseBody = "") {
|
|
15450
15581
|
super(message);
|
|
@@ -15586,7 +15717,7 @@ async function runBlastRadius(client, input) {
|
|
|
15586
15717
|
}
|
|
15587
15718
|
}
|
|
15588
15719
|
function formatBlastEntry(n) {
|
|
15589
|
-
const tag = n.edgeProvenance ===
|
|
15720
|
+
const tag = n.edgeProvenance === import_types48.Provenance.STALE ? " [STALE \u2014 last seen too long ago]" : "";
|
|
15590
15721
|
return ` \u2022 ${n.nodeId} (distance ${n.distance}, ${n.edgeProvenance})${tag}`;
|
|
15591
15722
|
}
|
|
15592
15723
|
async function runDependencies(client, input) {
|
|
@@ -15643,7 +15774,7 @@ async function runObservedDependencies(client, input) {
|
|
|
15643
15774
|
if (result.observed) {
|
|
15644
15775
|
return {
|
|
15645
15776
|
summary: `${input.nodeId} makes no outbound runtime calls, but OTel has observed it receiving traffic on ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 it's a pure receiver.`,
|
|
15646
|
-
provenance:
|
|
15777
|
+
provenance: import_types48.Provenance.OBSERVED
|
|
15647
15778
|
};
|
|
15648
15779
|
}
|
|
15649
15780
|
const note = result.hasExtractedOutbound ? " Static (EXTRACTED) dependencies exist but no runtime traffic has been seen \u2014 is OTel running?" : "";
|
|
@@ -15653,7 +15784,7 @@ async function runObservedDependencies(client, input) {
|
|
|
15653
15784
|
return {
|
|
15654
15785
|
summary: `${input.nodeId} has ${result.dependencies.length} runtime dependenc${result.dependencies.length === 1 ? "y" : "ies"} confirmed by OTel.`,
|
|
15655
15786
|
block: blockLines.join("\n"),
|
|
15656
|
-
provenance:
|
|
15787
|
+
provenance: import_types48.Provenance.OBSERVED
|
|
15657
15788
|
};
|
|
15658
15789
|
} catch (err) {
|
|
15659
15790
|
if (err instanceof HttpError && err.status === 404) {
|
|
@@ -15707,7 +15838,7 @@ async function runIncidents(client, input) {
|
|
|
15707
15838
|
return {
|
|
15708
15839
|
summary: `${target} has ${body.total} recorded incident${body.total === 1 ? "" : "s"}; showing the ${ordered.length} most recent.`,
|
|
15709
15840
|
block: blockLines.join("\n"),
|
|
15710
|
-
provenance:
|
|
15841
|
+
provenance: import_types48.Provenance.OBSERVED
|
|
15711
15842
|
};
|
|
15712
15843
|
} catch (err) {
|
|
15713
15844
|
if (err instanceof HttpError && err.status === 404) {
|
|
@@ -15816,7 +15947,7 @@ async function runStaleEdges(client, input) {
|
|
|
15816
15947
|
return {
|
|
15817
15948
|
summary: `${events.length} stale-edge transition${events.length === 1 ? "" : "s"} recorded${input.edgeType ? ` for ${input.edgeType}` : ""}.`,
|
|
15818
15949
|
block: blockLines.join("\n"),
|
|
15819
|
-
provenance:
|
|
15950
|
+
provenance: import_types48.Provenance.STALE
|
|
15820
15951
|
};
|
|
15821
15952
|
}
|
|
15822
15953
|
async function runPolicies(client, input) {
|
|
@@ -16133,7 +16264,7 @@ async function runSync(opts) {
|
|
|
16133
16264
|
}
|
|
16134
16265
|
|
|
16135
16266
|
// src/cli.ts
|
|
16136
|
-
var
|
|
16267
|
+
var import_types49 = require("@neat.is/types");
|
|
16137
16268
|
function isNpxInvocation() {
|
|
16138
16269
|
if (process.env.npm_command === "exec") return true;
|
|
16139
16270
|
const execpath = process.env.npm_execpath ?? "";
|
|
@@ -17070,10 +17201,10 @@ async function runQueryVerb(cmd, parsed) {
|
|
|
17070
17201
|
const parts = parsed.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
17071
17202
|
const out = [];
|
|
17072
17203
|
for (const p of parts) {
|
|
17073
|
-
const r =
|
|
17204
|
+
const r = import_types49.DivergenceTypeSchema.safeParse(p);
|
|
17074
17205
|
if (!r.success) {
|
|
17075
17206
|
console.error(
|
|
17076
|
-
`neat divergences: unknown --type "${p}". allowed: ${
|
|
17207
|
+
`neat divergences: unknown --type "${p}". allowed: ${import_types49.DivergenceTypeSchema.options.join(", ")}`
|
|
17077
17208
|
);
|
|
17078
17209
|
return 2;
|
|
17079
17210
|
}
|