@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
|
@@ -483,7 +483,7 @@ function databaseRootCauseShape(graph, origin, walk3) {
|
|
|
483
483
|
for (const id of walk3.path) {
|
|
484
484
|
const owner = resolveOwningService(graph, id);
|
|
485
485
|
if (!owner) continue;
|
|
486
|
-
const { id:
|
|
486
|
+
const { id: serviceId5, svc } = owner;
|
|
487
487
|
const deps = svc.dependencies ?? {};
|
|
488
488
|
for (const pair of candidatePairs) {
|
|
489
489
|
const declared = deps[pair.driver];
|
|
@@ -496,7 +496,7 @@ function databaseRootCauseShape(graph, origin, walk3) {
|
|
|
496
496
|
);
|
|
497
497
|
if (!result.compatible) {
|
|
498
498
|
return {
|
|
499
|
-
rootCauseNode:
|
|
499
|
+
rootCauseNode: serviceId5,
|
|
500
500
|
rootCauseReason: result.reason ?? "incompatible driver",
|
|
501
501
|
...result.minDriverVersion ? {
|
|
502
502
|
fixRecommendation: `Upgrade ${svc.name} ${pair.driver} driver to >= ${result.minDriverVersion}`
|
|
@@ -511,7 +511,7 @@ function serviceRootCauseShape(graph, _origin, walk3) {
|
|
|
511
511
|
for (const id of walk3.path) {
|
|
512
512
|
const owner = resolveOwningService(graph, id);
|
|
513
513
|
if (!owner) continue;
|
|
514
|
-
const { id:
|
|
514
|
+
const { id: serviceId5, svc } = owner;
|
|
515
515
|
const deps = svc.dependencies ?? {};
|
|
516
516
|
const serviceNodeEngine = svc.nodeEngine;
|
|
517
517
|
for (const constraint of nodeEngineConstraints()) {
|
|
@@ -520,7 +520,7 @@ function serviceRootCauseShape(graph, _origin, walk3) {
|
|
|
520
520
|
const result = checkNodeEngineConstraint(constraint, declared, serviceNodeEngine);
|
|
521
521
|
if (!result.compatible && result.reason) {
|
|
522
522
|
return {
|
|
523
|
-
rootCauseNode:
|
|
523
|
+
rootCauseNode: serviceId5,
|
|
524
524
|
rootCauseReason: result.reason,
|
|
525
525
|
...result.requiredNodeVersion ? {
|
|
526
526
|
fixRecommendation: `Bump ${svc.name}'s engines.node to >= ${result.requiredNodeVersion}`
|
|
@@ -535,7 +535,7 @@ function serviceRootCauseShape(graph, _origin, walk3) {
|
|
|
535
535
|
const result = checkPackageConflict(conflict, declared, requiredDeclared);
|
|
536
536
|
if (!result.compatible && result.reason) {
|
|
537
537
|
return {
|
|
538
|
-
rootCauseNode:
|
|
538
|
+
rootCauseNode: serviceId5,
|
|
539
539
|
rootCauseReason: result.reason,
|
|
540
540
|
fixRecommendation: `Upgrade ${svc.name}'s ${conflict.requires.name} to >= ${conflict.requires.minVersion}`
|
|
541
541
|
};
|
|
@@ -626,9 +626,9 @@ function rootCauseFromIncidents(nodeId, incidents, errorEvent) {
|
|
|
626
626
|
function isFailingCallEdge(e) {
|
|
627
627
|
return e.type === EdgeType.CALLS && (e.signal?.errorCount ?? 0) > 0;
|
|
628
628
|
}
|
|
629
|
-
function callSourcesForService(graph,
|
|
630
|
-
const ids = [
|
|
631
|
-
for (const edgeId of graph.outboundEdges(
|
|
629
|
+
function callSourcesForService(graph, serviceId5) {
|
|
630
|
+
const ids = [serviceId5];
|
|
631
|
+
for (const edgeId of graph.outboundEdges(serviceId5)) {
|
|
632
632
|
const e = graph.getEdgeAttributes(edgeId);
|
|
633
633
|
if (e.type !== EdgeType.CONTAINS) continue;
|
|
634
634
|
const tgt = graph.getNodeAttributes(e.target);
|
|
@@ -645,9 +645,9 @@ function failingCallDominates(e, id, curEdge, curId) {
|
|
|
645
645
|
}
|
|
646
646
|
return id < curId;
|
|
647
647
|
}
|
|
648
|
-
function dominantFailingCall(graph,
|
|
648
|
+
function dominantFailingCall(graph, serviceId5, visited) {
|
|
649
649
|
let best = null;
|
|
650
|
-
for (const src of callSourcesForService(graph,
|
|
650
|
+
for (const src of callSourcesForService(graph, serviceId5)) {
|
|
651
651
|
for (const edgeId of graph.outboundEdges(src)) {
|
|
652
652
|
const e = graph.getEdgeAttributes(edgeId);
|
|
653
653
|
if (!isFailingCallEdge(e)) continue;
|
|
@@ -1923,6 +1923,27 @@ function ensureLocalDatabaseNode(graph, serviceName, name, engine) {
|
|
|
1923
1923
|
graph.addNode(id, node);
|
|
1924
1924
|
return id;
|
|
1925
1925
|
}
|
|
1926
|
+
function findDeclaredDatabaseForService(graph, serviceNodeId, engine) {
|
|
1927
|
+
if (!graph.hasNode(serviceNodeId)) return null;
|
|
1928
|
+
const sources = [serviceNodeId];
|
|
1929
|
+
for (const edgeId of graph.outboundEdges(serviceNodeId)) {
|
|
1930
|
+
const e = graph.getEdgeAttributes(edgeId);
|
|
1931
|
+
if (e.type === EdgeType3.CONTAINS) sources.push(e.target);
|
|
1932
|
+
}
|
|
1933
|
+
const matches = /* @__PURE__ */ new Set();
|
|
1934
|
+
for (const src of sources) {
|
|
1935
|
+
if (!graph.hasNode(src)) continue;
|
|
1936
|
+
for (const edgeId of graph.outboundEdges(src)) {
|
|
1937
|
+
const edge = graph.getEdgeAttributes(edgeId);
|
|
1938
|
+
if (edge.type !== EdgeType3.CONNECTS_TO || edge.provenance !== Provenance2.EXTRACTED) continue;
|
|
1939
|
+
if (!graph.hasNode(edge.target)) continue;
|
|
1940
|
+
const target = graph.getNodeAttributes(edge.target);
|
|
1941
|
+
if (target.type !== NodeType3.DatabaseNode || target.engine !== engine) continue;
|
|
1942
|
+
matches.add(edge.target);
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
return matches.size === 1 ? [...matches][0] : null;
|
|
1946
|
+
}
|
|
1926
1947
|
function ensureFrontierNode(graph, host, ts) {
|
|
1927
1948
|
const id = frontierIdFor(host);
|
|
1928
1949
|
if (graph.hasNode(id)) {
|
|
@@ -1943,6 +1964,7 @@ function ensureFrontierNode(graph, host, ts) {
|
|
|
1943
1964
|
}
|
|
1944
1965
|
function upsertObservedEdge(graph, type, source, target, ts, isError = false, evidence) {
|
|
1945
1966
|
if (!graph.hasNode(source) || !graph.hasNode(target)) return null;
|
|
1967
|
+
const grain = source.startsWith("file:") ? "file" : "service";
|
|
1946
1968
|
const id = makeObservedEdgeId(type, source, target);
|
|
1947
1969
|
if (graph.hasEdge(id)) {
|
|
1948
1970
|
const existing = graph.getEdgeAttributes(id);
|
|
@@ -1959,7 +1981,9 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
|
|
|
1959
1981
|
lastObserved: ts,
|
|
1960
1982
|
callCount: newSpanCount,
|
|
1961
1983
|
signal: newSignal,
|
|
1962
|
-
confidence: confidenceForObservedSignal(newSignal)
|
|
1984
|
+
confidence: confidenceForObservedSignal(newSignal),
|
|
1985
|
+
grain
|
|
1986
|
+
// backfills legacy edges that predate ADR-142
|
|
1963
1987
|
};
|
|
1964
1988
|
graph.replaceEdgeAttributes(id, updated);
|
|
1965
1989
|
return { edge: updated, created: false };
|
|
@@ -1979,6 +2003,7 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
|
|
|
1979
2003
|
lastObserved: ts,
|
|
1980
2004
|
callCount: 1,
|
|
1981
2005
|
signal,
|
|
2006
|
+
grain,
|
|
1982
2007
|
// Call-site evidence from span code.* semconv (file-awareness.md §4 + §6).
|
|
1983
2008
|
// Only set when code.filepath was present on the span — never fabricated.
|
|
1984
2009
|
...evidence ? { evidence } : {}
|
|
@@ -2181,13 +2206,18 @@ async function handleSpan(ctx, span) {
|
|
|
2181
2206
|
ensureDatabaseNode(ctx.graph, host, span.dbSystem);
|
|
2182
2207
|
targetId = databaseId(host);
|
|
2183
2208
|
} else {
|
|
2184
|
-
const
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
localName
|
|
2189
|
-
|
|
2190
|
-
|
|
2209
|
+
const declared = findDeclaredDatabaseForService(ctx.graph, sourceId, span.dbSystem);
|
|
2210
|
+
if (declared) {
|
|
2211
|
+
targetId = declared;
|
|
2212
|
+
} else {
|
|
2213
|
+
const localName = span.dbName ?? span.dbSystem;
|
|
2214
|
+
targetId = ensureLocalDatabaseNode(
|
|
2215
|
+
ctx.graph,
|
|
2216
|
+
span.service,
|
|
2217
|
+
localName,
|
|
2218
|
+
span.dbSystem
|
|
2219
|
+
);
|
|
2220
|
+
}
|
|
2191
2221
|
}
|
|
2192
2222
|
const result = upsertObservedEdge(
|
|
2193
2223
|
ctx.graph,
|
|
@@ -2371,29 +2401,29 @@ function promoteFrontierNodes(graph, opts = {}) {
|
|
|
2371
2401
|
toPromote.push({ frontierId: id, serviceId: target });
|
|
2372
2402
|
});
|
|
2373
2403
|
let promoted = 0;
|
|
2374
|
-
for (const { frontierId: frontierId2, serviceId:
|
|
2404
|
+
for (const { frontierId: frontierId2, serviceId: serviceId5 } of toPromote) {
|
|
2375
2405
|
if (opts.policies && opts.policies.length > 0 && opts.policyCtx) {
|
|
2376
2406
|
const gate = canPromoteFrontier(graph, frontierId2, opts.policies, opts.policyCtx);
|
|
2377
2407
|
if (!gate.allowed) {
|
|
2378
2408
|
continue;
|
|
2379
2409
|
}
|
|
2380
2410
|
}
|
|
2381
|
-
rewireFrontierEdges(graph, frontierId2,
|
|
2411
|
+
rewireFrontierEdges(graph, frontierId2, serviceId5);
|
|
2382
2412
|
graph.dropNode(frontierId2);
|
|
2383
2413
|
promoted++;
|
|
2384
2414
|
}
|
|
2385
2415
|
return promoted;
|
|
2386
2416
|
}
|
|
2387
|
-
function rewireFrontierEdges(graph, frontierId2,
|
|
2417
|
+
function rewireFrontierEdges(graph, frontierId2, serviceId5) {
|
|
2388
2418
|
const inbound = [...graph.inboundEdges(frontierId2)];
|
|
2389
2419
|
const outbound = [...graph.outboundEdges(frontierId2)];
|
|
2390
2420
|
for (const edgeId of inbound) {
|
|
2391
2421
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
2392
|
-
rebuildEdge(graph, edge, edge.source,
|
|
2422
|
+
rebuildEdge(graph, edge, edge.source, serviceId5, edgeId);
|
|
2393
2423
|
}
|
|
2394
2424
|
for (const edgeId of outbound) {
|
|
2395
2425
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
2396
|
-
rebuildEdge(graph, edge,
|
|
2426
|
+
rebuildEdge(graph, edge, serviceId5, edge.target, edgeId);
|
|
2397
2427
|
}
|
|
2398
2428
|
}
|
|
2399
2429
|
function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
|
|
@@ -3195,9 +3225,9 @@ var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
|
3195
3225
|
"StatefulSet",
|
|
3196
3226
|
"DaemonSet"
|
|
3197
3227
|
]);
|
|
3198
|
-
function addAliases(graph,
|
|
3199
|
-
if (!graph.hasNode(
|
|
3200
|
-
const node = graph.getNodeAttributes(
|
|
3228
|
+
function addAliases(graph, serviceId5, candidates) {
|
|
3229
|
+
if (!graph.hasNode(serviceId5)) return;
|
|
3230
|
+
const node = graph.getNodeAttributes(serviceId5);
|
|
3201
3231
|
if (node.type !== NodeType5.ServiceNode) return;
|
|
3202
3232
|
const set = new Set(node.aliases ?? []);
|
|
3203
3233
|
for (const c of candidates) {
|
|
@@ -3207,7 +3237,7 @@ function addAliases(graph, serviceId4, candidates) {
|
|
|
3207
3237
|
}
|
|
3208
3238
|
if (set.size === 0) return;
|
|
3209
3239
|
const updated = { ...node, aliases: [...set].sort() };
|
|
3210
|
-
graph.replaceNodeAttributes(
|
|
3240
|
+
graph.replaceNodeAttributes(serviceId5, updated);
|
|
3211
3241
|
}
|
|
3212
3242
|
function indexServicesByName(services) {
|
|
3213
3243
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -3240,12 +3270,12 @@ async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
|
3240
3270
|
}
|
|
3241
3271
|
if (!compose?.services) return;
|
|
3242
3272
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
3243
|
-
const
|
|
3244
|
-
if (!
|
|
3273
|
+
const serviceId5 = serviceIndex.get(composeName);
|
|
3274
|
+
if (!serviceId5) continue;
|
|
3245
3275
|
const aliases = /* @__PURE__ */ new Set([composeName]);
|
|
3246
3276
|
if (svc.container_name) aliases.add(svc.container_name);
|
|
3247
3277
|
if (svc.hostname) aliases.add(svc.hostname);
|
|
3248
|
-
addAliases(graph,
|
|
3278
|
+
addAliases(graph, serviceId5, aliases);
|
|
3249
3279
|
}
|
|
3250
3280
|
}
|
|
3251
3281
|
var LABEL_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -3906,6 +3936,29 @@ async function readIfExists(filePath) {
|
|
|
3906
3936
|
return null;
|
|
3907
3937
|
}
|
|
3908
3938
|
}
|
|
3939
|
+
async function resolveEnvVar(serviceDir, name) {
|
|
3940
|
+
const entries = await fs12.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
3941
|
+
const envNames = entries.filter((e) => e.isFile() && (e.name === ".env" || e.name.startsWith(".env."))).map((e) => e.name);
|
|
3942
|
+
const rank = (n) => n === ".env.local" ? 0 : n === ".env" ? 1 : 2;
|
|
3943
|
+
envNames.sort((a, b) => rank(a) - rank(b) || a.localeCompare(b));
|
|
3944
|
+
for (const fileName of envNames) {
|
|
3945
|
+
const content = await readIfExists(path14.join(serviceDir, fileName));
|
|
3946
|
+
if (!content) continue;
|
|
3947
|
+
for (const line of content.split("\n")) {
|
|
3948
|
+
const trimmed = line.trim();
|
|
3949
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
3950
|
+
const eq = trimmed.indexOf("=");
|
|
3951
|
+
if (eq < 0) continue;
|
|
3952
|
+
if (trimmed.slice(0, eq).trim() !== name) continue;
|
|
3953
|
+
let value = trimmed.slice(eq + 1).trim();
|
|
3954
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
3955
|
+
value = value.slice(1, -1);
|
|
3956
|
+
}
|
|
3957
|
+
return value || null;
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
return null;
|
|
3961
|
+
}
|
|
3909
3962
|
async function findFirst(serviceDir, candidates) {
|
|
3910
3963
|
for (const rel of candidates) {
|
|
3911
3964
|
const abs = path14.join(serviceDir, rel);
|
|
@@ -4002,6 +4055,14 @@ async function parse3(serviceDir) {
|
|
|
4002
4055
|
const config = parseConnectionString(urlMatch[1]);
|
|
4003
4056
|
if (config) return [{ ...config, sourceFile: schemaPath }];
|
|
4004
4057
|
}
|
|
4058
|
+
const envMatch = body.match(/url\s*=\s*env\(\s*"([^"]+)"\s*\)/);
|
|
4059
|
+
if (envMatch) {
|
|
4060
|
+
const resolved = await resolveEnvVar(serviceDir, envMatch[1]);
|
|
4061
|
+
if (resolved) {
|
|
4062
|
+
const config = parseConnectionString(resolved);
|
|
4063
|
+
if (config) return [{ ...config, sourceFile: schemaPath }];
|
|
4064
|
+
}
|
|
4065
|
+
}
|
|
4005
4066
|
return [
|
|
4006
4067
|
{
|
|
4007
4068
|
host: `${engine}-prisma`,
|
|
@@ -4044,6 +4105,15 @@ async function parse4(serviceDir) {
|
|
|
4044
4105
|
const config = parseConnectionString(urlMatch[1]);
|
|
4045
4106
|
if (config) return [{ ...config, sourceFile: filePath }];
|
|
4046
4107
|
}
|
|
4108
|
+
const urlEnvMatch = content.match(
|
|
4109
|
+
/(?:url|connectionString)\s*:\s*process\.env(?:\.([A-Za-z_$][\w$]*)|\[\s*['"]([^'"]+)['"]\s*\])/
|
|
4110
|
+
);
|
|
4111
|
+
if (urlEnvMatch) {
|
|
4112
|
+
const varName = urlEnvMatch[1] ?? urlEnvMatch[2];
|
|
4113
|
+
const resolved = varName ? await resolveEnvVar(serviceDir, varName) : null;
|
|
4114
|
+
const config = resolved ? parseConnectionString(resolved) : null;
|
|
4115
|
+
if (config) return [{ ...config, sourceFile: filePath }];
|
|
4116
|
+
}
|
|
4047
4117
|
const hostMatch = content.match(/host\s*:\s*['"`]([^'"`]+)['"`]/);
|
|
4048
4118
|
if (hostMatch) {
|
|
4049
4119
|
const portMatch = content.match(/port\s*:\s*(\d+)/);
|
|
@@ -4096,6 +4166,15 @@ async function parse5(serviceDir) {
|
|
|
4096
4166
|
const config = parseConnectionString(urlMatch[1]);
|
|
4097
4167
|
if (config) return [{ ...config, sourceFile: filePath }];
|
|
4098
4168
|
}
|
|
4169
|
+
const urlEnvMatch = content.match(
|
|
4170
|
+
/connection\s*:\s*process\.env(?:\.([A-Za-z_$][\w$]*)|\[\s*['"]([^'"]+)['"]\s*\])/
|
|
4171
|
+
);
|
|
4172
|
+
if (urlEnvMatch) {
|
|
4173
|
+
const varName = urlEnvMatch[1] ?? urlEnvMatch[2];
|
|
4174
|
+
const resolved = varName ? await resolveEnvVar(serviceDir, varName) : null;
|
|
4175
|
+
const config = resolved ? parseConnectionString(resolved) : null;
|
|
4176
|
+
if (config) return [{ ...config, sourceFile: filePath }];
|
|
4177
|
+
}
|
|
4099
4178
|
const host = content.match(/host\s*:\s*['"`]([^'"`]+)['"`]/)?.[1];
|
|
4100
4179
|
if (host) {
|
|
4101
4180
|
const port = content.match(/port\s*:\s*(\d+)/)?.[1];
|
|
@@ -5667,6 +5746,16 @@ function constructorMatchesImport(name, ctx) {
|
|
|
5667
5746
|
if (name === "createClient") return ctx.hasSupabaseJs;
|
|
5668
5747
|
return ctx.hasSupabaseSsr;
|
|
5669
5748
|
}
|
|
5749
|
+
var SUPABASE_CLIENT_ASSIGN_RE = /(?:const|let|var)\s+(\w+)\s*=\s*(?:await\s+)?(createClient|createServerClient|createBrowserClient)\s*\(/g;
|
|
5750
|
+
function supabaseClientVars(content, ctx) {
|
|
5751
|
+
const vars = /* @__PURE__ */ new Set();
|
|
5752
|
+
SUPABASE_CLIENT_ASSIGN_RE.lastIndex = 0;
|
|
5753
|
+
let m;
|
|
5754
|
+
while ((m = SUPABASE_CLIENT_ASSIGN_RE.exec(content)) !== null) {
|
|
5755
|
+
if (constructorMatchesImport(m[2], ctx)) vars.add(m[1]);
|
|
5756
|
+
}
|
|
5757
|
+
return vars;
|
|
5758
|
+
}
|
|
5670
5759
|
function supabaseEndpointsFromFile(file, serviceDir) {
|
|
5671
5760
|
const ctx = readImports2(file.content);
|
|
5672
5761
|
if (!ctx.hasSupabaseJs && !ctx.hasSupabaseSsr) return [];
|
|
@@ -5699,6 +5788,34 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
5699
5788
|
}
|
|
5700
5789
|
});
|
|
5701
5790
|
}
|
|
5791
|
+
const clientVars = supabaseClientVars(file.content, ctx);
|
|
5792
|
+
for (const clientVar of clientVars) {
|
|
5793
|
+
const accessRe = new RegExp(
|
|
5794
|
+
`\\b${clientVar}\\s*\\.\\s*(from|rpc)\\s*\\(\\s*['"\`]([\\w.-]+)['"\`]`,
|
|
5795
|
+
"g"
|
|
5796
|
+
);
|
|
5797
|
+
let am;
|
|
5798
|
+
while ((am = accessRe.exec(file.content)) !== null) {
|
|
5799
|
+
const kind = am[1] === "rpc" ? "supabase-rpc" : "supabase-table";
|
|
5800
|
+
const resource = am[2];
|
|
5801
|
+
const key = `${kind}/${resource}`;
|
|
5802
|
+
if (seen.has(key)) continue;
|
|
5803
|
+
seen.add(key);
|
|
5804
|
+
const line = lineOf(file.content, am[0]);
|
|
5805
|
+
out.push({
|
|
5806
|
+
infraId: infraId6(kind, resource),
|
|
5807
|
+
name: resource,
|
|
5808
|
+
kind,
|
|
5809
|
+
edgeType: "CALLS",
|
|
5810
|
+
confidenceKind: "verified-call-site",
|
|
5811
|
+
evidence: {
|
|
5812
|
+
file: path30.relative(serviceDir, file.path),
|
|
5813
|
+
line,
|
|
5814
|
+
snippet: snippet(file.content, line)
|
|
5815
|
+
}
|
|
5816
|
+
});
|
|
5817
|
+
}
|
|
5818
|
+
}
|
|
5702
5819
|
return out;
|
|
5703
5820
|
}
|
|
5704
5821
|
|
|
@@ -6768,19 +6885,30 @@ import {
|
|
|
6768
6885
|
EdgeType as EdgeType20,
|
|
6769
6886
|
NodeType as NodeType15,
|
|
6770
6887
|
parseEdgeId,
|
|
6771
|
-
|
|
6888
|
+
parseFileId,
|
|
6889
|
+
Provenance as Provenance18,
|
|
6890
|
+
serviceId as serviceId4
|
|
6772
6891
|
} from "@neat.is/types";
|
|
6773
6892
|
function bucketKey(source, target, type) {
|
|
6774
6893
|
return `${type}|${source}|${target}`;
|
|
6775
6894
|
}
|
|
6895
|
+
function bucketSourceFor(graph, edge) {
|
|
6896
|
+
if (edge.type !== EdgeType20.CONNECTS_TO) return edge.source;
|
|
6897
|
+
const parsed = parseFileId(edge.source);
|
|
6898
|
+
if (!parsed || !graph.hasNode(edge.target)) return edge.source;
|
|
6899
|
+
const target = graph.getNodeAttributes(edge.target);
|
|
6900
|
+
if (target.type !== NodeType15.DatabaseNode) return edge.source;
|
|
6901
|
+
return serviceId4(parsed.service);
|
|
6902
|
+
}
|
|
6776
6903
|
function bucketEdges(graph) {
|
|
6777
6904
|
const buckets = /* @__PURE__ */ new Map();
|
|
6778
6905
|
graph.forEachEdge((id, attrs) => {
|
|
6779
6906
|
const e = attrs;
|
|
6780
6907
|
const parsed = parseEdgeId(id);
|
|
6781
6908
|
const provenance = parsed?.provenance ?? e.provenance;
|
|
6782
|
-
const
|
|
6783
|
-
const
|
|
6909
|
+
const source = bucketSourceFor(graph, e);
|
|
6910
|
+
const key = bucketKey(source, e.target, e.type);
|
|
6911
|
+
const cur = buckets.get(key) ?? { source, target: e.target, type: e.type };
|
|
6784
6912
|
switch (provenance) {
|
|
6785
6913
|
case Provenance18.EXTRACTED:
|
|
6786
6914
|
cur.extracted = e;
|
|
@@ -9233,4 +9361,4 @@ export {
|
|
|
9233
9361
|
recordConnectorPoll,
|
|
9234
9362
|
buildApi
|
|
9235
9363
|
};
|
|
9236
|
-
//# sourceMappingURL=chunk-
|
|
9364
|
+
//# sourceMappingURL=chunk-BI3XKGVG.js.map
|