@neat.is/core 0.9.5 → 0.9.6
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-DGAI4VOE.js → chunk-XOGTJVUM.js} +131 -20
- package/dist/chunk-XOGTJVUM.js.map +1 -0
- package/dist/{chunk-4SLKQNG7.js → chunk-XYAZOGEX.js} +2 -2
- package/dist/cli.cjs +130 -19
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +130 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -6
- package/dist/index.d.ts +2 -6
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +130 -19
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +130 -19
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-DGAI4VOE.js.map +0 -1
- /package/dist/{chunk-4SLKQNG7.js.map → chunk-XYAZOGEX.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MultiDirectedGraph } from 'graphology';
|
|
2
|
-
import { GraphNode, GraphEdge, SpanAttributes, EdgeTypeValue, StaleEvent, ErrorEvent, BlastRadiusResult, RootCauseResult, RegistryEntry, RegistryStatus, RegistryFile } from '@neat.is/types';
|
|
2
|
+
import { GraphNode, GraphEdge, EdgeEvidence, SpanAttributes, EdgeTypeValue, StaleEvent, ErrorEvent, BlastRadiusResult, RootCauseResult, RegistryEntry, RegistryStatus, RegistryFile } from '@neat.is/types';
|
|
3
3
|
export { StaleEvent } from '@neat.is/types';
|
|
4
4
|
import { FastifyInstance } from 'fastify';
|
|
5
5
|
|
|
@@ -21,11 +21,7 @@ interface DroppedExtractedEdge {
|
|
|
21
21
|
type: string;
|
|
22
22
|
confidence: number;
|
|
23
23
|
confidenceKind: string;
|
|
24
|
-
evidence:
|
|
25
|
-
file: string;
|
|
26
|
-
line?: number;
|
|
27
|
-
snippet?: string;
|
|
28
|
-
};
|
|
24
|
+
evidence: EdgeEvidence;
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
interface ExtractResult {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MultiDirectedGraph } from 'graphology';
|
|
2
|
-
import { GraphNode, GraphEdge, SpanAttributes, EdgeTypeValue, StaleEvent, ErrorEvent, BlastRadiusResult, RootCauseResult, RegistryEntry, RegistryStatus, RegistryFile } from '@neat.is/types';
|
|
2
|
+
import { GraphNode, GraphEdge, EdgeEvidence, SpanAttributes, EdgeTypeValue, StaleEvent, ErrorEvent, BlastRadiusResult, RootCauseResult, RegistryEntry, RegistryStatus, RegistryFile } from '@neat.is/types';
|
|
3
3
|
export { StaleEvent } from '@neat.is/types';
|
|
4
4
|
import { FastifyInstance } from 'fastify';
|
|
5
5
|
|
|
@@ -21,11 +21,7 @@ interface DroppedExtractedEdge {
|
|
|
21
21
|
type: string;
|
|
22
22
|
confidence: number;
|
|
23
23
|
confidenceKind: string;
|
|
24
|
-
evidence:
|
|
25
|
-
file: string;
|
|
26
|
-
line?: number;
|
|
27
|
-
snippet?: string;
|
|
28
|
-
};
|
|
24
|
+
evidence: EdgeEvidence;
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
interface ExtractResult {
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
routeSpanToProject,
|
|
3
3
|
startDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XYAZOGEX.js";
|
|
5
5
|
import {
|
|
6
6
|
ProjectNameCollisionError,
|
|
7
7
|
addProject,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
thresholdForEdgeType,
|
|
38
38
|
touchLastSeen,
|
|
39
39
|
writeAtomically
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-XOGTJVUM.js";
|
|
41
41
|
import {
|
|
42
42
|
startOtelGrpcReceiver
|
|
43
43
|
} from "./chunk-ERE47MCR.js";
|
package/dist/neatd.cjs
CHANGED
|
@@ -10722,27 +10722,72 @@ function walk2(node, visit) {
|
|
|
10722
10722
|
if (child) walk2(child, visit);
|
|
10723
10723
|
}
|
|
10724
10724
|
}
|
|
10725
|
-
function
|
|
10726
|
-
if (node
|
|
10725
|
+
function resolveStaticString(node, constMap, depth = 0) {
|
|
10726
|
+
if (!node || depth > 4) return null;
|
|
10727
|
+
if (node.type === "string") return stringText(node);
|
|
10728
|
+
if (node.type === "template_string") {
|
|
10729
|
+
let out = "";
|
|
10730
|
+
let sawSub = false;
|
|
10727
10731
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
10728
10732
|
const child = node.namedChild(i);
|
|
10729
|
-
if (child
|
|
10733
|
+
if (!child) continue;
|
|
10734
|
+
if (child.type === "string_fragment") out += child.text;
|
|
10735
|
+
else if (child.type === "template_substitution") sawSub = true;
|
|
10730
10736
|
}
|
|
10731
|
-
return
|
|
10737
|
+
return sawSub ? null : out;
|
|
10738
|
+
}
|
|
10739
|
+
if (node.type === "identifier") return constMap.get(node.text) ?? null;
|
|
10740
|
+
if (node.type === "binary_expression") {
|
|
10741
|
+
const left = resolveStaticString(node.childForFieldName("left"), constMap, depth + 1);
|
|
10742
|
+
if (left !== null) return left;
|
|
10743
|
+
return resolveStaticString(node.childForFieldName("right"), constMap, depth + 1);
|
|
10744
|
+
}
|
|
10745
|
+
if (node.type === "parenthesized_expression") {
|
|
10746
|
+
return resolveStaticString(node.namedChild(0), constMap, depth + 1);
|
|
10747
|
+
}
|
|
10748
|
+
return null;
|
|
10749
|
+
}
|
|
10750
|
+
function collectStaticStringBindings(root) {
|
|
10751
|
+
const map = /* @__PURE__ */ new Map();
|
|
10752
|
+
walk2(root, (node) => {
|
|
10753
|
+
if (node.type !== "variable_declarator") return;
|
|
10754
|
+
const name = node.childForFieldName("name");
|
|
10755
|
+
if (!name || name.type !== "identifier") return;
|
|
10756
|
+
const resolved = resolveStaticString(node.childForFieldName("value"), map);
|
|
10757
|
+
if (resolved !== null) map.set(name.text, resolved);
|
|
10758
|
+
});
|
|
10759
|
+
return map;
|
|
10760
|
+
}
|
|
10761
|
+
function reconstructUrl(node, constMap) {
|
|
10762
|
+
if (node.type === "string") {
|
|
10763
|
+
const s = stringText(node);
|
|
10764
|
+
return s === null ? null : { url: s, approximate: false };
|
|
10732
10765
|
}
|
|
10733
10766
|
if (node.type === "template_string") {
|
|
10734
10767
|
let out = "";
|
|
10768
|
+
let approximate = false;
|
|
10769
|
+
let sawPart = false;
|
|
10735
10770
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
10736
10771
|
const child = node.namedChild(i);
|
|
10737
10772
|
if (!child) continue;
|
|
10738
|
-
if (child.type === "string_fragment")
|
|
10739
|
-
|
|
10773
|
+
if (child.type === "string_fragment") {
|
|
10774
|
+
out += child.text;
|
|
10775
|
+
sawPart = true;
|
|
10776
|
+
} else if (child.type === "template_substitution") {
|
|
10777
|
+
sawPart = true;
|
|
10778
|
+
const resolved = resolveStaticString(child.namedChild(0), constMap);
|
|
10779
|
+
if (resolved !== null) out += resolved;
|
|
10780
|
+
else {
|
|
10781
|
+
out += ":param";
|
|
10782
|
+
approximate = true;
|
|
10783
|
+
}
|
|
10784
|
+
}
|
|
10740
10785
|
}
|
|
10741
|
-
if (
|
|
10786
|
+
if (!sawPart) {
|
|
10742
10787
|
const raw = node.text;
|
|
10743
|
-
return raw.length >= 2 ? raw.slice(1, -1) : "";
|
|
10788
|
+
return { url: raw.length >= 2 ? raw.slice(1, -1) : "", approximate: false };
|
|
10744
10789
|
}
|
|
10745
|
-
return out;
|
|
10790
|
+
return { url: out, approximate };
|
|
10746
10791
|
}
|
|
10747
10792
|
return null;
|
|
10748
10793
|
}
|
|
@@ -10796,23 +10841,57 @@ function matchHost(urlStr, knownHosts) {
|
|
|
10796
10841
|
}
|
|
10797
10842
|
return null;
|
|
10798
10843
|
}
|
|
10844
|
+
function hostSlotUnresolved(url) {
|
|
10845
|
+
const schemeRel = url.indexOf("//");
|
|
10846
|
+
let authority;
|
|
10847
|
+
if (schemeRel >= 0) {
|
|
10848
|
+
const rest = url.slice(schemeRel + 2);
|
|
10849
|
+
const slash = rest.indexOf("/");
|
|
10850
|
+
authority = slash >= 0 ? rest.slice(0, slash) : rest;
|
|
10851
|
+
} else {
|
|
10852
|
+
const slash = url.indexOf("/");
|
|
10853
|
+
authority = slash >= 0 ? url.slice(0, slash) : url;
|
|
10854
|
+
}
|
|
10855
|
+
return authority.length === 0 || authority.includes(":param");
|
|
10856
|
+
}
|
|
10857
|
+
function pathHasLiteralAnchor(pathTemplate) {
|
|
10858
|
+
const segs = normalizePathTemplate(pathTemplate).split("/").filter((s) => s.length > 0);
|
|
10859
|
+
if (segs.length === 0) return false;
|
|
10860
|
+
return segs.some((s) => s !== ":param");
|
|
10861
|
+
}
|
|
10799
10862
|
function clientCallSitesFromSource(source, parser, knownHosts) {
|
|
10800
10863
|
const tree = parseSource5(parser, source);
|
|
10801
10864
|
const out = [];
|
|
10865
|
+
const constMap = collectStaticStringBindings(tree.rootNode);
|
|
10802
10866
|
const push = (urlNode, method, callNode) => {
|
|
10803
|
-
const
|
|
10804
|
-
if (!
|
|
10805
|
-
const host = matchHost(urlStr, knownHosts);
|
|
10806
|
-
if (!host) return;
|
|
10807
|
-
const p = pathOf(urlStr);
|
|
10808
|
-
if (p === null) return;
|
|
10867
|
+
const rec = reconstructUrl(urlNode, constMap);
|
|
10868
|
+
if (!rec) return;
|
|
10809
10869
|
const line = callNode.startPosition.row + 1;
|
|
10870
|
+
const host = matchHost(rec.url, knownHosts);
|
|
10871
|
+
if (host === null) {
|
|
10872
|
+
if (rec.approximate && hostSlotUnresolved(rec.url)) {
|
|
10873
|
+
out.push({
|
|
10874
|
+
host: null,
|
|
10875
|
+
method,
|
|
10876
|
+
pathTemplate: "",
|
|
10877
|
+
line,
|
|
10878
|
+
snippet: snippet(source, line),
|
|
10879
|
+
approximate: true,
|
|
10880
|
+
reason: "base URL interpolation could not be resolved statically"
|
|
10881
|
+
});
|
|
10882
|
+
}
|
|
10883
|
+
return;
|
|
10884
|
+
}
|
|
10885
|
+
const p = pathOf(rec.url);
|
|
10886
|
+
if (p === null) return;
|
|
10810
10887
|
out.push({
|
|
10811
10888
|
host,
|
|
10812
10889
|
method,
|
|
10813
10890
|
pathTemplate: p,
|
|
10814
10891
|
line,
|
|
10815
|
-
snippet: snippet(source, line)
|
|
10892
|
+
snippet: snippet(source, line),
|
|
10893
|
+
approximate: rec.approximate,
|
|
10894
|
+
reason: rec.approximate ? "path segment interpolation could not be resolved statically" : void 0
|
|
10816
10895
|
});
|
|
10817
10896
|
};
|
|
10818
10897
|
walk2(tree.rootNode, (node) => {
|
|
@@ -10908,6 +10987,35 @@ async function addRouteCallEdges(graph, services) {
|
|
|
10908
10987
|
if (sites.length === 0) continue;
|
|
10909
10988
|
const relFile = toPosix(import_node_path38.default.relative(service.dir, file.path));
|
|
10910
10989
|
for (const site of sites) {
|
|
10990
|
+
if (site.host === null) {
|
|
10991
|
+
const dedupKey2 = `${relFile}|unresolved-host`;
|
|
10992
|
+
if (seen.has(dedupKey2)) continue;
|
|
10993
|
+
seen.add(dedupKey2);
|
|
10994
|
+
const { fileNodeId: fileNodeId2, nodesAdded: n2, edgesAdded: e2 } = ensureFileNode(
|
|
10995
|
+
graph,
|
|
10996
|
+
service.pkg.name,
|
|
10997
|
+
service.node.id,
|
|
10998
|
+
relFile
|
|
10999
|
+
);
|
|
11000
|
+
nodesAdded += n2;
|
|
11001
|
+
edgesAdded += e2;
|
|
11002
|
+
noteExtractedDropped({
|
|
11003
|
+
source: fileNodeId2,
|
|
11004
|
+
target: "route:unresolved",
|
|
11005
|
+
type: import_types27.EdgeType.CALLS,
|
|
11006
|
+
confidence: (0, import_types27.confidenceForExtracted)("reconstructed-approximate"),
|
|
11007
|
+
confidenceKind: "reconstructed-approximate",
|
|
11008
|
+
evidence: {
|
|
11009
|
+
file: relFile,
|
|
11010
|
+
line: site.line,
|
|
11011
|
+
snippet: site.snippet,
|
|
11012
|
+
method: site.method,
|
|
11013
|
+
approximate: true,
|
|
11014
|
+
reason: site.reason
|
|
11015
|
+
}
|
|
11016
|
+
});
|
|
11017
|
+
continue;
|
|
11018
|
+
}
|
|
10911
11019
|
const serverServiceId = hostToNodeId.get(site.host);
|
|
10912
11020
|
if (!serverServiceId || serverServiceId === service.node.id) continue;
|
|
10913
11021
|
const entries = routeIndex.get(serverServiceId);
|
|
@@ -10926,13 +11034,16 @@ async function addRouteCallEdges(graph, services) {
|
|
|
10926
11034
|
);
|
|
10927
11035
|
nodesAdded += n;
|
|
10928
11036
|
edgesAdded += e;
|
|
10929
|
-
const
|
|
11037
|
+
const anchored = pathHasLiteralAnchor(site.pathTemplate);
|
|
11038
|
+
const confidenceKind = site.approximate && !anchored ? "reconstructed-approximate" : "verified-call-site";
|
|
11039
|
+
const confidence = (0, import_types27.confidenceForExtracted)(confidenceKind);
|
|
10930
11040
|
const ev = {
|
|
10931
11041
|
file: relFile,
|
|
10932
11042
|
line: site.line,
|
|
10933
11043
|
snippet: site.snippet,
|
|
10934
11044
|
method: site.method ?? match.method,
|
|
10935
|
-
pathTemplate: site.pathTemplate
|
|
11045
|
+
pathTemplate: site.pathTemplate,
|
|
11046
|
+
...confidenceKind === "reconstructed-approximate" ? { approximate: true, reason: site.reason } : {}
|
|
10936
11047
|
};
|
|
10937
11048
|
if (!(0, import_types27.passesExtractedFloor)(confidence)) {
|
|
10938
11049
|
noteExtractedDropped({
|
|
@@ -10940,7 +11051,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
10940
11051
|
target: match.routeNodeId,
|
|
10941
11052
|
type: import_types27.EdgeType.CALLS,
|
|
10942
11053
|
confidence,
|
|
10943
|
-
confidenceKind
|
|
11054
|
+
confidenceKind,
|
|
10944
11055
|
evidence: ev
|
|
10945
11056
|
});
|
|
10946
11057
|
continue;
|