@neat.is/core 0.10.6-dev.20261009 → 0.10.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-H2BAPN33.js → chunk-MW2XYLCS.js} +384 -181
- package/dist/chunk-MW2XYLCS.js.map +1 -0
- package/dist/{chunk-ECBRGTB2.js → chunk-OKM4N7GH.js} +227 -9
- package/dist/chunk-OKM4N7GH.js.map +1 -0
- package/dist/cli.cjs +946 -546
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +33 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +948 -525
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +948 -525
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +721 -570
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-ECBRGTB2.js.map +0 -1
- package/dist/chunk-H2BAPN33.js.map +0 -1
|
@@ -949,7 +949,7 @@ import {
|
|
|
949
949
|
EdgeType as EdgeType5,
|
|
950
950
|
GraphEdgeSchema,
|
|
951
951
|
GraphNodeSchema,
|
|
952
|
-
NodeType as
|
|
952
|
+
NodeType as NodeType5,
|
|
953
953
|
Provenance as Provenance5,
|
|
954
954
|
confidenceForObservedSignal,
|
|
955
955
|
databaseId,
|
|
@@ -3758,6 +3758,97 @@ async function addRoutes(graph, services) {
|
|
|
3758
3758
|
return { nodesAdded, edgesAdded };
|
|
3759
3759
|
}
|
|
3760
3760
|
|
|
3761
|
+
// src/extract/source-baseline.ts
|
|
3762
|
+
import { NodeType as NodeType4 } from "@neat.is/types";
|
|
3763
|
+
var states = /* @__PURE__ */ new WeakMap();
|
|
3764
|
+
var REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
3765
|
+
function validCommit(commit, repository) {
|
|
3766
|
+
return !!commit && commit.repository === repository && /^[0-9a-f]{40}$/.test(commit.sha);
|
|
3767
|
+
}
|
|
3768
|
+
function stateOf(graph) {
|
|
3769
|
+
let state = states.get(graph);
|
|
3770
|
+
if (!state) {
|
|
3771
|
+
state = { repos: /* @__PURE__ */ new Map(), active: /* @__PURE__ */ new Set(), conflicted: /* @__PURE__ */ new Set() };
|
|
3772
|
+
states.set(graph, state);
|
|
3773
|
+
}
|
|
3774
|
+
return state;
|
|
3775
|
+
}
|
|
3776
|
+
function setEntry(state, repository, baseline, generation = /* @__PURE__ */ Symbol()) {
|
|
3777
|
+
state.repos.set(repository, {
|
|
3778
|
+
baseline,
|
|
3779
|
+
generation,
|
|
3780
|
+
services: state.repos.get(repository)?.services ?? /* @__PURE__ */ new Set()
|
|
3781
|
+
});
|
|
3782
|
+
}
|
|
3783
|
+
function readSourceBaselines(graph) {
|
|
3784
|
+
const state = states.get(graph);
|
|
3785
|
+
if (!state) return [];
|
|
3786
|
+
return [...state.repos.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([, entry]) => ({ ...entry.baseline }));
|
|
3787
|
+
}
|
|
3788
|
+
function invalidateSourceBaseline(graph, repository, status = "unavailable") {
|
|
3789
|
+
if (repository !== void 0) {
|
|
3790
|
+
if (REPOSITORY.test(repository)) setEntry(stateOf(graph), repository, { status, repository });
|
|
3791
|
+
return;
|
|
3792
|
+
}
|
|
3793
|
+
const state = states.get(graph);
|
|
3794
|
+
if (!state) return;
|
|
3795
|
+
for (const generation of state.active) state.conflicted.add(generation);
|
|
3796
|
+
for (const name of state.repos.keys()) {
|
|
3797
|
+
setEntry(state, name, { status: "unavailable", repository: name });
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3800
|
+
function retainSourceBaselines(graph, repositories) {
|
|
3801
|
+
const state = states.get(graph);
|
|
3802
|
+
if (!state) return;
|
|
3803
|
+
const keep = new Set(repositories);
|
|
3804
|
+
for (const name of [...state.repos.keys()]) if (!keep.has(name)) state.repos.delete(name);
|
|
3805
|
+
}
|
|
3806
|
+
function beginSourceExtraction(graph, source, commit) {
|
|
3807
|
+
const generation = /* @__PURE__ */ Symbol();
|
|
3808
|
+
const state = stateOf(graph);
|
|
3809
|
+
if (source === void 0) {
|
|
3810
|
+
invalidateSourceBaseline(graph);
|
|
3811
|
+
state.active.add(generation);
|
|
3812
|
+
return generation;
|
|
3813
|
+
}
|
|
3814
|
+
state.active.add(generation);
|
|
3815
|
+
if (!REPOSITORY.test(source)) return generation;
|
|
3816
|
+
setEntry(
|
|
3817
|
+
state,
|
|
3818
|
+
source,
|
|
3819
|
+
validCommit(commit, source) ? { status: "syncing", repository: source } : { status: "unavailable", repository: source },
|
|
3820
|
+
generation
|
|
3821
|
+
);
|
|
3822
|
+
return generation;
|
|
3823
|
+
}
|
|
3824
|
+
function servicesOf(graph, repository) {
|
|
3825
|
+
const services = /* @__PURE__ */ new Set();
|
|
3826
|
+
graph.forEachNode((_id, attrs) => {
|
|
3827
|
+
const node = attrs;
|
|
3828
|
+
if (node.type === NodeType4.FileNode && node.source === repository && node.service) {
|
|
3829
|
+
services.add(node.service);
|
|
3830
|
+
}
|
|
3831
|
+
});
|
|
3832
|
+
return services;
|
|
3833
|
+
}
|
|
3834
|
+
function finishSourceExtraction(graph, generation, source, commit, result) {
|
|
3835
|
+
const state = states.get(graph);
|
|
3836
|
+
if (!state) return;
|
|
3837
|
+
state.active.delete(generation);
|
|
3838
|
+
const conflicted = state.conflicted.delete(generation);
|
|
3839
|
+
if (source === void 0 || !REPOSITORY.test(source)) return;
|
|
3840
|
+
const entry = state.repos.get(source);
|
|
3841
|
+
if (!entry || entry.generation !== generation) return;
|
|
3842
|
+
entry.services = servicesOf(graph, source);
|
|
3843
|
+
let shared = false;
|
|
3844
|
+
for (const [name, other] of state.repos) {
|
|
3845
|
+
if (name === source || ![...entry.services].some((s) => other.services.has(s))) continue;
|
|
3846
|
+
shared = true;
|
|
3847
|
+
setEntry(state, name, { status: "unavailable", repository: name }, other.generation);
|
|
3848
|
+
}
|
|
3849
|
+
entry.baseline = !conflicted && !shared && validCommit(commit, source) && result.extractionErrors === 0 && result.skippedFiles === 0 ? { status: "ready", repository: source, sha: commit.sha } : { status: "unavailable", repository: source };
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3761
3852
|
// src/columns.ts
|
|
3762
3853
|
import { Provenance as Provenance4 } from "@neat.is/types";
|
|
3763
3854
|
var OBSERVED_COLUMN_CONFIDENCE = 0.9;
|
|
@@ -4271,7 +4362,7 @@ function reconcileObservedRelPath(graph, serviceName, relPath) {
|
|
|
4271
4362
|
let best = null;
|
|
4272
4363
|
graph.forEachNode((_id, attrs) => {
|
|
4273
4364
|
const a = attrs;
|
|
4274
|
-
if (a.type !==
|
|
4365
|
+
if (a.type !== NodeType5.FileNode || a.service !== serviceName) return;
|
|
4275
4366
|
if (a.discoveredVia === "otel") return;
|
|
4276
4367
|
const p = a.path;
|
|
4277
4368
|
if (!p) return;
|
|
@@ -4283,14 +4374,14 @@ function reconcileObservedRelPath(graph, serviceName, relPath) {
|
|
|
4283
4374
|
}
|
|
4284
4375
|
function ensureObservedFileNode(graph, serviceName, serviceNodeId, callSite) {
|
|
4285
4376
|
const svcAttrs = graph.hasNode(serviceNodeId) ? graph.getNodeAttributes(serviceNodeId) : void 0;
|
|
4286
|
-
const canonicalService = svcAttrs && svcAttrs.type ===
|
|
4377
|
+
const canonicalService = svcAttrs && svcAttrs.type === NodeType5.ServiceNode && typeof svcAttrs.name === "string" ? svcAttrs.name : serviceName;
|
|
4287
4378
|
const relPath = reconcileObservedRelPath(graph, canonicalService, callSite.relPath);
|
|
4288
4379
|
const fileNodeId = fileId3(canonicalService, relPath);
|
|
4289
4380
|
if (!graph.hasNode(fileNodeId)) {
|
|
4290
4381
|
const language = languageForExt(relPath);
|
|
4291
4382
|
const node = {
|
|
4292
4383
|
id: fileNodeId,
|
|
4293
|
-
type:
|
|
4384
|
+
type: NodeType5.FileNode,
|
|
4294
4385
|
service: canonicalService,
|
|
4295
4386
|
path: relPath,
|
|
4296
4387
|
...language ? { language } : {},
|
|
@@ -4334,7 +4425,7 @@ function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line)
|
|
|
4334
4425
|
if (!graph.hasNode(sid)) {
|
|
4335
4426
|
const node = {
|
|
4336
4427
|
id: sid,
|
|
4337
|
-
type:
|
|
4428
|
+
type: NodeType5.SymbolNode,
|
|
4338
4429
|
kind: "function",
|
|
4339
4430
|
qualname: fn,
|
|
4340
4431
|
span: { startLine: line, endLine: line },
|
|
@@ -4365,7 +4456,7 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint
|
|
|
4365
4456
|
graph.forEachOutboundEdge(fileNodeId, (_edge, edgeAttrs, _source, target) => {
|
|
4366
4457
|
if (edgeAttrs.type !== EdgeType5.CONTAINS) return;
|
|
4367
4458
|
const t = graph.getNodeAttributes(target);
|
|
4368
|
-
if (t.type !==
|
|
4459
|
+
if (t.type !== NodeType5.SymbolNode) return;
|
|
4369
4460
|
sawSymbol = true;
|
|
4370
4461
|
if (line >= t.span.startLine && line <= t.span.endLine) {
|
|
4371
4462
|
candidates.push({ id: target, symbol: t });
|
|
@@ -4408,7 +4499,7 @@ function ensureGraphqlOperationNode(graph, serviceName, operationType, operation
|
|
|
4408
4499
|
if (graph.hasNode(id)) return id;
|
|
4409
4500
|
const node = {
|
|
4410
4501
|
id,
|
|
4411
|
-
type:
|
|
4502
|
+
type: NodeType5.GraphQLOperationNode,
|
|
4412
4503
|
name: operationName,
|
|
4413
4504
|
service: serviceName,
|
|
4414
4505
|
operationType: operationType.toLowerCase(),
|
|
@@ -4426,7 +4517,7 @@ function ensureGrpcMethodNode(graph, rpcService, rpcMethod) {
|
|
|
4426
4517
|
if (graph.hasNode(id)) return id;
|
|
4427
4518
|
const node = {
|
|
4428
4519
|
id,
|
|
4429
|
-
type:
|
|
4520
|
+
type: NodeType5.GrpcMethodNode,
|
|
4430
4521
|
name: `${rpcService}/${rpcMethod}`,
|
|
4431
4522
|
rpcService,
|
|
4432
4523
|
rpcMethod,
|
|
@@ -4443,7 +4534,7 @@ function ensureWebsocketChannelNode(graph, serviceName, channel) {
|
|
|
4443
4534
|
if (graph.hasNode(id)) return id;
|
|
4444
4535
|
const node = {
|
|
4445
4536
|
id,
|
|
4446
|
-
type:
|
|
4537
|
+
type: NodeType5.WebSocketChannelNode,
|
|
4447
4538
|
name: channel,
|
|
4448
4539
|
service: serviceName,
|
|
4449
4540
|
channel,
|
|
@@ -4460,7 +4551,7 @@ function ensureMessagingDestinationNode(graph, system, destination) {
|
|
|
4460
4551
|
if (graph.hasNode(id)) return id;
|
|
4461
4552
|
const node = {
|
|
4462
4553
|
id,
|
|
4463
|
-
type:
|
|
4554
|
+
type: NodeType5.InfraNode,
|
|
4464
4555
|
name: destination,
|
|
4465
4556
|
provider: "self",
|
|
4466
4557
|
kind: messagingDestinationKind(system)
|
|
@@ -4514,7 +4605,7 @@ function resolveServiceId(graph, host, env) {
|
|
|
4514
4605
|
graph.forEachNode((id, attrs) => {
|
|
4515
4606
|
if (sameEnv) return;
|
|
4516
4607
|
const a = attrs;
|
|
4517
|
-
if (a.type !==
|
|
4608
|
+
if (a.type !== NodeType5.ServiceNode) return;
|
|
4518
4609
|
const matchesByName = a.name === host;
|
|
4519
4610
|
const matchesByAlias = a.aliases ? a.aliases.includes(host) : false;
|
|
4520
4611
|
if (!matchesByName && !matchesByAlias) return;
|
|
@@ -4536,7 +4627,7 @@ function resolveFusedServiceId(graph, serviceName, env) {
|
|
|
4536
4627
|
if (graph.hasNode(id)) return id;
|
|
4537
4628
|
const wanted = serviceName.toLowerCase();
|
|
4538
4629
|
const extractedId = graph.findNode((_nid, attrs) => {
|
|
4539
|
-
if (attrs.type !==
|
|
4630
|
+
if (attrs.type !== NodeType5.ServiceNode) return false;
|
|
4540
4631
|
const svc = attrs;
|
|
4541
4632
|
if (svc.discoveredVia === "otel") return false;
|
|
4542
4633
|
return typeof svc.name === "string" && svc.name.toLowerCase() === wanted;
|
|
@@ -4548,7 +4639,7 @@ function ensureServiceNode(graph, serviceName, env) {
|
|
|
4548
4639
|
if (graph.hasNode(resolved)) return resolved;
|
|
4549
4640
|
const node = {
|
|
4550
4641
|
id: resolved,
|
|
4551
|
-
type:
|
|
4642
|
+
type: NodeType5.ServiceNode,
|
|
4552
4643
|
name: serviceName,
|
|
4553
4644
|
language: "unknown",
|
|
4554
4645
|
discoveredVia: "otel",
|
|
@@ -4562,7 +4653,7 @@ function ensureInfraNode(graph, kind, name, provider) {
|
|
|
4562
4653
|
if (graph.hasNode(id)) return id;
|
|
4563
4654
|
const node = {
|
|
4564
4655
|
id,
|
|
4565
|
-
type:
|
|
4656
|
+
type: NodeType5.InfraNode,
|
|
4566
4657
|
name,
|
|
4567
4658
|
provider,
|
|
4568
4659
|
kind
|
|
@@ -4574,7 +4665,7 @@ var COLUMN_BEARING_INFRA_KINDS = /* @__PURE__ */ new Set(["sql-table", "supabase
|
|
|
4574
4665
|
function mergeColumnsAt(graph, tableNodeId, columns, provenance, confidence) {
|
|
4575
4666
|
if (!columns || columns.length === 0 || !graph.hasNode(tableNodeId)) return;
|
|
4576
4667
|
const node = graph.getNodeAttributes(tableNodeId);
|
|
4577
|
-
if (node.type !==
|
|
4668
|
+
if (node.type !== NodeType5.InfraNode || !node.kind || !COLUMN_BEARING_INFRA_KINDS.has(node.kind)) {
|
|
4578
4669
|
return;
|
|
4579
4670
|
}
|
|
4580
4671
|
graph.replaceNodeAttributes(tableNodeId, {
|
|
@@ -4598,7 +4689,7 @@ function ensureDatabaseNode(graph, host, engine) {
|
|
|
4598
4689
|
if (graph.hasNode(id)) return id;
|
|
4599
4690
|
const node = {
|
|
4600
4691
|
id,
|
|
4601
|
-
type:
|
|
4692
|
+
type: NodeType5.DatabaseNode,
|
|
4602
4693
|
name: host,
|
|
4603
4694
|
engine,
|
|
4604
4695
|
engineVersion: "unknown",
|
|
@@ -4614,7 +4705,7 @@ function ensureLocalDatabaseNode(graph, serviceName, name, engine) {
|
|
|
4614
4705
|
if (graph.hasNode(id)) return id;
|
|
4615
4706
|
const node = {
|
|
4616
4707
|
id,
|
|
4617
|
-
type:
|
|
4708
|
+
type: NodeType5.DatabaseNode,
|
|
4618
4709
|
name,
|
|
4619
4710
|
engine,
|
|
4620
4711
|
engineVersion: "unknown",
|
|
@@ -4639,7 +4730,7 @@ function findDeclaredDatabaseForService(graph, serviceNodeId, engine) {
|
|
|
4639
4730
|
if (edge.type !== EdgeType5.CONNECTS_TO || edge.provenance !== Provenance5.EXTRACTED) continue;
|
|
4640
4731
|
if (!graph.hasNode(edge.target)) continue;
|
|
4641
4732
|
const target = graph.getNodeAttributes(edge.target);
|
|
4642
|
-
if (target.type !==
|
|
4733
|
+
if (target.type !== NodeType5.DatabaseNode || target.engine !== engine) continue;
|
|
4643
4734
|
matches.add(edge.target);
|
|
4644
4735
|
}
|
|
4645
4736
|
}
|
|
@@ -4654,7 +4745,7 @@ function ensureFrontierNode(graph, host, ts) {
|
|
|
4654
4745
|
}
|
|
4655
4746
|
const node = {
|
|
4656
4747
|
id,
|
|
4657
|
-
type:
|
|
4748
|
+
type: NodeType5.FrontierNode,
|
|
4658
4749
|
name: host,
|
|
4659
4750
|
host,
|
|
4660
4751
|
firstObserved: ts,
|
|
@@ -5052,7 +5143,7 @@ function findRouteNodeByHttpRoute(graph, serviceName, method, httpRoute) {
|
|
|
5052
5143
|
graph.forEachNode((id, attrs) => {
|
|
5053
5144
|
if (found) return;
|
|
5054
5145
|
const a = attrs;
|
|
5055
|
-
if (a.type !==
|
|
5146
|
+
if (a.type !== NodeType5.RouteNode || a.service !== serviceName) return;
|
|
5056
5147
|
if (m && a.method !== "ALL" && a.method !== m) return;
|
|
5057
5148
|
if (normalizePathTemplate(a.pathTemplate) === target) found = id;
|
|
5058
5149
|
});
|
|
@@ -5315,7 +5406,7 @@ function promoteFrontierNodes(graph, opts = {}) {
|
|
|
5315
5406
|
const aliasIndex = /* @__PURE__ */ new Map();
|
|
5316
5407
|
graph.forEachNode((id, attrs) => {
|
|
5317
5408
|
const a = attrs;
|
|
5318
|
-
if (a.type !==
|
|
5409
|
+
if (a.type !== NodeType5.ServiceNode) return;
|
|
5319
5410
|
aliasIndex.set(a.name, id);
|
|
5320
5411
|
if (a.aliases) {
|
|
5321
5412
|
for (const alias of a.aliases) aliasIndex.set(alias, id);
|
|
@@ -5324,7 +5415,7 @@ function promoteFrontierNodes(graph, opts = {}) {
|
|
|
5324
5415
|
const toPromote = [];
|
|
5325
5416
|
graph.forEachNode((id, attrs) => {
|
|
5326
5417
|
const a = attrs;
|
|
5327
|
-
if (a.type !==
|
|
5418
|
+
if (a.type !== NodeType5.FrontierNode) return;
|
|
5328
5419
|
const target = aliasIndex.get(a.host);
|
|
5329
5420
|
if (!target) return;
|
|
5330
5421
|
if (target === id) return;
|
|
@@ -5589,6 +5680,7 @@ function describeZodIssues(error) {
|
|
|
5589
5680
|
return error.issues.map((issue) => issue.path.length > 0 ? `${issue.path.join(".")}: ${issue.message}` : issue.message).join("; ");
|
|
5590
5681
|
}
|
|
5591
5682
|
function mergeSnapshot(graph, snapshot) {
|
|
5683
|
+
invalidateSourceBaseline(graph);
|
|
5592
5684
|
const exported = snapshot.graph;
|
|
5593
5685
|
const incomingNodes = Array.isArray(exported.nodes) ? exported.nodes : [];
|
|
5594
5686
|
const incomingEdges = Array.isArray(exported.edges) ? exported.edges : [];
|
|
@@ -5639,7 +5731,7 @@ import {
|
|
|
5639
5731
|
BlastRadiusResultSchema,
|
|
5640
5732
|
EdgeType as EdgeType6,
|
|
5641
5733
|
ExpandResultSchema,
|
|
5642
|
-
NodeType as
|
|
5734
|
+
NodeType as NodeType6,
|
|
5643
5735
|
ObservedDependenciesResultSchema,
|
|
5644
5736
|
PROV_RANK,
|
|
5645
5737
|
Provenance as Provenance6,
|
|
@@ -5655,23 +5747,23 @@ var BLAST_RADIUS_DEFAULT_DEPTH = 10;
|
|
|
5655
5747
|
function isFrontierNode(graph, nodeId) {
|
|
5656
5748
|
if (!graph.hasNode(nodeId)) return false;
|
|
5657
5749
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
5658
|
-
return attrs.type ===
|
|
5750
|
+
return attrs.type === NodeType6.FrontierNode;
|
|
5659
5751
|
}
|
|
5660
5752
|
function resolveOwningService(graph, nodeId) {
|
|
5661
5753
|
if (!graph.hasNode(nodeId)) return null;
|
|
5662
5754
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
5663
|
-
if (attrs.type ===
|
|
5755
|
+
if (attrs.type === NodeType6.ServiceNode) {
|
|
5664
5756
|
return { id: nodeId, svc: attrs };
|
|
5665
5757
|
}
|
|
5666
|
-
if (attrs.type ===
|
|
5758
|
+
if (attrs.type === NodeType6.FileNode || attrs.type === NodeType6.SymbolNode) {
|
|
5667
5759
|
for (const edgeId of graph.inboundEdges(nodeId)) {
|
|
5668
5760
|
const e = graph.getEdgeAttributes(edgeId);
|
|
5669
5761
|
if (e.type !== EdgeType6.CONTAINS) continue;
|
|
5670
5762
|
const owner = graph.getNodeAttributes(e.source);
|
|
5671
|
-
if (owner.type ===
|
|
5763
|
+
if (owner.type === NodeType6.ServiceNode) {
|
|
5672
5764
|
return { id: e.source, svc: owner };
|
|
5673
5765
|
}
|
|
5674
|
-
if (owner.type ===
|
|
5766
|
+
if (owner.type === NodeType6.FileNode) {
|
|
5675
5767
|
return resolveOwningService(graph, e.source);
|
|
5676
5768
|
}
|
|
5677
5769
|
}
|
|
@@ -5867,10 +5959,10 @@ function symbolRootCauseShape(graph, origin, walk11) {
|
|
|
5867
5959
|
return serviceRootCauseShape(graph, owner.svc, walk11);
|
|
5868
5960
|
}
|
|
5869
5961
|
var rootCauseShapes = {
|
|
5870
|
-
[
|
|
5871
|
-
[
|
|
5872
|
-
[
|
|
5873
|
-
[
|
|
5962
|
+
[NodeType6.DatabaseNode]: databaseRootCauseShape,
|
|
5963
|
+
[NodeType6.ServiceNode]: serviceRootCauseShape,
|
|
5964
|
+
[NodeType6.FileNode]: fileRootCauseShape,
|
|
5965
|
+
[NodeType6.SymbolNode]: symbolRootCauseShape
|
|
5874
5966
|
};
|
|
5875
5967
|
function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
|
|
5876
5968
|
if (!graph.hasNode(errorNodeId)) return null;
|
|
@@ -5894,7 +5986,7 @@ function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
|
|
|
5894
5986
|
};
|
|
5895
5987
|
}
|
|
5896
5988
|
}
|
|
5897
|
-
if (origin.type ===
|
|
5989
|
+
if (origin.type === NodeType6.ServiceNode) {
|
|
5898
5990
|
const crossService = crossServiceRootCause(graph, errorNodeId, incidents, errorEvent);
|
|
5899
5991
|
if (crossService) return { result: crossService, source: "cross-service" };
|
|
5900
5992
|
}
|
|
@@ -5958,13 +6050,13 @@ function callSourcesForService(graph, serviceId17) {
|
|
|
5958
6050
|
const e = graph.getEdgeAttributes(edgeId);
|
|
5959
6051
|
if (e.type !== EdgeType6.CONTAINS) continue;
|
|
5960
6052
|
const tgt = graph.getNodeAttributes(e.target);
|
|
5961
|
-
if (tgt.type !==
|
|
6053
|
+
if (tgt.type !== NodeType6.FileNode) continue;
|
|
5962
6054
|
ids.push(e.target);
|
|
5963
6055
|
for (const symEdgeId of graph.outboundEdges(e.target)) {
|
|
5964
6056
|
const se = graph.getEdgeAttributes(symEdgeId);
|
|
5965
6057
|
if (se.type !== EdgeType6.CONTAINS) continue;
|
|
5966
6058
|
const sym = graph.getNodeAttributes(se.target);
|
|
5967
|
-
if (sym.type ===
|
|
6059
|
+
if (sym.type === NodeType6.SymbolNode) ids.push(se.target);
|
|
5968
6060
|
}
|
|
5969
6061
|
}
|
|
5970
6062
|
return ids;
|
|
@@ -6193,12 +6285,12 @@ function getObservedDependencies(graph, nodeId) {
|
|
|
6193
6285
|
}
|
|
6194
6286
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
6195
6287
|
const scope = [nodeId];
|
|
6196
|
-
if (attrs.type ===
|
|
6288
|
+
if (attrs.type === NodeType6.ServiceNode) {
|
|
6197
6289
|
for (const edgeId of graph.outboundEdges(nodeId)) {
|
|
6198
6290
|
const e = graph.getEdgeAttributes(edgeId);
|
|
6199
6291
|
if (e.type !== EdgeType6.CONTAINS) continue;
|
|
6200
6292
|
const owned = graph.getNodeAttributes(e.target);
|
|
6201
|
-
if (owned.type ===
|
|
6293
|
+
if (owned.type === NodeType6.FileNode) scope.push(e.target);
|
|
6202
6294
|
}
|
|
6203
6295
|
}
|
|
6204
6296
|
const dependencies = [];
|
|
@@ -6254,12 +6346,12 @@ function nodeScope(graph, nodeId) {
|
|
|
6254
6346
|
const scope = [nodeId];
|
|
6255
6347
|
if (!graph.hasNode(nodeId)) return scope;
|
|
6256
6348
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
6257
|
-
if (attrs.type ===
|
|
6349
|
+
if (attrs.type === NodeType6.ServiceNode) {
|
|
6258
6350
|
for (const edgeId of graph.outboundEdges(nodeId)) {
|
|
6259
6351
|
const e = graph.getEdgeAttributes(edgeId);
|
|
6260
6352
|
if (e.type !== EdgeType6.CONTAINS) continue;
|
|
6261
6353
|
const owned = graph.getNodeAttributes(e.target);
|
|
6262
|
-
if (owned.type ===
|
|
6354
|
+
if (owned.type === NodeType6.FileNode) scope.push(e.target);
|
|
6263
6355
|
}
|
|
6264
6356
|
}
|
|
6265
6357
|
return scope;
|
|
@@ -6414,9 +6506,9 @@ function hasFailingOutbound(graph, nodeId, seedSource, incidents) {
|
|
|
6414
6506
|
function grainOf(graph, nodeId) {
|
|
6415
6507
|
if (!graph.hasNode(nodeId)) return "unknown";
|
|
6416
6508
|
const t = graph.getNodeAttributes(nodeId).type;
|
|
6417
|
-
if (t ===
|
|
6418
|
-
if (t ===
|
|
6419
|
-
if (t ===
|
|
6509
|
+
if (t === NodeType6.ServiceNode) return "service";
|
|
6510
|
+
if (t === NodeType6.FileNode) return "file";
|
|
6511
|
+
if (t === NodeType6.SymbolNode) return "symbol";
|
|
6420
6512
|
return t;
|
|
6421
6513
|
}
|
|
6422
6514
|
function findPath(graph, from, to, direction, maxDepth) {
|
|
@@ -6785,7 +6877,7 @@ import { promises as fs20 } from "fs";
|
|
|
6785
6877
|
import path22 from "path";
|
|
6786
6878
|
import ignore2 from "ignore";
|
|
6787
6879
|
import { minimatch as minimatch2 } from "minimatch";
|
|
6788
|
-
import { NodeType as
|
|
6880
|
+
import { NodeType as NodeType16, serviceId as serviceId11 } from "@neat.is/types";
|
|
6789
6881
|
|
|
6790
6882
|
// src/extract/python.ts
|
|
6791
6883
|
import { promises as fs10 } from "fs";
|
|
@@ -6856,7 +6948,7 @@ function pythonToPackage(service) {
|
|
|
6856
6948
|
// src/extract/go.ts
|
|
6857
6949
|
import { promises as fs11 } from "fs";
|
|
6858
6950
|
import path12 from "path";
|
|
6859
|
-
import { NodeType as
|
|
6951
|
+
import { NodeType as NodeType7, serviceId as serviceId2 } from "@neat.is/types";
|
|
6860
6952
|
function parseGoMod(source) {
|
|
6861
6953
|
const module = source.match(/^\s*module\s+(\S+)\s*$/m)?.[1];
|
|
6862
6954
|
if (!module) return null;
|
|
@@ -6893,7 +6985,7 @@ async function discoverGoService(scanPath, dir) {
|
|
|
6893
6985
|
const framework = goFramework(mod.dependencies);
|
|
6894
6986
|
const node = {
|
|
6895
6987
|
id: serviceId2(name),
|
|
6896
|
-
type:
|
|
6988
|
+
type: NodeType7.ServiceNode,
|
|
6897
6989
|
name,
|
|
6898
6990
|
language: "go",
|
|
6899
6991
|
dependencies: mod.dependencies,
|
|
@@ -6906,7 +6998,7 @@ async function discoverGoService(scanPath, dir) {
|
|
|
6906
6998
|
// src/extract/ruby.ts
|
|
6907
6999
|
import { promises as fs12 } from "fs";
|
|
6908
7000
|
import path13 from "path";
|
|
6909
|
-
import { NodeType as
|
|
7001
|
+
import { NodeType as NodeType8, serviceId as serviceId3 } from "@neat.is/types";
|
|
6910
7002
|
function parseGemfile(source) {
|
|
6911
7003
|
const dependencies = {};
|
|
6912
7004
|
for (const raw of source.split(/\r?\n/)) {
|
|
@@ -6931,7 +7023,7 @@ async function discoverRubyService(scanPath, dir) {
|
|
|
6931
7023
|
const pkg = { name, dependencies: gemfile.dependencies };
|
|
6932
7024
|
const node = {
|
|
6933
7025
|
id: serviceId3(name),
|
|
6934
|
-
type:
|
|
7026
|
+
type: NodeType8.ServiceNode,
|
|
6935
7027
|
name,
|
|
6936
7028
|
language: "ruby",
|
|
6937
7029
|
dependencies: gemfile.dependencies,
|
|
@@ -6943,7 +7035,7 @@ async function discoverRubyService(scanPath, dir) {
|
|
|
6943
7035
|
|
|
6944
7036
|
// src/extract/php.ts
|
|
6945
7037
|
import path14 from "path";
|
|
6946
|
-
import { NodeType as
|
|
7038
|
+
import { NodeType as NodeType9, serviceId as serviceId4 } from "@neat.is/types";
|
|
6947
7039
|
function parseComposerJson(composer) {
|
|
6948
7040
|
return {
|
|
6949
7041
|
dependencies: {
|
|
@@ -6964,7 +7056,7 @@ async function discoverPhpService(scanPath, dir) {
|
|
|
6964
7056
|
const pkg = { name, dependencies };
|
|
6965
7057
|
const node = {
|
|
6966
7058
|
id: serviceId4(name),
|
|
6967
|
-
type:
|
|
7059
|
+
type: NodeType9.ServiceNode,
|
|
6968
7060
|
name,
|
|
6969
7061
|
language: "php",
|
|
6970
7062
|
dependencies,
|
|
@@ -6977,7 +7069,7 @@ async function discoverPhpService(scanPath, dir) {
|
|
|
6977
7069
|
// src/extract/csharp.ts
|
|
6978
7070
|
import { promises as fs13 } from "fs";
|
|
6979
7071
|
import path15 from "path";
|
|
6980
|
-
import { NodeType as
|
|
7072
|
+
import { NodeType as NodeType10, serviceId as serviceId5 } from "@neat.is/types";
|
|
6981
7073
|
var CSHARP_PROJECT_EXTS = /* @__PURE__ */ new Set([".csproj", ".sln"]);
|
|
6982
7074
|
async function projectFiles(dir) {
|
|
6983
7075
|
const entries = await fs13.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
@@ -7025,7 +7117,7 @@ async function discoverCsharpService(scanPath, dir) {
|
|
|
7025
7117
|
const pkg = { name, dependencies };
|
|
7026
7118
|
const node = {
|
|
7027
7119
|
id: serviceId5(name),
|
|
7028
|
-
type:
|
|
7120
|
+
type: NodeType10.ServiceNode,
|
|
7029
7121
|
name,
|
|
7030
7122
|
language: "csharp",
|
|
7031
7123
|
dependencies,
|
|
@@ -7039,7 +7131,7 @@ async function discoverCsharpService(scanPath, dir) {
|
|
|
7039
7131
|
// src/extract/java.ts
|
|
7040
7132
|
import { promises as fs14 } from "fs";
|
|
7041
7133
|
import path16 from "path";
|
|
7042
|
-
import { NodeType as
|
|
7134
|
+
import { NodeType as NodeType11, serviceId as serviceId6 } from "@neat.is/types";
|
|
7043
7135
|
var JAVA_MANIFESTS = ["pom.xml", "build.gradle", "build.gradle.kts"];
|
|
7044
7136
|
async function hasJavaManifest(dir) {
|
|
7045
7137
|
for (const manifest of JAVA_MANIFESTS) {
|
|
@@ -7095,7 +7187,7 @@ async function discoverJavaService(scanPath, dir) {
|
|
|
7095
7187
|
const pkg = { name, dependencies };
|
|
7096
7188
|
const node = {
|
|
7097
7189
|
id: serviceId6(name),
|
|
7098
|
-
type:
|
|
7190
|
+
type: NodeType11.ServiceNode,
|
|
7099
7191
|
name,
|
|
7100
7192
|
language: "java",
|
|
7101
7193
|
dependencies,
|
|
@@ -7107,7 +7199,7 @@ async function discoverJavaService(scanPath, dir) {
|
|
|
7107
7199
|
// src/extract/kotlin.ts
|
|
7108
7200
|
import { promises as fs15 } from "fs";
|
|
7109
7201
|
import path17 from "path";
|
|
7110
|
-
import { NodeType as
|
|
7202
|
+
import { NodeType as NodeType12, serviceId as serviceId7 } from "@neat.is/types";
|
|
7111
7203
|
var KOTLIN_SOURCE_EXT = ".kt";
|
|
7112
7204
|
var JAVA_SOURCE_EXT = ".java";
|
|
7113
7205
|
var SOURCE_PROBE_MAX_DEPTH = 8;
|
|
@@ -7159,7 +7251,7 @@ async function discoverKotlinService(scanPath, dir) {
|
|
|
7159
7251
|
const pkg = { name, dependencies };
|
|
7160
7252
|
const node = {
|
|
7161
7253
|
id: serviceId7(name),
|
|
7162
|
-
type:
|
|
7254
|
+
type: NodeType12.ServiceNode,
|
|
7163
7255
|
name,
|
|
7164
7256
|
language: "kotlin",
|
|
7165
7257
|
dependencies,
|
|
@@ -7172,7 +7264,7 @@ async function discoverKotlinService(scanPath, dir) {
|
|
|
7172
7264
|
import { promises as fs16 } from "fs";
|
|
7173
7265
|
import path18 from "path";
|
|
7174
7266
|
import { parse as parseToml2 } from "smol-toml";
|
|
7175
|
-
import { NodeType as
|
|
7267
|
+
import { NodeType as NodeType13, serviceId as serviceId8 } from "@neat.is/types";
|
|
7176
7268
|
var CARGO_MANIFEST = "Cargo.toml";
|
|
7177
7269
|
async function hasRustManifest(dir) {
|
|
7178
7270
|
return exists(path18.join(dir, CARGO_MANIFEST));
|
|
@@ -7208,7 +7300,7 @@ async function discoverRustService(scanPath, dir) {
|
|
|
7208
7300
|
const pkg = { name, dependencies };
|
|
7209
7301
|
const node = {
|
|
7210
7302
|
id: serviceId8(name),
|
|
7211
|
-
type:
|
|
7303
|
+
type: NodeType13.ServiceNode,
|
|
7212
7304
|
name,
|
|
7213
7305
|
language: "rust",
|
|
7214
7306
|
dependencies,
|
|
@@ -7220,7 +7312,7 @@ async function discoverRustService(scanPath, dir) {
|
|
|
7220
7312
|
// src/extract/cpp.ts
|
|
7221
7313
|
import { promises as fs17 } from "fs";
|
|
7222
7314
|
import path19 from "path";
|
|
7223
|
-
import { NodeType as
|
|
7315
|
+
import { NodeType as NodeType14, serviceId as serviceId9 } from "@neat.is/types";
|
|
7224
7316
|
var CMAKE_MANIFEST = "CMakeLists.txt";
|
|
7225
7317
|
async function hasCppManifest(dir) {
|
|
7226
7318
|
return exists(path19.join(dir, CMAKE_MANIFEST));
|
|
@@ -7239,7 +7331,7 @@ async function discoverCppService(scanPath, dir) {
|
|
|
7239
7331
|
const pkg = { name, dependencies };
|
|
7240
7332
|
const node = {
|
|
7241
7333
|
id: serviceId9(name),
|
|
7242
|
-
type:
|
|
7334
|
+
type: NodeType14.ServiceNode,
|
|
7243
7335
|
name,
|
|
7244
7336
|
language: "cpp",
|
|
7245
7337
|
dependencies,
|
|
@@ -7251,7 +7343,7 @@ async function discoverCppService(scanPath, dir) {
|
|
|
7251
7343
|
// src/extract/dockerfile-service.ts
|
|
7252
7344
|
import { promises as fs18 } from "fs";
|
|
7253
7345
|
import path20 from "path";
|
|
7254
|
-
import { NodeType as
|
|
7346
|
+
import { NodeType as NodeType15, serviceId as serviceId10 } from "@neat.is/types";
|
|
7255
7347
|
function languageForSourceExt(ext) {
|
|
7256
7348
|
switch (ext) {
|
|
7257
7349
|
case ".py":
|
|
@@ -7338,7 +7430,7 @@ async function discoverDockerfileService(scanPath, dir) {
|
|
|
7338
7430
|
const pkg = { name, dependencies: {} };
|
|
7339
7431
|
const node = {
|
|
7340
7432
|
id: serviceId10(name),
|
|
7341
|
-
type:
|
|
7433
|
+
type: NodeType15.ServiceNode,
|
|
7342
7434
|
name,
|
|
7343
7435
|
language,
|
|
7344
7436
|
dependencies: {},
|
|
@@ -7532,7 +7624,7 @@ async function discoverNodeService(scanPath, dir) {
|
|
|
7532
7624
|
const language = await detectJsServiceLanguage(dir, pkg);
|
|
7533
7625
|
const node = {
|
|
7534
7626
|
id: serviceId11(pkg.name),
|
|
7535
|
-
type:
|
|
7627
|
+
type: NodeType16.ServiceNode,
|
|
7536
7628
|
name: pkg.name,
|
|
7537
7629
|
language,
|
|
7538
7630
|
version: pkg.version,
|
|
@@ -7549,7 +7641,7 @@ async function discoverPyService(scanPath, dir) {
|
|
|
7549
7641
|
const pkg = pythonToPackage(py);
|
|
7550
7642
|
const node = {
|
|
7551
7643
|
id: serviceId11(py.name),
|
|
7552
|
-
type:
|
|
7644
|
+
type: NodeType16.ServiceNode,
|
|
7553
7645
|
name: py.name,
|
|
7554
7646
|
language: "python",
|
|
7555
7647
|
version: py.version,
|
|
@@ -7667,7 +7759,7 @@ function addServiceNodes(graph, services) {
|
|
|
7667
7759
|
import path23 from "path";
|
|
7668
7760
|
import { promises as fs21 } from "fs";
|
|
7669
7761
|
import { parseAllDocuments } from "yaml";
|
|
7670
|
-
import { NodeType as
|
|
7762
|
+
import { NodeType as NodeType17 } from "@neat.is/types";
|
|
7671
7763
|
var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
7672
7764
|
"Service",
|
|
7673
7765
|
"Deployment",
|
|
@@ -7677,7 +7769,7 @@ var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
|
7677
7769
|
function addAliases(graph, serviceId17, candidates) {
|
|
7678
7770
|
if (!graph.hasNode(serviceId17)) return;
|
|
7679
7771
|
const node = graph.getNodeAttributes(serviceId17);
|
|
7680
|
-
if (node.type !==
|
|
7772
|
+
if (node.type !== NodeType17.ServiceNode) return;
|
|
7681
7773
|
const set = new Set(node.aliases ?? []);
|
|
7682
7774
|
for (const c of candidates) {
|
|
7683
7775
|
if (!c) continue;
|
|
@@ -7867,7 +7959,7 @@ import Rust2 from "tree-sitter-rust";
|
|
|
7867
7959
|
import Cpp from "tree-sitter-cpp";
|
|
7868
7960
|
import {
|
|
7869
7961
|
EdgeType as EdgeType7,
|
|
7870
|
-
NodeType as
|
|
7962
|
+
NodeType as NodeType18,
|
|
7871
7963
|
Provenance as Provenance7,
|
|
7872
7964
|
confidenceForExtracted as confidenceForExtracted4,
|
|
7873
7965
|
extractedEdgeId as extractedEdgeId6,
|
|
@@ -7925,7 +8017,9 @@ function collectSymbolDefs(root) {
|
|
|
7925
8017
|
kind,
|
|
7926
8018
|
qualname,
|
|
7927
8019
|
startLine: node.startPosition.row + 1,
|
|
7928
|
-
endLine: node.endPosition.row + 1
|
|
8020
|
+
endLine: node.endPosition.row + 1,
|
|
8021
|
+
startIndex: node.startIndex,
|
|
8022
|
+
endIndex: node.endIndex
|
|
7929
8023
|
});
|
|
7930
8024
|
};
|
|
7931
8025
|
const visit = (node, classCtx) => {
|
|
@@ -7984,7 +8078,9 @@ function collectPythonSymbolDefs(root) {
|
|
|
7984
8078
|
kind,
|
|
7985
8079
|
qualname,
|
|
7986
8080
|
startLine: node.startPosition.row + 1,
|
|
7987
|
-
endLine: node.endPosition.row + 1
|
|
8081
|
+
endLine: node.endPosition.row + 1,
|
|
8082
|
+
startIndex: node.startIndex,
|
|
8083
|
+
endIndex: node.endIndex
|
|
7988
8084
|
});
|
|
7989
8085
|
};
|
|
7990
8086
|
const visit = (node, classCtx) => {
|
|
@@ -8057,7 +8153,9 @@ function collectGoSymbolDefs(root) {
|
|
|
8057
8153
|
kind,
|
|
8058
8154
|
qualname,
|
|
8059
8155
|
startLine: node.startPosition.row + 1,
|
|
8060
|
-
endLine: node.endPosition.row + 1
|
|
8156
|
+
endLine: node.endPosition.row + 1,
|
|
8157
|
+
startIndex: node.startIndex,
|
|
8158
|
+
endIndex: node.endIndex
|
|
8061
8159
|
});
|
|
8062
8160
|
};
|
|
8063
8161
|
const visit = (node) => {
|
|
@@ -8091,7 +8189,9 @@ function collectRubySymbolDefs(root) {
|
|
|
8091
8189
|
kind,
|
|
8092
8190
|
qualname,
|
|
8093
8191
|
startLine: node.startPosition.row + 1,
|
|
8094
|
-
endLine: node.endPosition.row + 1
|
|
8192
|
+
endLine: node.endPosition.row + 1,
|
|
8193
|
+
startIndex: node.startIndex,
|
|
8194
|
+
endIndex: node.endIndex
|
|
8095
8195
|
});
|
|
8096
8196
|
};
|
|
8097
8197
|
const nameText = (node) => node.childForFieldName("name")?.text.replace(/::/g, ".");
|
|
@@ -8142,7 +8242,9 @@ function collectPhpSymbolDefs(root) {
|
|
|
8142
8242
|
kind,
|
|
8143
8243
|
qualname,
|
|
8144
8244
|
startLine: node.startPosition.row + 1,
|
|
8145
|
-
endLine: node.endPosition.row + 1
|
|
8245
|
+
endLine: node.endPosition.row + 1,
|
|
8246
|
+
startIndex: node.startIndex,
|
|
8247
|
+
endIndex: node.endIndex
|
|
8146
8248
|
});
|
|
8147
8249
|
};
|
|
8148
8250
|
const dot = (s) => s.replace(/\\/g, ".").replace(/::/g, ".").replace(/^\.+/, "");
|
|
@@ -8208,7 +8310,9 @@ function collectCsharpSymbolDefs(root) {
|
|
|
8208
8310
|
kind,
|
|
8209
8311
|
qualname,
|
|
8210
8312
|
startLine: node.startPosition.row + 1,
|
|
8211
|
-
endLine: node.endPosition.row + 1
|
|
8313
|
+
endLine: node.endPosition.row + 1,
|
|
8314
|
+
startIndex: node.startIndex,
|
|
8315
|
+
endIndex: node.endIndex
|
|
8212
8316
|
});
|
|
8213
8317
|
};
|
|
8214
8318
|
const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
|
|
@@ -8270,7 +8374,9 @@ function collectJavaSymbolDefs(root) {
|
|
|
8270
8374
|
kind,
|
|
8271
8375
|
qualname,
|
|
8272
8376
|
startLine: node.startPosition.row + 1,
|
|
8273
|
-
endLine: node.endPosition.row + 1
|
|
8377
|
+
endLine: node.endPosition.row + 1,
|
|
8378
|
+
startIndex: node.startIndex,
|
|
8379
|
+
endIndex: node.endIndex
|
|
8274
8380
|
});
|
|
8275
8381
|
};
|
|
8276
8382
|
const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
|
|
@@ -8327,7 +8433,9 @@ function collectKotlinSymbolDefs(root) {
|
|
|
8327
8433
|
kind,
|
|
8328
8434
|
qualname,
|
|
8329
8435
|
startLine: node.startPosition.row + 1,
|
|
8330
|
-
endLine: node.endPosition.row + 1
|
|
8436
|
+
endLine: node.endPosition.row + 1,
|
|
8437
|
+
startIndex: node.startIndex,
|
|
8438
|
+
endIndex: node.endIndex
|
|
8331
8439
|
});
|
|
8332
8440
|
};
|
|
8333
8441
|
const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
|
|
@@ -8397,7 +8505,9 @@ function collectRustSymbolDefs(root) {
|
|
|
8397
8505
|
kind,
|
|
8398
8506
|
qualname,
|
|
8399
8507
|
startLine: node.startPosition.row + 1,
|
|
8400
|
-
endLine: node.endPosition.row + 1
|
|
8508
|
+
endLine: node.endPosition.row + 1,
|
|
8509
|
+
startIndex: node.startIndex,
|
|
8510
|
+
endIndex: node.endIndex
|
|
8401
8511
|
});
|
|
8402
8512
|
};
|
|
8403
8513
|
const join = (prefix, name) => prefix ? `${prefix}::${name}` : name;
|
|
@@ -8465,7 +8575,9 @@ function collectCppSymbolDefs(root) {
|
|
|
8465
8575
|
kind,
|
|
8466
8576
|
qualname,
|
|
8467
8577
|
startLine: node.startPosition.row + 1,
|
|
8468
|
-
endLine: node.endPosition.row + 1
|
|
8578
|
+
endLine: node.endPosition.row + 1,
|
|
8579
|
+
startIndex: node.startIndex,
|
|
8580
|
+
endIndex: node.endIndex
|
|
8469
8581
|
});
|
|
8470
8582
|
};
|
|
8471
8583
|
const join = (prefix, name) => prefix ? `${prefix}::${name}` : name;
|
|
@@ -8593,6 +8705,22 @@ function disambiguate(defs) {
|
|
|
8593
8705
|
return { def, disambiguator: ordinal };
|
|
8594
8706
|
});
|
|
8595
8707
|
}
|
|
8708
|
+
function utf8Offsets(content, defs) {
|
|
8709
|
+
if (content.includes("\uFFFD")) return /* @__PURE__ */ new Map();
|
|
8710
|
+
const indices = [...new Set(defs.flatMap(({ startIndex, endIndex }) => [startIndex, endIndex]))].sort(
|
|
8711
|
+
(a, b) => a - b
|
|
8712
|
+
);
|
|
8713
|
+
const offsets = /* @__PURE__ */ new Map();
|
|
8714
|
+
let cursor = 0;
|
|
8715
|
+
let bytes = 0;
|
|
8716
|
+
for (const index of indices) {
|
|
8717
|
+
if (index < cursor || index > content.length) return /* @__PURE__ */ new Map();
|
|
8718
|
+
bytes += Buffer.byteLength(content.slice(cursor, index), "utf8");
|
|
8719
|
+
offsets.set(index, bytes);
|
|
8720
|
+
cursor = index;
|
|
8721
|
+
}
|
|
8722
|
+
return offsets;
|
|
8723
|
+
}
|
|
8596
8724
|
async function addSymbols(graph, services) {
|
|
8597
8725
|
const parsers = /* @__PURE__ */ new Map();
|
|
8598
8726
|
const parserForExt5 = (ext) => {
|
|
@@ -8616,37 +8744,49 @@ async function addSymbols(graph, services) {
|
|
|
8616
8744
|
if (!parser) continue;
|
|
8617
8745
|
const relPath = toPosix(path25.relative(service.dir, file.path));
|
|
8618
8746
|
let defs;
|
|
8747
|
+
let completeParse;
|
|
8619
8748
|
try {
|
|
8620
8749
|
const tree = parseSource3(parser, file.content);
|
|
8621
8750
|
defs = collectSymbolDefsForExt(ext, tree.rootNode);
|
|
8751
|
+
completeParse = !tree.rootNode.hasError;
|
|
8622
8752
|
} catch (err) {
|
|
8623
8753
|
recordExtractionError("symbol extraction", file.path, err);
|
|
8624
8754
|
continue;
|
|
8625
8755
|
}
|
|
8626
8756
|
if (defs.length === 0) continue;
|
|
8627
|
-
const
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
);
|
|
8757
|
+
const offsets = completeParse ? utf8Offsets(file.content, defs) : /* @__PURE__ */ new Map();
|
|
8758
|
+
const {
|
|
8759
|
+
fileNodeId,
|
|
8760
|
+
nodesAdded: fn,
|
|
8761
|
+
edgesAdded: fe
|
|
8762
|
+
} = ensureFileNode(graph, service.pkg.name, service.node.id, relPath);
|
|
8633
8763
|
nodesAdded += fn;
|
|
8634
8764
|
edgesAdded += fe;
|
|
8635
8765
|
for (const { def, disambiguator } of disambiguate(defs)) {
|
|
8636
8766
|
const sid = symbolId2(service.pkg.name, relPath, def.qualname, disambiguator);
|
|
8767
|
+
const startByte = offsets.get(def.startIndex);
|
|
8768
|
+
const endByte = offsets.get(def.endIndex);
|
|
8769
|
+
const precise = startByte !== void 0 && endByte !== void 0 && endByte > startByte ? { startByte, endByte } : {};
|
|
8770
|
+
const node = {
|
|
8771
|
+
id: sid,
|
|
8772
|
+
type: NodeType18.SymbolNode,
|
|
8773
|
+
kind: def.kind,
|
|
8774
|
+
qualname: def.qualname,
|
|
8775
|
+
span: { startLine: def.startLine, endLine: def.endLine, ...precise },
|
|
8776
|
+
service: service.pkg.name,
|
|
8777
|
+
relPath,
|
|
8778
|
+
discoveredVia: "static"
|
|
8779
|
+
};
|
|
8637
8780
|
if (!graph.hasNode(sid)) {
|
|
8638
|
-
const node = {
|
|
8639
|
-
id: sid,
|
|
8640
|
-
type: NodeType17.SymbolNode,
|
|
8641
|
-
kind: def.kind,
|
|
8642
|
-
qualname: def.qualname,
|
|
8643
|
-
span: { startLine: def.startLine, endLine: def.endLine },
|
|
8644
|
-
service: service.pkg.name,
|
|
8645
|
-
relPath,
|
|
8646
|
-
discoveredVia: "static"
|
|
8647
|
-
};
|
|
8648
8781
|
graph.addNode(sid, node);
|
|
8649
8782
|
nodesAdded++;
|
|
8783
|
+
} else {
|
|
8784
|
+
const previous = graph.getNodeAttributes(sid);
|
|
8785
|
+
const discoveredVia = previous.discoveredVia === "otel" || previous.discoveredVia === "merged" ? "merged" : "static";
|
|
8786
|
+
const moved = previous.span.startLine !== node.span.startLine || previous.span.endLine !== node.span.endLine || previous.span.startByte !== node.span.startByte || previous.span.endByte !== node.span.endByte;
|
|
8787
|
+
if (moved || previous.kind !== node.kind || previous.qualname !== node.qualname || previous.discoveredVia !== discoveredVia || previous.service !== node.service || previous.relPath !== node.relPath) {
|
|
8788
|
+
graph.replaceNodeAttributes(sid, { ...previous, ...node, discoveredVia });
|
|
8789
|
+
}
|
|
8650
8790
|
}
|
|
8651
8791
|
const containsId = extractedEdgeId6(fileNodeId, sid, EdgeType7.CONTAINS);
|
|
8652
8792
|
if (!graph.hasEdge(containsId)) {
|
|
@@ -8677,7 +8817,7 @@ import path26 from "path";
|
|
|
8677
8817
|
import Parser4 from "tree-sitter";
|
|
8678
8818
|
import {
|
|
8679
8819
|
EdgeType as EdgeType8,
|
|
8680
|
-
NodeType as
|
|
8820
|
+
NodeType as NodeType19,
|
|
8681
8821
|
Provenance as Provenance8,
|
|
8682
8822
|
confidenceForExtracted as confidenceForExtracted5,
|
|
8683
8823
|
extractedEdgeId as extractedEdgeId7,
|
|
@@ -8832,7 +8972,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
8832
8972
|
const candidate = symbolId3(serviceName, imp.targetRelPath, imp.importedName);
|
|
8833
8973
|
if (graph.hasNode(candidate)) {
|
|
8834
8974
|
const node = graph.getNodeAttributes(candidate);
|
|
8835
|
-
if (node.type ===
|
|
8975
|
+
if (node.type === NodeType19.SymbolNode && node.kind === wantKind) return candidate;
|
|
8836
8976
|
}
|
|
8837
8977
|
}
|
|
8838
8978
|
return null;
|
|
@@ -8928,7 +9068,7 @@ import path27 from "path";
|
|
|
8928
9068
|
import Parser5 from "tree-sitter";
|
|
8929
9069
|
import {
|
|
8930
9070
|
EdgeType as EdgeType9,
|
|
8931
|
-
NodeType as
|
|
9071
|
+
NodeType as NodeType20,
|
|
8932
9072
|
Provenance as Provenance9,
|
|
8933
9073
|
confidenceForExtracted as confidenceForExtracted6,
|
|
8934
9074
|
extractedEdgeId as extractedEdgeId8,
|
|
@@ -9107,7 +9247,7 @@ async function addServerActions(graph, services) {
|
|
|
9107
9247
|
if (!graph.hasNode(aid)) {
|
|
9108
9248
|
const node = {
|
|
9109
9249
|
id: aid,
|
|
9110
|
-
type:
|
|
9250
|
+
type: NodeType20.ServerActionNode,
|
|
9111
9251
|
name: action.exportName,
|
|
9112
9252
|
service: service.pkg.name,
|
|
9113
9253
|
module: relPath,
|
|
@@ -9199,7 +9339,7 @@ async function addServerActions(graph, services) {
|
|
|
9199
9339
|
import path36 from "path";
|
|
9200
9340
|
import {
|
|
9201
9341
|
EdgeType as EdgeType10,
|
|
9202
|
-
NodeType as
|
|
9342
|
+
NodeType as NodeType21,
|
|
9203
9343
|
Provenance as Provenance10,
|
|
9204
9344
|
configId,
|
|
9205
9345
|
databaseId as databaseId2,
|
|
@@ -9853,7 +9993,7 @@ function compatibleDriversFor(engine) {
|
|
|
9853
9993
|
function toDatabaseNode(config) {
|
|
9854
9994
|
return {
|
|
9855
9995
|
id: databaseId2(config.host),
|
|
9856
|
-
type:
|
|
9996
|
+
type: NodeType21.DatabaseNode,
|
|
9857
9997
|
name: config.database || config.host,
|
|
9858
9998
|
engine: config.engine,
|
|
9859
9999
|
engineVersion: config.engineVersion,
|
|
@@ -10018,7 +10158,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
10018
10158
|
if (!graph.hasNode(cfgId)) {
|
|
10019
10159
|
const cfgNode = {
|
|
10020
10160
|
id: cfgId,
|
|
10021
|
-
type:
|
|
10161
|
+
type: NodeType21.ConfigNode,
|
|
10022
10162
|
name: path36.basename(primary.sourceFile),
|
|
10023
10163
|
path: relPath,
|
|
10024
10164
|
fileType: isConfigFile(path36.basename(primary.sourceFile)).fileType || "config"
|
|
@@ -10065,7 +10205,7 @@ import { promises as fs25 } from "fs";
|
|
|
10065
10205
|
import path37 from "path";
|
|
10066
10206
|
import {
|
|
10067
10207
|
EdgeType as EdgeType11,
|
|
10068
|
-
NodeType as
|
|
10208
|
+
NodeType as NodeType22,
|
|
10069
10209
|
Provenance as Provenance11,
|
|
10070
10210
|
configId as configId2,
|
|
10071
10211
|
confidenceForExtracted as confidenceForExtracted8
|
|
@@ -10099,7 +10239,7 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
10099
10239
|
const relPath = path37.relative(scanPath, file);
|
|
10100
10240
|
const node = {
|
|
10101
10241
|
id: configId2(relPath),
|
|
10102
|
-
type:
|
|
10242
|
+
type: NodeType22.ConfigNode,
|
|
10103
10243
|
name: path37.basename(file),
|
|
10104
10244
|
path: relPath,
|
|
10105
10245
|
fileType: isConfigFile(path37.basename(file)).fileType
|
|
@@ -10140,7 +10280,7 @@ import { promises as fs26 } from "fs";
|
|
|
10140
10280
|
import path38 from "path";
|
|
10141
10281
|
import {
|
|
10142
10282
|
EdgeType as EdgeType12,
|
|
10143
|
-
NodeType as
|
|
10283
|
+
NodeType as NodeType23,
|
|
10144
10284
|
Provenance as Provenance12,
|
|
10145
10285
|
confidenceForExtracted as confidenceForExtracted9,
|
|
10146
10286
|
extractedEdgeId as extractedEdgeId9,
|
|
@@ -10229,7 +10369,7 @@ async function addGrpcMethods(graph, services) {
|
|
|
10229
10369
|
if (!graph.hasNode(mid)) {
|
|
10230
10370
|
const node = {
|
|
10231
10371
|
id: mid,
|
|
10232
|
-
type:
|
|
10372
|
+
type: NodeType23.GrpcMethodNode,
|
|
10233
10373
|
name: `${method.rpcService}/${method.rpcMethod}`,
|
|
10234
10374
|
rpcService: method.rpcService,
|
|
10235
10375
|
rpcMethod: method.rpcMethod,
|
|
@@ -10267,7 +10407,7 @@ async function addGrpcMethods(graph, services) {
|
|
|
10267
10407
|
// src/extract/calls/index.ts
|
|
10268
10408
|
import {
|
|
10269
10409
|
EdgeType as EdgeType15,
|
|
10270
|
-
NodeType as
|
|
10410
|
+
NodeType as NodeType25,
|
|
10271
10411
|
Provenance as Provenance15,
|
|
10272
10412
|
confidenceForExtracted as confidenceForExtracted12,
|
|
10273
10413
|
passesExtractedFloor as passesExtractedFloor3
|
|
@@ -10429,7 +10569,7 @@ import Parser7 from "tree-sitter";
|
|
|
10429
10569
|
import JavaScript5 from "tree-sitter-javascript";
|
|
10430
10570
|
import {
|
|
10431
10571
|
EdgeType as EdgeType14,
|
|
10432
|
-
NodeType as
|
|
10572
|
+
NodeType as NodeType24,
|
|
10433
10573
|
Provenance as Provenance14,
|
|
10434
10574
|
confidenceForExtracted as confidenceForExtracted11,
|
|
10435
10575
|
passesExtractedFloor as passesExtractedFloor2,
|
|
@@ -10678,7 +10818,7 @@ function buildRouteIndex(graph) {
|
|
|
10678
10818
|
const index = /* @__PURE__ */ new Map();
|
|
10679
10819
|
graph.forEachNode((_id, attrs) => {
|
|
10680
10820
|
const node = attrs;
|
|
10681
|
-
if (node.type !==
|
|
10821
|
+
if (node.type !== NodeType24.RouteNode) return;
|
|
10682
10822
|
const route = attrs;
|
|
10683
10823
|
const owner = serviceId12(route.service);
|
|
10684
10824
|
const entry = {
|
|
@@ -14357,7 +14497,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
14357
14497
|
if (!graph.hasNode(ep.infraId)) {
|
|
14358
14498
|
const node = {
|
|
14359
14499
|
id: ep.infraId,
|
|
14360
|
-
type:
|
|
14500
|
+
type: NodeType25.InfraNode,
|
|
14361
14501
|
name: ep.name,
|
|
14362
14502
|
// #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
|
|
14363
14503
|
// aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
|
|
@@ -14370,7 +14510,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
14370
14510
|
}
|
|
14371
14511
|
if (ep.columns && ep.columns.length > 0) {
|
|
14372
14512
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
14373
|
-
if (node.type ===
|
|
14513
|
+
if (node.type === NodeType25.InfraNode) {
|
|
14374
14514
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
14375
14515
|
...node,
|
|
14376
14516
|
columns: foldColumns(
|
|
@@ -14384,7 +14524,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
14384
14524
|
}
|
|
14385
14525
|
if (ep.sdkWrites && Object.keys(ep.sdkWrites).length > 0) {
|
|
14386
14526
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
14387
|
-
if (node.type ===
|
|
14527
|
+
if (node.type === NodeType25.InfraNode) {
|
|
14388
14528
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
14389
14529
|
...node,
|
|
14390
14530
|
columns: foldSdkWrites(node.columns, ep.sdkWrites)
|
|
@@ -14446,7 +14586,7 @@ async function addCallEdges(graph, services) {
|
|
|
14446
14586
|
// src/extract/table-edges.ts
|
|
14447
14587
|
import {
|
|
14448
14588
|
EdgeType as EdgeType16,
|
|
14449
|
-
NodeType as
|
|
14589
|
+
NodeType as NodeType26,
|
|
14450
14590
|
Provenance as Provenance16,
|
|
14451
14591
|
confidenceForExtracted as confidenceForExtracted13,
|
|
14452
14592
|
extractedEdgeId as extractedEdgeId10,
|
|
@@ -14505,7 +14645,7 @@ function ensureTableNode(graph, id, name) {
|
|
|
14505
14645
|
if (graph.hasNode(id)) return 0;
|
|
14506
14646
|
const node = {
|
|
14507
14647
|
id,
|
|
14508
|
-
type:
|
|
14648
|
+
type: NodeType26.InfraNode,
|
|
14509
14649
|
name,
|
|
14510
14650
|
provider: "self",
|
|
14511
14651
|
kind: "sql-table"
|
|
@@ -14519,11 +14659,11 @@ import path58 from "path";
|
|
|
14519
14659
|
import { EdgeType as EdgeType17, Provenance as Provenance18, confidenceForExtracted as confidenceForExtracted15 } from "@neat.is/types";
|
|
14520
14660
|
|
|
14521
14661
|
// src/extract/infra/shared.ts
|
|
14522
|
-
import { NodeType as
|
|
14662
|
+
import { NodeType as NodeType27, Provenance as Provenance17, confidenceForExtracted as confidenceForExtracted14, infraId as infraId20 } from "@neat.is/types";
|
|
14523
14663
|
function makeInfraNode(kind, name, provider = "self", extras) {
|
|
14524
14664
|
return {
|
|
14525
14665
|
id: infraId20(kind, name),
|
|
14526
|
-
type:
|
|
14666
|
+
type: NodeType27.InfraNode,
|
|
14527
14667
|
name,
|
|
14528
14668
|
provider,
|
|
14529
14669
|
kind,
|
|
@@ -15398,7 +15538,7 @@ import Parser18 from "tree-sitter";
|
|
|
15398
15538
|
import JavaScript8 from "tree-sitter-javascript";
|
|
15399
15539
|
import {
|
|
15400
15540
|
EdgeType as EdgeType25,
|
|
15401
|
-
NodeType as
|
|
15541
|
+
NodeType as NodeType28,
|
|
15402
15542
|
Provenance as Provenance22,
|
|
15403
15543
|
confidenceForExtracted as confidenceForExtracted19,
|
|
15404
15544
|
extractedEdgeId as extractedEdgeId11,
|
|
@@ -15544,7 +15684,7 @@ async function addZodShapes(graph, services) {
|
|
|
15544
15684
|
if (!graph.hasNode(shape.infraId)) {
|
|
15545
15685
|
const node = {
|
|
15546
15686
|
id: shape.infraId,
|
|
15547
|
-
type:
|
|
15687
|
+
type: NodeType28.InfraNode,
|
|
15548
15688
|
name: shape.name,
|
|
15549
15689
|
provider: "self",
|
|
15550
15690
|
kind: "zod-schema"
|
|
@@ -15554,7 +15694,7 @@ async function addZodShapes(graph, services) {
|
|
|
15554
15694
|
}
|
|
15555
15695
|
if (shape.fields.length > 0) {
|
|
15556
15696
|
const node = graph.getNodeAttributes(shape.infraId);
|
|
15557
|
-
if (node.type ===
|
|
15697
|
+
if (node.type === NodeType28.InfraNode) {
|
|
15558
15698
|
graph.replaceNodeAttributes(shape.infraId, {
|
|
15559
15699
|
...node,
|
|
15560
15700
|
columns: foldColumns(
|
|
@@ -15596,7 +15736,7 @@ async function addZodShapes(graph, services) {
|
|
|
15596
15736
|
}
|
|
15597
15737
|
|
|
15598
15738
|
// src/extract/firestore-rules.ts
|
|
15599
|
-
import { NodeType as
|
|
15739
|
+
import { NodeType as NodeType29 } from "@neat.is/types";
|
|
15600
15740
|
var FIRESTORE_COLLECTION_KIND = "firestore-collection";
|
|
15601
15741
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["write", "create", "update"]);
|
|
15602
15742
|
function stripComments(src) {
|
|
@@ -15767,7 +15907,7 @@ async function addFirestoreRules(graph, services) {
|
|
|
15767
15907
|
if (guards.size === 0) return { nodesAdded: 0, edgesAdded: 0 };
|
|
15768
15908
|
graph.forEachNode((id, attrs) => {
|
|
15769
15909
|
const node = attrs;
|
|
15770
|
-
if (node.type !==
|
|
15910
|
+
if (node.type !== NodeType29.InfraNode) return;
|
|
15771
15911
|
if (node.kind !== FIRESTORE_COLLECTION_KIND) return;
|
|
15772
15912
|
const fields = guards.get(collectionKeyFromName(node.name));
|
|
15773
15913
|
if (!fields || fields.size === 0) return;
|
|
@@ -15785,12 +15925,12 @@ import path68 from "path";
|
|
|
15785
15925
|
// src/extract/retire.ts
|
|
15786
15926
|
import { existsSync as existsSync2 } from "fs";
|
|
15787
15927
|
import path67 from "path";
|
|
15788
|
-
import { NodeType as
|
|
15928
|
+
import { NodeType as NodeType30, Provenance as Provenance23 } from "@neat.is/types";
|
|
15789
15929
|
function dropOrphanedFileNodes(graph, source) {
|
|
15790
15930
|
const orphans = [];
|
|
15791
15931
|
graph.forEachNode((id, attrs) => {
|
|
15792
15932
|
const node = attrs;
|
|
15793
|
-
if (node.type !==
|
|
15933
|
+
if (node.type !== NodeType30.FileNode) return;
|
|
15794
15934
|
if (source && node.source !== source) return;
|
|
15795
15935
|
if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
|
|
15796
15936
|
orphans.push(id);
|
|
@@ -15817,7 +15957,7 @@ function outOfScope(graph, edge, source) {
|
|
|
15817
15957
|
for (const endpoint2 of [edge.source, edge.target]) {
|
|
15818
15958
|
if (!graph.hasNode(endpoint2)) continue;
|
|
15819
15959
|
const node = graph.getNodeAttributes(endpoint2);
|
|
15820
|
-
if (node.type !==
|
|
15960
|
+
if (node.type !== NodeType30.FileNode) continue;
|
|
15821
15961
|
return node.source !== source;
|
|
15822
15962
|
}
|
|
15823
15963
|
return false;
|
|
@@ -15846,7 +15986,23 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = [], so
|
|
|
15846
15986
|
// src/extract/index.ts
|
|
15847
15987
|
var passQueue = Promise.resolve();
|
|
15848
15988
|
function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
15849
|
-
|
|
15989
|
+
invalidateSourceBaseline(graph, opts.source, "syncing");
|
|
15990
|
+
const pass = passQueue.then(async () => {
|
|
15991
|
+
const sourceGeneration = beginSourceExtraction(graph, opts.source, opts.sourceCommit);
|
|
15992
|
+
let result;
|
|
15993
|
+
try {
|
|
15994
|
+
result = await runExtractionPass(graph, scanPath, opts);
|
|
15995
|
+
return result;
|
|
15996
|
+
} finally {
|
|
15997
|
+
finishSourceExtraction(
|
|
15998
|
+
graph,
|
|
15999
|
+
sourceGeneration,
|
|
16000
|
+
opts.source,
|
|
16001
|
+
opts.sourceCommit,
|
|
16002
|
+
result ?? { extractionErrors: 1, skippedFiles: 0 }
|
|
16003
|
+
);
|
|
16004
|
+
}
|
|
16005
|
+
});
|
|
15850
16006
|
passQueue = pass.catch(() => {
|
|
15851
16007
|
});
|
|
15852
16008
|
return pass;
|
|
@@ -15943,7 +16099,7 @@ import {
|
|
|
15943
16099
|
databaseId as databaseId3,
|
|
15944
16100
|
DivergenceResultSchema,
|
|
15945
16101
|
EdgeType as EdgeType26,
|
|
15946
|
-
NodeType as
|
|
16102
|
+
NodeType as NodeType31,
|
|
15947
16103
|
parseEdgeId,
|
|
15948
16104
|
parseFileId,
|
|
15949
16105
|
parseSymbolId as parseSymbolId2,
|
|
@@ -15958,7 +16114,7 @@ function bucketSourceFor(graph, edge) {
|
|
|
15958
16114
|
const parsed = parseFileId(edge.source);
|
|
15959
16115
|
if (!parsed || !graph.hasNode(edge.target)) return edge.source;
|
|
15960
16116
|
const target = graph.getNodeAttributes(edge.target);
|
|
15961
|
-
if (target.type !==
|
|
16117
|
+
if (target.type !== NodeType31.DatabaseNode) return edge.source;
|
|
15962
16118
|
return serviceId14(parsed.service);
|
|
15963
16119
|
}
|
|
15964
16120
|
function bucketEdges(graph) {
|
|
@@ -15990,22 +16146,22 @@ function bucketEdges(graph) {
|
|
|
15990
16146
|
function nodeIsFrontier(graph, nodeId) {
|
|
15991
16147
|
if (!graph.hasNode(nodeId)) return false;
|
|
15992
16148
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
15993
|
-
return attrs.type ===
|
|
16149
|
+
return attrs.type === NodeType31.FrontierNode;
|
|
15994
16150
|
}
|
|
15995
16151
|
function nodeIsWebsocketChannel(graph, nodeId) {
|
|
15996
16152
|
if (!graph.hasNode(nodeId)) return false;
|
|
15997
16153
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
15998
|
-
return attrs.type ===
|
|
16154
|
+
return attrs.type === NodeType31.WebSocketChannelNode;
|
|
15999
16155
|
}
|
|
16000
16156
|
function nodeIsServerAction(graph, nodeId) {
|
|
16001
16157
|
if (!graph.hasNode(nodeId)) return false;
|
|
16002
16158
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
16003
|
-
return attrs.type ===
|
|
16159
|
+
return attrs.type === NodeType31.ServerActionNode;
|
|
16004
16160
|
}
|
|
16005
16161
|
function nodeIsSymbol(graph, nodeId) {
|
|
16006
16162
|
if (!graph.hasNode(nodeId)) return false;
|
|
16007
16163
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
16008
|
-
return attrs.type ===
|
|
16164
|
+
return attrs.type === NodeType31.SymbolNode;
|
|
16009
16165
|
}
|
|
16010
16166
|
function clampConfidence(n) {
|
|
16011
16167
|
if (!Number.isFinite(n)) return 0;
|
|
@@ -16090,7 +16246,7 @@ function detectHostMismatch(graph, svcId, svc) {
|
|
|
16090
16246
|
if (edge.type !== EdgeType26.CONNECTS_TO) continue;
|
|
16091
16247
|
if (edge.provenance !== Provenance24.OBSERVED) continue;
|
|
16092
16248
|
const target = graph.getNodeAttributes(edge.target);
|
|
16093
|
-
if (target.type !==
|
|
16249
|
+
if (target.type !== NodeType31.DatabaseNode) continue;
|
|
16094
16250
|
const observedHost = target.host?.trim();
|
|
16095
16251
|
if (!observedHost) continue;
|
|
16096
16252
|
if (observedHost === declaredHost) continue;
|
|
@@ -16115,7 +16271,7 @@ function detectCompatDivergences(graph, svcId, svc) {
|
|
|
16115
16271
|
if (edge.type !== EdgeType26.CONNECTS_TO) continue;
|
|
16116
16272
|
if (edge.provenance !== Provenance24.OBSERVED) continue;
|
|
16117
16273
|
const target = graph.getNodeAttributes(edge.target);
|
|
16118
|
-
if (target.type !==
|
|
16274
|
+
if (target.type !== NodeType31.DatabaseNode) continue;
|
|
16119
16275
|
for (const pair of compatPairs()) {
|
|
16120
16276
|
if (pair.engine !== target.engine) continue;
|
|
16121
16277
|
const declared = deps[pair.driver];
|
|
@@ -16480,7 +16636,7 @@ function involvesNode(d, nodeId) {
|
|
|
16480
16636
|
function datastoreEverObserved(graph, nodeId) {
|
|
16481
16637
|
if (!graph.hasNode(nodeId)) return false;
|
|
16482
16638
|
const n = graph.getNodeAttributes(nodeId);
|
|
16483
|
-
if (n.type ===
|
|
16639
|
+
if (n.type === NodeType31.DatabaseNode) {
|
|
16484
16640
|
const via = n.discoveredVia;
|
|
16485
16641
|
if (via === "otel" || via === "merged") return true;
|
|
16486
16642
|
}
|
|
@@ -16497,7 +16653,7 @@ function serviceHasObservedSameEngineStore(graph, buckets2, serviceId17, engine,
|
|
|
16497
16653
|
if (bucket.target === excludeTarget) continue;
|
|
16498
16654
|
if (!graph.hasNode(bucket.target)) continue;
|
|
16499
16655
|
const target = graph.getNodeAttributes(bucket.target);
|
|
16500
|
-
if (target.type !==
|
|
16656
|
+
if (target.type !== NodeType31.DatabaseNode) continue;
|
|
16501
16657
|
if (target.engine !== engine) continue;
|
|
16502
16658
|
if (bucket.observed || datastoreEverObserved(graph, bucket.target)) return true;
|
|
16503
16659
|
}
|
|
@@ -16510,7 +16666,7 @@ function dampenDeadCodeProbes(graph, buckets2, all) {
|
|
|
16510
16666
|
if (!d.extracted || d.edgeType !== EdgeType26.CONNECTS_TO) return d;
|
|
16511
16667
|
if (!graph.hasNode(d.target)) return d;
|
|
16512
16668
|
const target = graph.getNodeAttributes(d.target);
|
|
16513
|
-
if (target.type !==
|
|
16669
|
+
if (target.type !== NodeType31.DatabaseNode) return d;
|
|
16514
16670
|
if (d.extracted.evidence?.hostSource !== "literal") return d;
|
|
16515
16671
|
if (datastoreEverObserved(graph, d.target)) return d;
|
|
16516
16672
|
const engine = target.engine;
|
|
@@ -16550,14 +16706,14 @@ function computeDivergences(graph, opts = {}) {
|
|
|
16550
16706
|
}
|
|
16551
16707
|
graph.forEachNode((nodeId, attrs) => {
|
|
16552
16708
|
const n = attrs;
|
|
16553
|
-
if (n.type ===
|
|
16709
|
+
if (n.type === NodeType31.ServiceNode) {
|
|
16554
16710
|
const svc = n;
|
|
16555
16711
|
for (const d of detectHostMismatch(graph, nodeId, svc)) all.push(d);
|
|
16556
16712
|
for (const d of detectCompatDivergences(graph, nodeId, svc)) all.push(d);
|
|
16557
16713
|
for (const d of detectDeployDivergence(svc)) all.push(d);
|
|
16558
16714
|
return;
|
|
16559
16715
|
}
|
|
16560
|
-
if (n.type ===
|
|
16716
|
+
if (n.type === NodeType31.InfraNode && n.kind === "sql-table") {
|
|
16561
16717
|
for (const d of detectColumnDrift(n)) all.push(d);
|
|
16562
16718
|
}
|
|
16563
16719
|
});
|
|
@@ -16632,7 +16788,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
16632
16788
|
// src/persist.ts
|
|
16633
16789
|
import { promises as fs34 } from "fs";
|
|
16634
16790
|
import path69 from "path";
|
|
16635
|
-
import { NodeType as
|
|
16791
|
+
import { NodeType as NodeType32, Provenance as Provenance25, observedEdgeId as observedEdgeId2 } from "@neat.is/types";
|
|
16636
16792
|
var SCHEMA_VERSION = 7;
|
|
16637
16793
|
function migrateV1ToV2(payload) {
|
|
16638
16794
|
const nodes = payload.graph.nodes;
|
|
@@ -16656,7 +16812,7 @@ function migrateV5ToV6(payload) {
|
|
|
16656
16812
|
if (Array.isArray(nodes)) {
|
|
16657
16813
|
for (const node of nodes) {
|
|
16658
16814
|
const attrs = node.attributes;
|
|
16659
|
-
if (!attrs || attrs.type !==
|
|
16815
|
+
if (!attrs || attrs.type !== NodeType32.InfraNode) continue;
|
|
16660
16816
|
if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
|
|
16661
16817
|
if (!Array.isArray(attrs.columns)) attrs.columns = [];
|
|
16662
16818
|
}
|
|
@@ -17609,7 +17765,7 @@ function gradeIncidentCard(card) {
|
|
|
17609
17765
|
}
|
|
17610
17766
|
|
|
17611
17767
|
// src/ask.ts
|
|
17612
|
-
import { AskResultSchema, NodeType as
|
|
17768
|
+
import { AskResultSchema, NodeType as NodeType33, Provenance as Provenance27, serviceId as serviceId15 } from "@neat.is/types";
|
|
17613
17769
|
var DEFAULT_MAX_NODES = 3;
|
|
17614
17770
|
var MAX_FACTS_PER_SECTION = 6;
|
|
17615
17771
|
var INTENT_RULES = [
|
|
@@ -17845,11 +18001,11 @@ function idBody(id) {
|
|
|
17845
18001
|
return colon >= 0 ? id.slice(colon + 1) : id;
|
|
17846
18002
|
}
|
|
17847
18003
|
var TYPE_NOUNS = [
|
|
17848
|
-
{ nouns: ["database", "db", "table"], type:
|
|
17849
|
-
{ nouns: ["service", "api", "backend"], type:
|
|
17850
|
-
{ nouns: ["route", "endpoint"], type:
|
|
17851
|
-
{ nouns: ["file"], type:
|
|
17852
|
-
{ nouns: ["config"], type:
|
|
18004
|
+
{ nouns: ["database", "db", "table"], type: NodeType33.DatabaseNode },
|
|
18005
|
+
{ nouns: ["service", "api", "backend"], type: NodeType33.ServiceNode },
|
|
18006
|
+
{ nouns: ["route", "endpoint"], type: NodeType33.RouteNode },
|
|
18007
|
+
{ nouns: ["file"], type: NodeType33.FileNode },
|
|
18008
|
+
{ nouns: ["config"], type: NodeType33.ConfigNode }
|
|
17853
18009
|
];
|
|
17854
18010
|
var EMBED_MIN_SCORE = 0.35;
|
|
17855
18011
|
async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
@@ -17863,7 +18019,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
|
17863
18019
|
};
|
|
17864
18020
|
graph.forEachNode((id, attrs) => {
|
|
17865
18021
|
const node = attrs;
|
|
17866
|
-
if (node.type ===
|
|
18022
|
+
if (node.type === NodeType33.FrontierNode) return;
|
|
17867
18023
|
const name = nodeName(node);
|
|
17868
18024
|
const body = idBody(id);
|
|
17869
18025
|
const labelTokens = /* @__PURE__ */ new Set([...tokens(body), ...tokens(name)]);
|
|
@@ -17882,7 +18038,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
|
17882
18038
|
const res = await searchIndex.search(question, 10);
|
|
17883
18039
|
if (res.provider !== "substring") {
|
|
17884
18040
|
for (const m of res.matches) {
|
|
17885
|
-
if (m.node.type ===
|
|
18041
|
+
if (m.node.type === NodeType33.FrontierNode) continue;
|
|
17886
18042
|
if (!graph.hasNode(m.node.id)) continue;
|
|
17887
18043
|
const already = best.get(m.node.id);
|
|
17888
18044
|
if (!already && m.score < EMBED_MIN_SCORE) continue;
|
|
@@ -18015,10 +18171,10 @@ function buildBlastSection(graph, node) {
|
|
|
18015
18171
|
}
|
|
18016
18172
|
function buildDatabaseCallersSection(graph, node) {
|
|
18017
18173
|
const callers = getBlastRadius(graph, node).affectedNodes.filter((item) => {
|
|
18018
|
-
if (graph.getNodeAttributes(item.nodeId).type !==
|
|
18174
|
+
if (graph.getNodeAttributes(item.nodeId).type !== NodeType33.ServiceNode) return false;
|
|
18019
18175
|
return item.path.slice(1, -1).every((id) => {
|
|
18020
18176
|
const type = graph.getNodeAttributes(id).type;
|
|
18021
|
-
return type ===
|
|
18177
|
+
return type === NodeType33.FileNode || type === NodeType33.SymbolNode;
|
|
18022
18178
|
});
|
|
18023
18179
|
});
|
|
18024
18180
|
return {
|
|
@@ -18157,7 +18313,7 @@ function buildOverviewSections(graph, incidents) {
|
|
|
18157
18313
|
graph.forEachNode((_id, attrs) => {
|
|
18158
18314
|
const node = attrs;
|
|
18159
18315
|
nodeByType.set(node.type, (nodeByType.get(node.type) ?? 0) + 1);
|
|
18160
|
-
if (node.type ===
|
|
18316
|
+
if (node.type === NodeType33.ServiceNode) services.push(node.id);
|
|
18161
18317
|
});
|
|
18162
18318
|
const edgeByProv = /* @__PURE__ */ new Map();
|
|
18163
18319
|
graph.forEachEdge((_id, attrs) => {
|
|
@@ -18169,7 +18325,7 @@ function buildOverviewSections(graph, incidents) {
|
|
|
18169
18325
|
const shapeFacts = [
|
|
18170
18326
|
{ text: `${graph.order} nodes, ${graph.size} edges` },
|
|
18171
18327
|
{
|
|
18172
|
-
text: `${count(
|
|
18328
|
+
text: `${count(NodeType33.ServiceNode)} services, ${count(NodeType33.FileNode)} files, ${count(NodeType33.SymbolNode)} symbols, ${count(NodeType33.DatabaseNode)} databases`
|
|
18173
18329
|
}
|
|
18174
18330
|
];
|
|
18175
18331
|
for (const p of [Provenance27.EXTRACTED, Provenance27.OBSERVED, Provenance27.INFERRED, Provenance27.STALE]) {
|
|
@@ -18328,7 +18484,7 @@ async function askGraph(graph, question, opts = {}) {
|
|
|
18328
18484
|
let scope;
|
|
18329
18485
|
if (primary) {
|
|
18330
18486
|
scope = "node";
|
|
18331
|
-
const callersQuestion = intent === "dependencies" && graph.getNodeAttributes(primary).type ===
|
|
18487
|
+
const callersQuestion = intent === "dependencies" && graph.getNodeAttributes(primary).type === NodeType33.DatabaseNode && /\b(?:which|what)\s+services?\s+(?:talks?\s+to|connects?\s+to|uses?|hits?|calls?|reads?\s+from|writes?\s+to)\b/i.test(question);
|
|
18332
18488
|
if (callersQuestion) sections.push(buildDatabaseCallersSection(graph, primary));
|
|
18333
18489
|
for (const kind of SECTION_ORDER[intent]) {
|
|
18334
18490
|
if (callersQuestion && kind === "blast") continue;
|
|
@@ -18829,6 +18985,7 @@ var defaultCloneRepo = async (cloneUrl, ref, destDir) => {
|
|
|
18829
18985
|
});
|
|
18830
18986
|
try {
|
|
18831
18987
|
await Promise.race([clone, timeout]);
|
|
18988
|
+
return await git.resolveRef({ fs: fs40, dir: destDir, ref: "HEAD" });
|
|
18832
18989
|
} finally {
|
|
18833
18990
|
if (timer) clearTimeout(timer);
|
|
18834
18991
|
}
|
|
@@ -18880,6 +19037,19 @@ function scrubCloneToken(s) {
|
|
|
18880
19037
|
function needsSync(r) {
|
|
18881
19038
|
return r.syncStatus === void 0 || r.syncStatus === "syncing";
|
|
18882
19039
|
}
|
|
19040
|
+
function validRepoRow(row) {
|
|
19041
|
+
if (!row || typeof row !== "object") return false;
|
|
19042
|
+
const r = row;
|
|
19043
|
+
if (typeof r.owner !== "string" || typeof r.name !== "string" || typeof r.cloneUrl !== "string") return false;
|
|
19044
|
+
if (!/^[A-Za-z0-9_.-]+$/.test(r.owner) || !/^[A-Za-z0-9_.-]+$/.test(r.name)) return false;
|
|
19045
|
+
if (r.syncStatus !== void 0 && !["syncing", "synced", "failed"].includes(r.syncStatus)) return false;
|
|
19046
|
+
try {
|
|
19047
|
+
const url = new URL(r.cloneUrl);
|
|
19048
|
+
return url.protocol === "https:" && url.hostname === "github.com" && !url.port && !url.search && !url.hash && url.pathname === `/${r.owner}/${r.name}.git`;
|
|
19049
|
+
} catch {
|
|
19050
|
+
return false;
|
|
19051
|
+
}
|
|
19052
|
+
}
|
|
18883
19053
|
async function syncOneRepo(r, input) {
|
|
18884
19054
|
const { deps, graph } = input;
|
|
18885
19055
|
const cloneRepo = input.cloneRepo ?? defaultCloneRepo;
|
|
@@ -18888,20 +19058,30 @@ async function syncOneRepo(r, input) {
|
|
|
18888
19058
|
const tmpRoot = input.tmpRoot ?? os3.tmpdir();
|
|
18889
19059
|
let dir;
|
|
18890
19060
|
try {
|
|
19061
|
+
invalidateSourceBaseline(graph, label, "syncing");
|
|
18891
19062
|
dir = await mkdtemp(path73.join(tmpRoot, "neat-repo-"));
|
|
18892
19063
|
await cpPostStatus(deps, r.owner, r.name, { syncStatus: "syncing", detail: "cloning" }).catch(() => {
|
|
18893
19064
|
});
|
|
18894
|
-
await cloneRepo(r.cloneUrl, r.defaultBranch, dir);
|
|
18895
|
-
const extracted = await extract(graph, dir, {
|
|
19065
|
+
const sha = await cloneRepo(r.cloneUrl, r.defaultBranch, dir);
|
|
19066
|
+
const extracted = await extract(graph, dir, {
|
|
19067
|
+
source: label,
|
|
19068
|
+
...typeof sha === "string" ? { sourceCommit: { repository: label, sha } } : {}
|
|
19069
|
+
});
|
|
19070
|
+
input.onExtracted?.(label);
|
|
19071
|
+
const errors = extracted?.extractionErrors ?? 0;
|
|
19072
|
+
const skipped = extracted?.skippedFiles ?? 0;
|
|
19073
|
+
const incomplete = errors > 0 || skipped > 0;
|
|
19074
|
+
if (incomplete) invalidateSourceBaseline(graph, label);
|
|
18896
19075
|
const nodes = extracted?.nodesAdded ?? 0;
|
|
18897
19076
|
const edges = extracted?.edgesAdded ?? 0;
|
|
18898
19077
|
await cpPostStatus(deps, r.owner, r.name, {
|
|
18899
19078
|
syncStatus: "synced",
|
|
18900
|
-
detail: `extracted ${nodes} node${nodes === 1 ? "" : "s"}, ${edges} edge${edges === 1 ? "" : "s"}
|
|
19079
|
+
detail: `extracted ${nodes} node${nodes === 1 ? "" : "s"}, ${edges} edge${edges === 1 ? "" : "s"}` + (incomplete ? ` (incomplete: ${errors} errors, ${skipped} skipped files)` : ""),
|
|
18901
19080
|
lastSyncAt: new Date(input.now?.() ?? Date.now()).toISOString()
|
|
18902
19081
|
});
|
|
18903
19082
|
return true;
|
|
18904
19083
|
} catch (err) {
|
|
19084
|
+
invalidateSourceBaseline(graph, label);
|
|
18905
19085
|
input.onError?.(label, err);
|
|
18906
19086
|
await cpPostStatus(deps, r.owner, r.name, {
|
|
18907
19087
|
syncStatus: "failed",
|
|
@@ -18920,13 +19100,30 @@ async function runRepoSyncPassCounted(input) {
|
|
|
18920
19100
|
try {
|
|
18921
19101
|
repos = await cpGet(`/internal/projects/${input.deps.projectId}/repos`, input.deps);
|
|
18922
19102
|
} catch (err) {
|
|
19103
|
+
invalidateSourceBaseline(input.graph);
|
|
18923
19104
|
input.onSkip?.("(all)", `control plane repo list unreadable \u2014 ${err.message}`);
|
|
18924
19105
|
return counts;
|
|
18925
19106
|
}
|
|
18926
|
-
if (!Array.isArray(repos))
|
|
19107
|
+
if (!Array.isArray(repos)) {
|
|
19108
|
+
invalidateSourceBaseline(input.graph);
|
|
19109
|
+
return counts;
|
|
19110
|
+
}
|
|
18927
19111
|
counts.listed = true;
|
|
18928
|
-
|
|
18929
|
-
|
|
19112
|
+
const validRepos = repos.filter(validRepoRow);
|
|
19113
|
+
const invalidCount = repos.length - validRepos.length;
|
|
19114
|
+
if (invalidCount) {
|
|
19115
|
+
counts.failed += invalidCount;
|
|
19116
|
+
for (let index = 0; index < invalidCount; index++) {
|
|
19117
|
+
input.onSkip?.("(invalid)", "control plane repo row invalid");
|
|
19118
|
+
}
|
|
19119
|
+
}
|
|
19120
|
+
retainSourceBaselines(input.graph, validRepos.map((r) => `${r.owner}/${r.name}`));
|
|
19121
|
+
for (const r of validRepos) {
|
|
19122
|
+
if (r.syncStatus === "failed") invalidateSourceBaseline(input.graph, `${r.owner}/${r.name}`);
|
|
19123
|
+
}
|
|
19124
|
+
for (const r of validRepos) {
|
|
19125
|
+
const forced = typeof input.forceResync === "function" ? input.forceResync(`${r.owner}/${r.name}`) : input.forceResync === true;
|
|
19126
|
+
if (!forced && !needsSync(r)) continue;
|
|
18930
19127
|
if (await syncOneRepo(r, input)) counts.synced++;
|
|
18931
19128
|
else counts.failed++;
|
|
18932
19129
|
}
|
|
@@ -18939,14 +19136,20 @@ async function startRepoSync(input) {
|
|
|
18939
19136
|
let inFlight = null;
|
|
18940
19137
|
let again = false;
|
|
18941
19138
|
let lastPass;
|
|
18942
|
-
|
|
19139
|
+
const bootExtracted = /* @__PURE__ */ new Set();
|
|
18943
19140
|
const run = async () => {
|
|
18944
19141
|
try {
|
|
18945
19142
|
do {
|
|
18946
19143
|
again = false;
|
|
18947
19144
|
const startedAt = new Date(now()).toISOString();
|
|
18948
|
-
const counts = await runRepoSyncPassCounted({
|
|
18949
|
-
|
|
19145
|
+
const counts = await runRepoSyncPassCounted({
|
|
19146
|
+
...input,
|
|
19147
|
+
forceResync: (repo) => !bootExtracted.has(repo),
|
|
19148
|
+
onExtracted: (repo) => {
|
|
19149
|
+
bootExtracted.add(repo);
|
|
19150
|
+
input.onExtracted?.(repo);
|
|
19151
|
+
}
|
|
19152
|
+
});
|
|
18950
19153
|
lastPass = { ...counts, startedAt, finishedAt: new Date(now()).toISOString() };
|
|
18951
19154
|
} while (again && !stopped);
|
|
18952
19155
|
} finally {
|
|
@@ -19482,7 +19685,7 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
|
|
|
19482
19685
|
}
|
|
19483
19686
|
|
|
19484
19687
|
// src/connectors/index.ts
|
|
19485
|
-
import { NodeType as
|
|
19688
|
+
import { NodeType as NodeType34, parseFileId as parseFileId2, Provenance as Provenance28 } from "@neat.is/types";
|
|
19486
19689
|
var NO_ENV = "unknown";
|
|
19487
19690
|
function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
19488
19691
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
@@ -19501,7 +19704,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
|
19501
19704
|
function routeCallSiteFor(graph, targetNodeId) {
|
|
19502
19705
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
19503
19706
|
const attrs = graph.getNodeAttributes(targetNodeId);
|
|
19504
|
-
if (attrs.type !==
|
|
19707
|
+
if (attrs.type !== NodeType34.RouteNode || !attrs.path) return void 0;
|
|
19505
19708
|
const site = { relPath: attrs.path };
|
|
19506
19709
|
if (attrs.line !== void 0) site.line = attrs.line;
|
|
19507
19710
|
return site;
|
|
@@ -20317,7 +20520,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
|
|
|
20317
20520
|
}
|
|
20318
20521
|
|
|
20319
20522
|
// src/connectors/railway/index.ts
|
|
20320
|
-
import { EdgeType as EdgeType28, NodeType as
|
|
20523
|
+
import { EdgeType as EdgeType28, NodeType as NodeType35, serviceId as serviceId16 } from "@neat.is/types";
|
|
20321
20524
|
|
|
20322
20525
|
// src/connectors/railway/client.ts
|
|
20323
20526
|
var DEFAULT_RAILWAY_API_URL = "https://backboard.railway.com/graphql/v2";
|
|
@@ -20467,7 +20670,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
|
|
|
20467
20670
|
const out = [];
|
|
20468
20671
|
graph.forEachNode((_id, attrs) => {
|
|
20469
20672
|
const node = attrs;
|
|
20470
|
-
if (node.type !==
|
|
20673
|
+
if (node.type !== NodeType35.RouteNode) return;
|
|
20471
20674
|
const route = attrs;
|
|
20472
20675
|
if (route.service !== serviceName) return;
|
|
20473
20676
|
out.push({
|
|
@@ -20758,10 +20961,10 @@ function mapLogEntriesToSignals(entries) {
|
|
|
20758
20961
|
}
|
|
20759
20962
|
|
|
20760
20963
|
// src/connectors/firebase/resolve.ts
|
|
20761
|
-
import { NodeType as
|
|
20964
|
+
import { NodeType as NodeType37, EdgeType as EdgeType29 } from "@neat.is/types";
|
|
20762
20965
|
|
|
20763
20966
|
// src/connectors/infer-service.ts
|
|
20764
|
-
import { NodeType as
|
|
20967
|
+
import { NodeType as NodeType36 } from "@neat.is/types";
|
|
20765
20968
|
function normalizeName(name) {
|
|
20766
20969
|
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
20767
20970
|
}
|
|
@@ -20772,11 +20975,11 @@ function inferServiceName(graph, resourceName, method, path76) {
|
|
|
20772
20975
|
const owners = /* @__PURE__ */ new Set();
|
|
20773
20976
|
graph.forEachNode((_id, attrs) => {
|
|
20774
20977
|
const node = attrs;
|
|
20775
|
-
if (node.type ===
|
|
20978
|
+
if (node.type === NodeType36.ServiceNode && typeof node.name === "string") {
|
|
20776
20979
|
services.push(node.name);
|
|
20777
20980
|
return;
|
|
20778
20981
|
}
|
|
20779
|
-
if (node.type !==
|
|
20982
|
+
if (node.type !== NodeType36.RouteNode) return;
|
|
20780
20983
|
const route = attrs;
|
|
20781
20984
|
if (!route.pathTemplate || normalizePathTemplate(route.pathTemplate) !== wantedPath) return;
|
|
20782
20985
|
const routeMethod = route.method.toUpperCase();
|
|
@@ -20803,7 +21006,7 @@ function routeEntriesFor(graph, serviceName) {
|
|
|
20803
21006
|
const entries = [];
|
|
20804
21007
|
graph.forEachNode((_id, attrs) => {
|
|
20805
21008
|
const node = attrs;
|
|
20806
|
-
if (node.type !==
|
|
21009
|
+
if (node.type !== NodeType37.RouteNode) return;
|
|
20807
21010
|
const route = attrs;
|
|
20808
21011
|
if (route.service !== serviceName) return;
|
|
20809
21012
|
entries.push({
|
|
@@ -20864,7 +21067,7 @@ function createFirebaseConnector(graph, serviceMap) {
|
|
|
20864
21067
|
}
|
|
20865
21068
|
|
|
20866
21069
|
// src/connectors/cloudflare/connector.ts
|
|
20867
|
-
import { EdgeType as EdgeType30, NodeType as
|
|
21070
|
+
import { EdgeType as EdgeType30, NodeType as NodeType38, fileId as fileId5, infraId as infraId23 } from "@neat.is/types";
|
|
20868
21071
|
|
|
20869
21072
|
// src/connectors/cloudflare/client.ts
|
|
20870
21073
|
import { randomUUID } from "crypto";
|
|
@@ -21023,7 +21226,7 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
21023
21226
|
graph.forEachNode((id, attrs) => {
|
|
21024
21227
|
if (found) return;
|
|
21025
21228
|
const a = attrs;
|
|
21026
|
-
if (a.type ===
|
|
21229
|
+
if (a.type === NodeType38.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
|
|
21027
21230
|
found = id;
|
|
21028
21231
|
}
|
|
21029
21232
|
});
|
|
@@ -21035,7 +21238,7 @@ function findMatchingRouteNode(graph, serviceName, method, path76) {
|
|
|
21035
21238
|
graph.forEachNode((id, attrs) => {
|
|
21036
21239
|
if (found) return;
|
|
21037
21240
|
const a = attrs;
|
|
21038
|
-
if (a.type !==
|
|
21241
|
+
if (a.type !== NodeType38.RouteNode || a.service !== serviceName) return;
|
|
21039
21242
|
if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
|
|
21040
21243
|
const routeMethod = (a.method ?? "").toUpperCase();
|
|
21041
21244
|
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
@@ -21434,14 +21637,14 @@ function mapLogEntriesToSignals2(entries) {
|
|
|
21434
21637
|
}
|
|
21435
21638
|
|
|
21436
21639
|
// src/connectors/cloud-run/resolve.ts
|
|
21437
|
-
import { EdgeType as EdgeType32, NodeType as
|
|
21640
|
+
import { EdgeType as EdgeType32, NodeType as NodeType39, infraId as infraId25 } from "@neat.is/types";
|
|
21438
21641
|
var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
|
|
21439
21642
|
function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
|
|
21440
21643
|
let found = null;
|
|
21441
21644
|
graph.forEachNode((_id, attrs) => {
|
|
21442
21645
|
if (found) return;
|
|
21443
21646
|
const node = attrs;
|
|
21444
|
-
if (node.type !==
|
|
21647
|
+
if (node.type !== NodeType39.RouteNode) return;
|
|
21445
21648
|
const route = attrs;
|
|
21446
21649
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
21447
21650
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -21645,14 +21848,14 @@ function mapLogEntriesToSignals3(entries) {
|
|
|
21645
21848
|
}
|
|
21646
21849
|
|
|
21647
21850
|
// src/connectors/gcp-lb/resolve.ts
|
|
21648
|
-
import { EdgeType as EdgeType33, NodeType as
|
|
21851
|
+
import { EdgeType as EdgeType33, NodeType as NodeType40, infraId as infraId26 } from "@neat.is/types";
|
|
21649
21852
|
var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
|
|
21650
21853
|
function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
|
|
21651
21854
|
let found = null;
|
|
21652
21855
|
graph.forEachNode((_id, attrs) => {
|
|
21653
21856
|
if (found) return;
|
|
21654
21857
|
const node = attrs;
|
|
21655
|
-
if (node.type !==
|
|
21858
|
+
if (node.type !== NodeType40.RouteNode) return;
|
|
21656
21859
|
const route = attrs;
|
|
21657
21860
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
21658
21861
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -21723,7 +21926,7 @@ function createGcpLbConnector(graph, config = {}) {
|
|
|
21723
21926
|
}
|
|
21724
21927
|
|
|
21725
21928
|
// src/connectors/render/index.ts
|
|
21726
|
-
import { EdgeType as EdgeType34, NodeType as
|
|
21929
|
+
import { EdgeType as EdgeType34, NodeType as NodeType41 } from "@neat.is/types";
|
|
21727
21930
|
|
|
21728
21931
|
// src/connectors/render/types.ts
|
|
21729
21932
|
function readRenderToken(credentials) {
|
|
@@ -21799,7 +22002,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
21799
22002
|
const out = [];
|
|
21800
22003
|
graph.forEachNode((_id, attrs) => {
|
|
21801
22004
|
const node = attrs;
|
|
21802
|
-
if (node.type !==
|
|
22005
|
+
if (node.type !== NodeType41.RouteNode) return;
|
|
21803
22006
|
const route = attrs;
|
|
21804
22007
|
if (route.service !== serviceName) return;
|
|
21805
22008
|
out.push({
|
|
@@ -22283,7 +22486,7 @@ function mapBuildsToSignals(builds, serviceName) {
|
|
|
22283
22486
|
}
|
|
22284
22487
|
|
|
22285
22488
|
// src/connectors/eas/resolve.ts
|
|
22286
|
-
import { EdgeType as EdgeType36, NodeType as
|
|
22489
|
+
import { EdgeType as EdgeType36, NodeType as NodeType42, parseFileId as parseFileId3 } from "@neat.is/types";
|
|
22287
22490
|
var NO_ENV2 = "unknown";
|
|
22288
22491
|
var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
|
|
22289
22492
|
var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
|
|
@@ -22311,7 +22514,7 @@ function findConfigNode(graph, basenames, serviceName) {
|
|
|
22311
22514
|
graph.forEachNode((id, attrs) => {
|
|
22312
22515
|
if (scoped) return;
|
|
22313
22516
|
const node = attrs;
|
|
22314
|
-
if (node.type !==
|
|
22517
|
+
if (node.type !== NodeType42.ConfigNode) return;
|
|
22315
22518
|
if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
|
|
22316
22519
|
if (anyMatch === null) anyMatch = id;
|
|
22317
22520
|
if (configNodeService(graph, id) === serviceName) scoped = id;
|
|
@@ -23056,7 +23259,7 @@ function serializeGraph(graph) {
|
|
|
23056
23259
|
graph.forEachEdge((_id, attrs) => {
|
|
23057
23260
|
edges.push(attrs);
|
|
23058
23261
|
});
|
|
23059
|
-
return { nodes, edges };
|
|
23262
|
+
return { nodes, edges, sourceBaselines: readSourceBaselines(graph) };
|
|
23060
23263
|
}
|
|
23061
23264
|
function projectFromReq(req, singleProject, registry) {
|
|
23062
23265
|
const params = req.params;
|
|
@@ -24157,4 +24360,4 @@ export {
|
|
|
24157
24360
|
deprovisionConnector,
|
|
24158
24361
|
buildApi
|
|
24159
24362
|
};
|
|
24160
|
-
//# sourceMappingURL=chunk-
|
|
24363
|
+
//# sourceMappingURL=chunk-MW2XYLCS.js.map
|