@neat.is/core 0.10.1-dev.20260928 → 0.10.2
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-ERE47MCR.js → chunk-5SJHA5ZH.js} +2 -2
- package/dist/{chunk-HVBD4ULO.js → chunk-CAGAHYDB.js} +3 -3
- package/dist/{chunk-GDGUY4T6.js → chunk-M7CGATVC.js} +3 -2
- package/dist/{chunk-CNOJ4T6I.js → chunk-TXKOAART.js} +797 -563
- package/dist/chunk-TXKOAART.js.map +1 -0
- package/dist/cli.cjs +1858 -1110
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +6 -2
- package/dist/cli.d.ts +6 -2
- package/dist/cli.js +802 -289
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +838 -621
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +849 -632
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-Y5K4WGWO.js → otel-grpc-CU73Y5WT.js} +3 -3
- package/dist/server.cjs +712 -525
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +3 -3
- package/dist/chunk-CNOJ4T6I.js.map +0 -1
- /package/dist/{chunk-ERE47MCR.js.map → chunk-5SJHA5ZH.js.map} +0 -0
- /package/dist/{chunk-HVBD4ULO.js.map → chunk-CAGAHYDB.js.map} +0 -0
- /package/dist/{chunk-GDGUY4T6.js.map → chunk-M7CGATVC.js.map} +0 -0
- /package/dist/{otel-grpc-Y5K4WGWO.js.map → otel-grpc-CU73Y5WT.js.map} +0 -0
package/dist/neatd.cjs
CHANGED
|
@@ -61,8 +61,8 @@ function mountBearerAuth(app, opts) {
|
|
|
61
61
|
]);
|
|
62
62
|
const publicRead = opts.publicRead === true;
|
|
63
63
|
app.addHook("preHandler", (req2, reply, done) => {
|
|
64
|
-
const
|
|
65
|
-
if (exactUnauthPaths.has(
|
|
64
|
+
const path82 = (req2.url.split("?")[0] ?? "").replace(/\/+$/, "");
|
|
65
|
+
if (exactUnauthPaths.has(path82) || PROJECT_SCOPED_UNAUTH_PATTERN.test(path82)) {
|
|
66
66
|
done();
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
@@ -194,8 +194,8 @@ function reshapeGrpcRequest(req2) {
|
|
|
194
194
|
};
|
|
195
195
|
}
|
|
196
196
|
function resolveProtoRoot() {
|
|
197
|
-
const here =
|
|
198
|
-
return
|
|
197
|
+
const here = import_node_path54.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
198
|
+
return import_node_path54.default.resolve(here, "..", "proto");
|
|
199
199
|
}
|
|
200
200
|
function loadTraceService() {
|
|
201
201
|
const protoRoot = resolveProtoRoot();
|
|
@@ -263,13 +263,13 @@ async function startOtelGrpcReceiver(opts) {
|
|
|
263
263
|
})
|
|
264
264
|
};
|
|
265
265
|
}
|
|
266
|
-
var import_node_url,
|
|
266
|
+
var import_node_url, import_node_path54, import_node_crypto2, grpc, protoLoader;
|
|
267
267
|
var init_otel_grpc = __esm({
|
|
268
268
|
"src/otel-grpc.ts"() {
|
|
269
269
|
"use strict";
|
|
270
270
|
init_cjs_shims();
|
|
271
271
|
import_node_url = require("url");
|
|
272
|
-
|
|
272
|
+
import_node_path54 = __toESM(require("path"), 1);
|
|
273
273
|
import_node_crypto2 = require("crypto");
|
|
274
274
|
grpc = __toESM(require("@grpc/grpc-js"), 1);
|
|
275
275
|
protoLoader = __toESM(require("@grpc/proto-loader"), 1);
|
|
@@ -415,8 +415,8 @@ function websocketChannelPathOf(attrs) {
|
|
|
415
415
|
const v = attrs[key];
|
|
416
416
|
if (typeof v === "string" && v.length > 0) {
|
|
417
417
|
const q = v.indexOf("?");
|
|
418
|
-
const
|
|
419
|
-
if (
|
|
418
|
+
const path82 = q === -1 ? v : v.slice(0, q);
|
|
419
|
+
if (path82.length > 0) return path82;
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
422
|
return void 0;
|
|
@@ -478,10 +478,10 @@ function parseOtlpRequest(body) {
|
|
|
478
478
|
return out;
|
|
479
479
|
}
|
|
480
480
|
function loadProtoRoot() {
|
|
481
|
-
const here =
|
|
482
|
-
const protoRoot =
|
|
481
|
+
const here = import_node_path55.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
482
|
+
const protoRoot = import_node_path55.default.resolve(here, "..", "proto");
|
|
483
483
|
const root = new import_protobufjs.default.Root();
|
|
484
|
-
root.resolvePath = (_origin, target) =>
|
|
484
|
+
root.resolvePath = (_origin, target) => import_node_path55.default.resolve(protoRoot, target);
|
|
485
485
|
root.loadSync(
|
|
486
486
|
"opentelemetry/proto/collector/trace/v1/trace_service.proto",
|
|
487
487
|
{ keepCase: true }
|
|
@@ -759,12 +759,12 @@ async function listenSteppingOtlp(app, requestedPort, host) {
|
|
|
759
759
|
}
|
|
760
760
|
}
|
|
761
761
|
}
|
|
762
|
-
var
|
|
762
|
+
var import_node_path55, import_node_url2, import_node_zlib, import_fastify, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody, OTLP_STEP_ATTEMPTS, OTLP_STEP_STRIDE;
|
|
763
763
|
var init_otel = __esm({
|
|
764
764
|
"src/otel.ts"() {
|
|
765
765
|
"use strict";
|
|
766
766
|
init_cjs_shims();
|
|
767
|
-
|
|
767
|
+
import_node_path55 = __toESM(require("path"), 1);
|
|
768
768
|
import_node_url2 = require("url");
|
|
769
769
|
import_node_zlib = __toESM(require("zlib"), 1);
|
|
770
770
|
import_fastify = __toESM(require("fastify"), 1);
|
|
@@ -788,14 +788,14 @@ __export(neatd_exports, {
|
|
|
788
788
|
});
|
|
789
789
|
module.exports = __toCommonJS(neatd_exports);
|
|
790
790
|
init_cjs_shims();
|
|
791
|
-
var
|
|
792
|
-
var
|
|
791
|
+
var import_node_fs44 = require("fs");
|
|
792
|
+
var import_node_path82 = __toESM(require("path"), 1);
|
|
793
793
|
var import_node_module2 = require("module");
|
|
794
794
|
|
|
795
795
|
// src/daemon.ts
|
|
796
796
|
init_cjs_shims();
|
|
797
|
-
var
|
|
798
|
-
var
|
|
797
|
+
var import_node_fs42 = require("fs");
|
|
798
|
+
var import_node_path80 = __toESM(require("path"), 1);
|
|
799
799
|
var import_node_module = require("module");
|
|
800
800
|
|
|
801
801
|
// src/graph.ts
|
|
@@ -831,8 +831,8 @@ init_cjs_shims();
|
|
|
831
831
|
|
|
832
832
|
// src/ingest.ts
|
|
833
833
|
init_cjs_shims();
|
|
834
|
-
var
|
|
835
|
-
var
|
|
834
|
+
var import_node_fs8 = require("fs");
|
|
835
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
836
836
|
var sourceMapJs = __toESM(require("source-map-js"), 1);
|
|
837
837
|
|
|
838
838
|
// src/policy.ts
|
|
@@ -1337,19 +1337,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
1337
1337
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
1338
1338
|
let best = { path: [start], edges: [] };
|
|
1339
1339
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
1340
|
-
function step(node,
|
|
1341
|
-
if (
|
|
1342
|
-
best = { path: [...
|
|
1340
|
+
function step(node, path82, edges) {
|
|
1341
|
+
if (path82.length > best.path.length) {
|
|
1342
|
+
best = { path: [...path82], edges: [...edges] };
|
|
1343
1343
|
}
|
|
1344
|
-
if (
|
|
1344
|
+
if (path82.length - 1 >= maxDepth) return;
|
|
1345
1345
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
1346
1346
|
for (const [srcId, edge] of incoming) {
|
|
1347
1347
|
if (visited.has(srcId)) continue;
|
|
1348
1348
|
visited.add(srcId);
|
|
1349
|
-
|
|
1349
|
+
path82.push(srcId);
|
|
1350
1350
|
edges.push(edge);
|
|
1351
|
-
step(srcId,
|
|
1352
|
-
|
|
1351
|
+
step(srcId, path82, edges);
|
|
1352
|
+
path82.pop();
|
|
1353
1353
|
edges.pop();
|
|
1354
1354
|
visited.delete(srcId);
|
|
1355
1355
|
}
|
|
@@ -1564,20 +1564,20 @@ function dominantFailingCall(graph, serviceId17, visited) {
|
|
|
1564
1564
|
return best;
|
|
1565
1565
|
}
|
|
1566
1566
|
function followFailingCallChain(graph, originServiceId, maxDepth) {
|
|
1567
|
-
const
|
|
1567
|
+
const path82 = [originServiceId];
|
|
1568
1568
|
const edges = [];
|
|
1569
1569
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
1570
1570
|
let current = originServiceId;
|
|
1571
1571
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
1572
1572
|
const hop = dominantFailingCall(graph, current, visited);
|
|
1573
1573
|
if (!hop) break;
|
|
1574
|
-
|
|
1574
|
+
path82.push(hop.nextService);
|
|
1575
1575
|
edges.push(hop.edge);
|
|
1576
1576
|
visited.add(hop.nextService);
|
|
1577
1577
|
current = hop.nextService;
|
|
1578
1578
|
}
|
|
1579
1579
|
if (edges.length === 0) return null;
|
|
1580
|
-
return { path:
|
|
1580
|
+
return { path: path82, edges, culprit: current };
|
|
1581
1581
|
}
|
|
1582
1582
|
function isStaleCallEdge(e) {
|
|
1583
1583
|
return e.type === import_types.EdgeType.CALLS && e.provenance === import_types.Provenance.STALE;
|
|
@@ -1613,26 +1613,26 @@ function dominantStaleCall(graph, serviceId17, visited) {
|
|
|
1613
1613
|
return best;
|
|
1614
1614
|
}
|
|
1615
1615
|
function followStaleCallChain(graph, originServiceId, maxDepth) {
|
|
1616
|
-
const
|
|
1616
|
+
const path82 = [originServiceId];
|
|
1617
1617
|
const edges = [];
|
|
1618
1618
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
1619
1619
|
let current = originServiceId;
|
|
1620
1620
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
1621
1621
|
const hop = dominantStaleCall(graph, current, visited);
|
|
1622
1622
|
if (!hop) break;
|
|
1623
|
-
|
|
1623
|
+
path82.push(hop.nextService);
|
|
1624
1624
|
edges.push(hop.edge);
|
|
1625
1625
|
visited.add(hop.nextService);
|
|
1626
1626
|
current = hop.nextService;
|
|
1627
1627
|
}
|
|
1628
1628
|
if (edges.length === 0) return null;
|
|
1629
|
-
return { path:
|
|
1629
|
+
return { path: path82, edges, culprit: current };
|
|
1630
1630
|
}
|
|
1631
1631
|
function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
1632
1632
|
const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
|
|
1633
1633
|
if (!chain) return null;
|
|
1634
1634
|
const culprit = chain.culprit;
|
|
1635
|
-
const
|
|
1635
|
+
const path82 = [...chain.path];
|
|
1636
1636
|
const edgeProvenances = chain.edges.map((e) => e.provenance);
|
|
1637
1637
|
const baseConfidence = confidenceFromMix(chain.edges);
|
|
1638
1638
|
const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
|
|
@@ -1640,14 +1640,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
1640
1640
|
if (loc) {
|
|
1641
1641
|
let rootCauseNode = culprit;
|
|
1642
1642
|
if (loc.fileNode) {
|
|
1643
|
-
|
|
1643
|
+
path82.push(loc.fileNode);
|
|
1644
1644
|
edgeProvenances.push(import_types.Provenance.OBSERVED);
|
|
1645
1645
|
rootCauseNode = loc.fileNode;
|
|
1646
1646
|
}
|
|
1647
1647
|
return import_types.RootCauseResultSchema.parse({
|
|
1648
1648
|
rootCauseNode,
|
|
1649
1649
|
rootCauseReason: loc.rootCauseReason,
|
|
1650
|
-
traversalPath:
|
|
1650
|
+
traversalPath: path82,
|
|
1651
1651
|
edgeProvenances,
|
|
1652
1652
|
confidence,
|
|
1653
1653
|
...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
|
|
@@ -1659,7 +1659,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
1659
1659
|
return import_types.RootCauseResultSchema.parse({
|
|
1660
1660
|
rootCauseNode: culprit,
|
|
1661
1661
|
rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
|
|
1662
|
-
traversalPath:
|
|
1662
|
+
traversalPath: path82,
|
|
1663
1663
|
edgeProvenances,
|
|
1664
1664
|
confidence,
|
|
1665
1665
|
fixRecommendation: `Inspect ${culpritName}'s failing handler`
|
|
@@ -2312,10 +2312,10 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
|
|
|
2312
2312
|
traversalPath = staleChain.path;
|
|
2313
2313
|
edgeProvenances = staleChain.edges.map((e) => e.provenance);
|
|
2314
2314
|
} else if (top.node !== seedNode) {
|
|
2315
|
-
const
|
|
2316
|
-
if (
|
|
2317
|
-
traversalPath =
|
|
2318
|
-
edgeProvenances =
|
|
2315
|
+
const path82 = findPath(graph, errorNodeId, top.node, "up", ROOT_CAUSE_MAX_DEPTH);
|
|
2316
|
+
if (path82) {
|
|
2317
|
+
traversalPath = path82.nodes;
|
|
2318
|
+
edgeProvenances = path82.edges.map((e) => e.provenance);
|
|
2319
2319
|
} else {
|
|
2320
2320
|
traversalPath = [errorNodeId, top.node];
|
|
2321
2321
|
edgeProvenances = [top.provenance ?? import_types.Provenance.OBSERVED];
|
|
@@ -2854,7 +2854,7 @@ var import_types8 = require("@neat.is/types");
|
|
|
2854
2854
|
|
|
2855
2855
|
// src/extract/routes.ts
|
|
2856
2856
|
init_cjs_shims();
|
|
2857
|
-
var
|
|
2857
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
2858
2858
|
var import_tree_sitter2 = __toESM(require("tree-sitter"), 1);
|
|
2859
2859
|
var import_tree_sitter_javascript2 = __toESM(require("tree-sitter-javascript"), 1);
|
|
2860
2860
|
var import_tree_sitter_python2 = __toESM(require("tree-sitter-python"), 1);
|
|
@@ -2880,6 +2880,17 @@ var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
|
2880
2880
|
"dist",
|
|
2881
2881
|
"build",
|
|
2882
2882
|
".next",
|
|
2883
|
+
// `_next` is the *emitted* half of the pair above — `next build`'s output as
|
|
2884
|
+
// it is served or exported. `.next` was listed and `_next` wasn't, so an
|
|
2885
|
+
// exported bundle walked in as first-party source: minified chunks, one file
|
|
2886
|
+
// per line, hundreds of KB each (#1254).
|
|
2887
|
+
"_next",
|
|
2888
|
+
// Agent scratch space. `.claude/worktrees/` holds a full checkout per agent
|
|
2889
|
+
// session, so walking it re-extracts the whole repo once per worktree — and
|
|
2890
|
+
// pulls in whatever build output those checkouts happen to carry. It is
|
|
2891
|
+
// gitignored in practice, but the file walk doesn't read .gitignore, so the
|
|
2892
|
+
// name has to be listed here.
|
|
2893
|
+
".claude",
|
|
2883
2894
|
// Python virtualenv shapes (issue #344). Walking into a venv pulls in the
|
|
2884
2895
|
// entire CPython stdlib + every installed package as if it were first-party
|
|
2885
2896
|
// service code — 20k+ files, none of which the user wrote. The shape names
|
|
@@ -3111,6 +3122,15 @@ function noteExtractedDropped(edge) {
|
|
|
3111
3122
|
function drainDroppedExtracted() {
|
|
3112
3123
|
return droppedSink.splice(0, droppedSink.length);
|
|
3113
3124
|
}
|
|
3125
|
+
var skippedSink = /* @__PURE__ */ new Map();
|
|
3126
|
+
function noteSkippedFile(file) {
|
|
3127
|
+
if (!skippedSink.has(file.path)) skippedSink.set(file.path, file);
|
|
3128
|
+
}
|
|
3129
|
+
function drainSkippedFiles() {
|
|
3130
|
+
const out = [...skippedSink.values()];
|
|
3131
|
+
skippedSink.clear();
|
|
3132
|
+
return out;
|
|
3133
|
+
}
|
|
3114
3134
|
function isRejectedLogEnabled() {
|
|
3115
3135
|
const raw = process.env.NEAT_EXTRACTED_REJECTED_LOG;
|
|
3116
3136
|
return raw === "1" || raw === "true";
|
|
@@ -3124,14 +3144,91 @@ async function writeRejectedExtracted(drops, rejectedPath) {
|
|
|
3124
3144
|
|
|
3125
3145
|
// src/extract/calls/shared.ts
|
|
3126
3146
|
init_cjs_shims();
|
|
3147
|
+
var import_node_fs6 = require("fs");
|
|
3148
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
3149
|
+
var import_types4 = require("@neat.is/types");
|
|
3150
|
+
|
|
3151
|
+
// src/extract/gitignore.ts
|
|
3152
|
+
init_cjs_shims();
|
|
3127
3153
|
var import_node_fs5 = require("fs");
|
|
3128
3154
|
var import_node_path5 = __toESM(require("path"), 1);
|
|
3129
|
-
var
|
|
3155
|
+
var import_ignore = __toESM(require("ignore"), 1);
|
|
3156
|
+
var LAYER_CACHE = /* @__PURE__ */ new Map();
|
|
3157
|
+
async function layerFor(dir) {
|
|
3158
|
+
const cached = LAYER_CACHE.get(dir);
|
|
3159
|
+
if (cached !== void 0) return cached;
|
|
3160
|
+
let layer = null;
|
|
3161
|
+
try {
|
|
3162
|
+
const raw = await import_node_fs5.promises.readFile(import_node_path5.default.join(dir, ".gitignore"), "utf8");
|
|
3163
|
+
layer = { dir, ig: (0, import_ignore.default)().add(raw) };
|
|
3164
|
+
} catch {
|
|
3165
|
+
layer = null;
|
|
3166
|
+
}
|
|
3167
|
+
LAYER_CACHE.set(dir, layer);
|
|
3168
|
+
return layer;
|
|
3169
|
+
}
|
|
3170
|
+
async function isRepoRoot(dir) {
|
|
3171
|
+
try {
|
|
3172
|
+
await import_node_fs5.promises.stat(import_node_path5.default.join(dir, ".git"));
|
|
3173
|
+
return true;
|
|
3174
|
+
} catch {
|
|
3175
|
+
return false;
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
async function loadIgnoreChain(startDir) {
|
|
3179
|
+
const dirs = [];
|
|
3180
|
+
let current = import_node_path5.default.resolve(startDir);
|
|
3181
|
+
for (; ; ) {
|
|
3182
|
+
dirs.push(current);
|
|
3183
|
+
if (await isRepoRoot(current)) break;
|
|
3184
|
+
const parent = import_node_path5.default.dirname(current);
|
|
3185
|
+
if (parent === current) break;
|
|
3186
|
+
current = parent;
|
|
3187
|
+
}
|
|
3188
|
+
dirs.reverse();
|
|
3189
|
+
const layers = [];
|
|
3190
|
+
for (const dir of dirs) {
|
|
3191
|
+
const layer = await layerFor(dir);
|
|
3192
|
+
if (layer) layers.push(layer);
|
|
3193
|
+
}
|
|
3194
|
+
return layers;
|
|
3195
|
+
}
|
|
3196
|
+
async function extendIgnoreChain(chain, dir) {
|
|
3197
|
+
const layer = await layerFor(import_node_path5.default.resolve(dir));
|
|
3198
|
+
return layer ? [...chain, layer] : chain;
|
|
3199
|
+
}
|
|
3200
|
+
function isIgnored(chain, fullPath, isDir) {
|
|
3201
|
+
return decide(chain, fullPath, isDir).ignored;
|
|
3202
|
+
}
|
|
3203
|
+
function decide(chain, fullPath, isDir) {
|
|
3204
|
+
if (chain.length === 0) return { ignored: false, subtree: chain };
|
|
3205
|
+
const abs = import_node_path5.default.resolve(fullPath);
|
|
3206
|
+
let ignored = false;
|
|
3207
|
+
let unignoredAt = -1;
|
|
3208
|
+
for (let i = 0; i < chain.length; i++) {
|
|
3209
|
+
const layer = chain[i];
|
|
3210
|
+
const rel = import_node_path5.default.relative(layer.dir, abs);
|
|
3211
|
+
if (!rel || rel.startsWith("..") || import_node_path5.default.isAbsolute(rel)) continue;
|
|
3212
|
+
const candidate = rel.split(import_node_path5.default.sep).join("/") + (isDir ? "/" : "");
|
|
3213
|
+
const result = layer.ig.test(candidate);
|
|
3214
|
+
if (result.ignored) ignored = true;
|
|
3215
|
+
else if (result.unignored) {
|
|
3216
|
+
ignored = false;
|
|
3217
|
+
unignoredAt = i;
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
return {
|
|
3221
|
+
ignored,
|
|
3222
|
+
subtree: unignoredAt >= 0 ? chain.slice(unignoredAt) : chain
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
// src/extract/calls/shared.ts
|
|
3130
3227
|
function buildServiceHostIndex(services) {
|
|
3131
3228
|
const knownHosts = /* @__PURE__ */ new Set();
|
|
3132
3229
|
const hostToNodeId = /* @__PURE__ */ new Map();
|
|
3133
3230
|
for (const service of services) {
|
|
3134
|
-
const base =
|
|
3231
|
+
const base = import_node_path6.default.basename(service.dir);
|
|
3135
3232
|
knownHosts.add(base);
|
|
3136
3233
|
knownHosts.add(service.pkg.name);
|
|
3137
3234
|
hostToNodeId.set(base, service.node.id);
|
|
@@ -3140,33 +3237,62 @@ function buildServiceHostIndex(services) {
|
|
|
3140
3237
|
return { knownHosts, hostToNodeId };
|
|
3141
3238
|
}
|
|
3142
3239
|
async function walkSourceFiles(dir, excludeDirs = []) {
|
|
3143
|
-
const excluded = new Set(excludeDirs.map((d) =>
|
|
3240
|
+
const excluded = new Set(excludeDirs.map((d) => import_node_path6.default.resolve(d)));
|
|
3144
3241
|
const out = [];
|
|
3145
|
-
|
|
3146
|
-
|
|
3242
|
+
const rootChain = await loadIgnoreChain(dir);
|
|
3243
|
+
async function walk11(current, inherited) {
|
|
3244
|
+
const entries = await import_node_fs6.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
3245
|
+
const chain = entries.some((e) => e.isFile() && e.name === ".gitignore") ? await extendIgnoreChain(inherited, current) : inherited;
|
|
3147
3246
|
for (const entry2 of entries) {
|
|
3148
|
-
const full =
|
|
3247
|
+
const full = import_node_path6.default.join(current, entry2.name);
|
|
3149
3248
|
if (entry2.isDirectory()) {
|
|
3150
3249
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
3151
|
-
if (excluded.has(
|
|
3250
|
+
if (excluded.has(import_node_path6.default.resolve(full))) continue;
|
|
3251
|
+
const verdict = decide(chain, full, true);
|
|
3252
|
+
if (verdict.ignored) continue;
|
|
3152
3253
|
if (await isPythonVenvDir(full)) continue;
|
|
3153
|
-
await walk11(full);
|
|
3154
|
-
} else if (entry2.isFile() && SERVICE_FILE_EXTENSIONS.has(
|
|
3254
|
+
await walk11(full, verdict.subtree);
|
|
3255
|
+
} else if (entry2.isFile() && SERVICE_FILE_EXTENSIONS.has(import_node_path6.default.extname(entry2.name)) && // Skip NEAT's own generated `otel-init.*` bootstrap — extracting it
|
|
3155
3256
|
// would attribute our instrumentation imports to the user's service.
|
|
3156
|
-
!isNeatAuthoredSourceFile(entry2.name)) {
|
|
3257
|
+
!isNeatAuthoredSourceFile(entry2.name) && !isIgnored(chain, full, false)) {
|
|
3157
3258
|
out.push(full);
|
|
3158
3259
|
}
|
|
3159
3260
|
}
|
|
3160
3261
|
}
|
|
3161
|
-
await walk11(dir);
|
|
3262
|
+
await walk11(dir, rootChain.filter((l) => import_node_path6.default.resolve(l.dir) !== import_node_path6.default.resolve(dir)));
|
|
3162
3263
|
return out;
|
|
3163
3264
|
}
|
|
3265
|
+
var MINIFIED_LINE_CHARS = 5e3;
|
|
3266
|
+
function hasMinifiedName(filePath) {
|
|
3267
|
+
return /\.min\.(js|mjs|cjs|jsx|ts|tsx)$/i.test(filePath);
|
|
3268
|
+
}
|
|
3269
|
+
function isMinifiedSource(filePath, content) {
|
|
3270
|
+
if (hasMinifiedName(filePath)) return { minified: true, detail: "named *.min.js" };
|
|
3271
|
+
let longest = 0;
|
|
3272
|
+
let start = 0;
|
|
3273
|
+
for (; ; ) {
|
|
3274
|
+
const nl = content.indexOf("\n", start);
|
|
3275
|
+
const len = (nl === -1 ? content.length : nl) - start;
|
|
3276
|
+
if (len > longest) longest = len;
|
|
3277
|
+
if (nl === -1) break;
|
|
3278
|
+
start = nl + 1;
|
|
3279
|
+
}
|
|
3280
|
+
if (longest > MINIFIED_LINE_CHARS) {
|
|
3281
|
+
return { minified: true, detail: `longest line ${longest} chars` };
|
|
3282
|
+
}
|
|
3283
|
+
return { minified: false, detail: "" };
|
|
3284
|
+
}
|
|
3164
3285
|
async function loadSourceFiles(dir, excludeDirs = []) {
|
|
3165
3286
|
const paths = await walkSourceFiles(dir, excludeDirs);
|
|
3166
3287
|
const out = [];
|
|
3167
3288
|
for (const p of paths) {
|
|
3168
3289
|
try {
|
|
3169
|
-
const content = await
|
|
3290
|
+
const content = await import_node_fs6.promises.readFile(p, "utf8");
|
|
3291
|
+
const verdict = isMinifiedSource(p, content);
|
|
3292
|
+
if (verdict.minified) {
|
|
3293
|
+
noteSkippedFile({ path: p, reason: "minified", detail: verdict.detail });
|
|
3294
|
+
continue;
|
|
3295
|
+
}
|
|
3170
3296
|
out.push({ path: p, content });
|
|
3171
3297
|
} catch {
|
|
3172
3298
|
}
|
|
@@ -3178,15 +3304,18 @@ function lineOf(text, needle) {
|
|
|
3178
3304
|
if (idx < 0) return 1;
|
|
3179
3305
|
return text.slice(0, idx).split("\n").length;
|
|
3180
3306
|
}
|
|
3307
|
+
var SNIPPET_MAX_CHARS = 120;
|
|
3181
3308
|
function snippet(text, line) {
|
|
3182
3309
|
const lines = text.split("\n");
|
|
3183
|
-
|
|
3310
|
+
const raw = (lines[line - 1] ?? "").trim();
|
|
3311
|
+
if (raw.length <= SNIPPET_MAX_CHARS) return raw;
|
|
3312
|
+
return `${raw.slice(0, SNIPPET_MAX_CHARS)}\u2026 (+${raw.length - SNIPPET_MAX_CHARS} chars)`;
|
|
3184
3313
|
}
|
|
3185
3314
|
function toPosix(p) {
|
|
3186
3315
|
return p.split("\\").join("/");
|
|
3187
3316
|
}
|
|
3188
3317
|
function languageForPath(relPath) {
|
|
3189
|
-
switch (
|
|
3318
|
+
switch (import_node_path6.default.extname(relPath).toLowerCase()) {
|
|
3190
3319
|
case ".py":
|
|
3191
3320
|
return "python";
|
|
3192
3321
|
case ".go":
|
|
@@ -3260,8 +3389,8 @@ function ensureFileNode(graph, serviceName, serviceNodeId, relPath) {
|
|
|
3260
3389
|
|
|
3261
3390
|
// src/extract/imports.ts
|
|
3262
3391
|
init_cjs_shims();
|
|
3263
|
-
var
|
|
3264
|
-
var
|
|
3392
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
3393
|
+
var import_node_fs7 = require("fs");
|
|
3265
3394
|
var import_tree_sitter = __toESM(require("tree-sitter"), 1);
|
|
3266
3395
|
var import_tree_sitter_javascript = __toESM(require("tree-sitter-javascript"), 1);
|
|
3267
3396
|
var import_tree_sitter_python = __toESM(require("tree-sitter-python"), 1);
|
|
@@ -3406,15 +3535,15 @@ function collectPyImports(node, out) {
|
|
|
3406
3535
|
}
|
|
3407
3536
|
async function fileExists(p) {
|
|
3408
3537
|
try {
|
|
3409
|
-
await
|
|
3538
|
+
await import_node_fs7.promises.access(p);
|
|
3410
3539
|
return true;
|
|
3411
3540
|
} catch {
|
|
3412
3541
|
return false;
|
|
3413
3542
|
}
|
|
3414
3543
|
}
|
|
3415
3544
|
function isWithinServiceDir(candidate, serviceDir) {
|
|
3416
|
-
const rel =
|
|
3417
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
3545
|
+
const rel = import_node_path7.default.relative(serviceDir, candidate);
|
|
3546
|
+
return rel !== "" && !rel.startsWith("..") && !import_node_path7.default.isAbsolute(rel);
|
|
3418
3547
|
}
|
|
3419
3548
|
var JS_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
3420
3549
|
var JS_INDEX_FILES = JS_EXTENSIONS.map((ext) => `index${ext}`);
|
|
@@ -3422,22 +3551,22 @@ async function firstExistingCandidate(base, serviceDir) {
|
|
|
3422
3551
|
for (const ext of JS_EXTENSIONS) {
|
|
3423
3552
|
const candidate = base + ext;
|
|
3424
3553
|
if (isWithinServiceDir(candidate, serviceDir) && await fileExists(candidate)) {
|
|
3425
|
-
return toPosix(
|
|
3554
|
+
return toPosix(import_node_path7.default.relative(serviceDir, candidate));
|
|
3426
3555
|
}
|
|
3427
3556
|
}
|
|
3428
3557
|
for (const indexFile of JS_INDEX_FILES) {
|
|
3429
|
-
const candidate =
|
|
3558
|
+
const candidate = import_node_path7.default.join(base, indexFile);
|
|
3430
3559
|
if (isWithinServiceDir(candidate, serviceDir) && await fileExists(candidate)) {
|
|
3431
|
-
return toPosix(
|
|
3560
|
+
return toPosix(import_node_path7.default.relative(serviceDir, candidate));
|
|
3432
3561
|
}
|
|
3433
3562
|
}
|
|
3434
3563
|
return null;
|
|
3435
3564
|
}
|
|
3436
3565
|
async function loadTsPathConfig(serviceDir) {
|
|
3437
|
-
const tsconfigPath =
|
|
3566
|
+
const tsconfigPath = import_node_path7.default.join(serviceDir, "tsconfig.json");
|
|
3438
3567
|
let raw;
|
|
3439
3568
|
try {
|
|
3440
|
-
raw = await
|
|
3569
|
+
raw = await import_node_fs7.promises.readFile(tsconfigPath, "utf8");
|
|
3441
3570
|
} catch {
|
|
3442
3571
|
return null;
|
|
3443
3572
|
}
|
|
@@ -3446,7 +3575,7 @@ async function loadTsPathConfig(serviceDir) {
|
|
|
3446
3575
|
const paths = parsed.compilerOptions?.paths;
|
|
3447
3576
|
if (!paths || Object.keys(paths).length === 0) return null;
|
|
3448
3577
|
const baseUrl = parsed.compilerOptions?.baseUrl;
|
|
3449
|
-
return { paths, baseDir: baseUrl ?
|
|
3578
|
+
return { paths, baseDir: baseUrl ? import_node_path7.default.resolve(serviceDir, baseUrl) : serviceDir };
|
|
3450
3579
|
} catch (err) {
|
|
3451
3580
|
recordExtractionError("import alias resolution", tsconfigPath, err);
|
|
3452
3581
|
return null;
|
|
@@ -3464,11 +3593,11 @@ async function resolveTsAlias(specifier, config, serviceDir) {
|
|
|
3464
3593
|
if (suffix === null) continue;
|
|
3465
3594
|
for (const target of targets) {
|
|
3466
3595
|
const targetBase = target.endsWith("/*") ? target.slice(0, -2) : target.replace(/\*$/, "");
|
|
3467
|
-
const resolvedBase =
|
|
3596
|
+
const resolvedBase = import_node_path7.default.resolve(config.baseDir, targetBase, suffix);
|
|
3468
3597
|
const hit = await firstExistingCandidate(resolvedBase, serviceDir);
|
|
3469
3598
|
if (hit) return hit;
|
|
3470
3599
|
if (isWithinServiceDir(resolvedBase, serviceDir) && await fileExists(resolvedBase)) {
|
|
3471
|
-
return toPosix(
|
|
3600
|
+
return toPosix(import_node_path7.default.relative(serviceDir, resolvedBase));
|
|
3472
3601
|
}
|
|
3473
3602
|
}
|
|
3474
3603
|
}
|
|
@@ -3477,18 +3606,18 @@ async function resolveTsAlias(specifier, config, serviceDir) {
|
|
|
3477
3606
|
async function resolveJsImport(specifier, importerDir, serviceDir, tsPaths) {
|
|
3478
3607
|
if (!specifier) return null;
|
|
3479
3608
|
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
3480
|
-
const base =
|
|
3481
|
-
const ext =
|
|
3609
|
+
const base = import_node_path7.default.resolve(importerDir, specifier);
|
|
3610
|
+
const ext = import_node_path7.default.extname(specifier);
|
|
3482
3611
|
if (ext) {
|
|
3483
3612
|
if (ext === ".js" || ext === ".jsx") {
|
|
3484
3613
|
const tsExt = ext === ".jsx" ? ".tsx" : ".ts";
|
|
3485
3614
|
const tsSibling = base.slice(0, -ext.length) + tsExt;
|
|
3486
3615
|
if (isWithinServiceDir(tsSibling, serviceDir) && await fileExists(tsSibling)) {
|
|
3487
|
-
return toPosix(
|
|
3616
|
+
return toPosix(import_node_path7.default.relative(serviceDir, tsSibling));
|
|
3488
3617
|
}
|
|
3489
3618
|
}
|
|
3490
3619
|
if (isWithinServiceDir(base, serviceDir) && await fileExists(base)) {
|
|
3491
|
-
return toPosix(
|
|
3620
|
+
return toPosix(import_node_path7.default.relative(serviceDir, base));
|
|
3492
3621
|
}
|
|
3493
3622
|
if (!JS_EXTENSIONS.includes(ext)) {
|
|
3494
3623
|
return firstExistingCandidate(base, serviceDir);
|
|
@@ -3503,30 +3632,30 @@ async function resolveJsImport(specifier, importerDir, serviceDir, tsPaths) {
|
|
|
3503
3632
|
async function resolvePyImport(imp, importerPath, serviceDir) {
|
|
3504
3633
|
let baseDir;
|
|
3505
3634
|
if (imp.level > 0) {
|
|
3506
|
-
baseDir =
|
|
3507
|
-
for (let i = 1; i < imp.level; i++) baseDir =
|
|
3635
|
+
baseDir = import_node_path7.default.dirname(importerPath);
|
|
3636
|
+
for (let i = 1; i < imp.level; i++) baseDir = import_node_path7.default.dirname(baseDir);
|
|
3508
3637
|
} else {
|
|
3509
3638
|
baseDir = serviceDir;
|
|
3510
3639
|
}
|
|
3511
|
-
const moduleBase = imp.modulePath ?
|
|
3640
|
+
const moduleBase = imp.modulePath ? import_node_path7.default.join(baseDir, imp.modulePath.split(".").join("/")) : baseDir;
|
|
3512
3641
|
const resolved = /* @__PURE__ */ new Set();
|
|
3513
3642
|
let needModuleFile = imp.names.length === 0;
|
|
3514
3643
|
for (const name of imp.names) {
|
|
3515
|
-
const submoduleFile =
|
|
3516
|
-
const subpackageInit =
|
|
3644
|
+
const submoduleFile = import_node_path7.default.join(moduleBase, `${name}.py`);
|
|
3645
|
+
const subpackageInit = import_node_path7.default.join(moduleBase, name, "__init__.py");
|
|
3517
3646
|
if (isWithinServiceDir(submoduleFile, serviceDir) && await fileExists(submoduleFile)) {
|
|
3518
|
-
resolved.add(toPosix(
|
|
3647
|
+
resolved.add(toPosix(import_node_path7.default.relative(serviceDir, submoduleFile)));
|
|
3519
3648
|
} else if (isWithinServiceDir(subpackageInit, serviceDir) && await fileExists(subpackageInit)) {
|
|
3520
|
-
resolved.add(toPosix(
|
|
3649
|
+
resolved.add(toPosix(import_node_path7.default.relative(serviceDir, subpackageInit)));
|
|
3521
3650
|
} else {
|
|
3522
3651
|
needModuleFile = true;
|
|
3523
3652
|
}
|
|
3524
3653
|
}
|
|
3525
3654
|
if (needModuleFile) {
|
|
3526
|
-
const moduleFileCandidates = imp.modulePath ? [`${moduleBase}.py`,
|
|
3655
|
+
const moduleFileCandidates = imp.modulePath ? [`${moduleBase}.py`, import_node_path7.default.join(moduleBase, "__init__.py")] : [import_node_path7.default.join(moduleBase, "__init__.py")];
|
|
3527
3656
|
for (const candidate of moduleFileCandidates) {
|
|
3528
3657
|
if (isWithinServiceDir(candidate, serviceDir) && await fileExists(candidate)) {
|
|
3529
|
-
resolved.add(toPosix(
|
|
3658
|
+
resolved.add(toPosix(import_node_path7.default.relative(serviceDir, candidate)));
|
|
3530
3659
|
break;
|
|
3531
3660
|
}
|
|
3532
3661
|
}
|
|
@@ -3536,11 +3665,11 @@ async function resolvePyImport(imp, importerPath, serviceDir) {
|
|
|
3536
3665
|
async function resolveGoImport(specifier, modulePath, serviceDir) {
|
|
3537
3666
|
if (specifier !== modulePath && !specifier.startsWith(`${modulePath}/`)) return null;
|
|
3538
3667
|
const suffix = specifier === modulePath ? "" : specifier.slice(modulePath.length + 1);
|
|
3539
|
-
const dir =
|
|
3540
|
-
const entries = await
|
|
3541
|
-
const candidates = entries.filter((entry2) => entry2.isFile() && entry2.name.endsWith(".go") && !entry2.name.endsWith("_test.go")).map((entry2) =>
|
|
3668
|
+
const dir = import_node_path7.default.join(serviceDir, suffix);
|
|
3669
|
+
const entries = await import_node_fs7.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
3670
|
+
const candidates = entries.filter((entry2) => entry2.isFile() && entry2.name.endsWith(".go") && !entry2.name.endsWith("_test.go")).map((entry2) => import_node_path7.default.join(dir, entry2.name));
|
|
3542
3671
|
if (candidates.length !== 1) return null;
|
|
3543
|
-
return toPosix(
|
|
3672
|
+
return toPosix(import_node_path7.default.relative(serviceDir, candidates[0]));
|
|
3544
3673
|
}
|
|
3545
3674
|
function emitImportEdge(graph, serviceName, importerFileId, importerRelPath, importeeRelPath, line, snippet2) {
|
|
3546
3675
|
const importeeFileId = (0, import_types5.fileId)(serviceName, importeeRelPath);
|
|
@@ -3570,12 +3699,12 @@ async function addImports(graph, services) {
|
|
|
3570
3699
|
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
3571
3700
|
for (const file of files) {
|
|
3572
3701
|
if (isTestPath(file.path)) continue;
|
|
3573
|
-
const relFile = toPosix(
|
|
3702
|
+
const relFile = toPosix(import_node_path7.default.relative(service.dir, file.path));
|
|
3574
3703
|
const importerFileId = (0, import_types5.fileId)(service.pkg.name, relFile);
|
|
3575
|
-
const isPython =
|
|
3576
|
-
const isGo =
|
|
3577
|
-
if (
|
|
3578
|
-
if (
|
|
3704
|
+
const isPython = import_node_path7.default.extname(file.path) === ".py";
|
|
3705
|
+
const isGo = import_node_path7.default.extname(file.path) === ".go";
|
|
3706
|
+
if (import_node_path7.default.extname(file.path) === ".rb") continue;
|
|
3707
|
+
if (import_node_path7.default.extname(file.path) === ".php") continue;
|
|
3579
3708
|
if (isGo) {
|
|
3580
3709
|
let goImports = [];
|
|
3581
3710
|
try {
|
|
@@ -3585,7 +3714,7 @@ async function addImports(graph, services) {
|
|
|
3585
3714
|
recordExtractionError("import extraction", file.path, err);
|
|
3586
3715
|
continue;
|
|
3587
3716
|
}
|
|
3588
|
-
const goMod = await
|
|
3717
|
+
const goMod = await import_node_fs7.promises.readFile(import_node_path7.default.join(service.dir, "go.mod"), "utf8").catch(() => "");
|
|
3589
3718
|
const modulePath = goMod.match(/^\s*module\s+(\S+)\s*$/m)?.[1];
|
|
3590
3719
|
if (!modulePath) continue;
|
|
3591
3720
|
for (const imp of goImports) {
|
|
@@ -3629,7 +3758,7 @@ async function addImports(graph, services) {
|
|
|
3629
3758
|
continue;
|
|
3630
3759
|
}
|
|
3631
3760
|
for (const imp of jsImports) {
|
|
3632
|
-
const resolved = await resolveJsImport(imp.specifier,
|
|
3761
|
+
const resolved = await resolveJsImport(imp.specifier, import_node_path7.default.dirname(file.path), service.dir, tsPaths);
|
|
3633
3762
|
if (!resolved) continue;
|
|
3634
3763
|
edgesAdded += emitImportEdge(
|
|
3635
3764
|
graph,
|
|
@@ -3754,8 +3883,8 @@ function chiRoutesFromSource(source, parser) {
|
|
|
3754
3883
|
chiWalk(tree.rootNode, "", out);
|
|
3755
3884
|
return out;
|
|
3756
3885
|
}
|
|
3757
|
-
function stripChiRegex(
|
|
3758
|
-
return
|
|
3886
|
+
function stripChiRegex(path82) {
|
|
3887
|
+
return path82.replace(/\{([^{}:]+):[^{}]*\}/g, "{$1}");
|
|
3759
3888
|
}
|
|
3760
3889
|
function chiWalk(node, prefix, out) {
|
|
3761
3890
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
@@ -4095,7 +4224,7 @@ function isNextPagesApiFile(relFile) {
|
|
|
4095
4224
|
if (pagesIdx === -1 || segs[pagesIdx + 1] !== "api") return false;
|
|
4096
4225
|
const base = segs[segs.length - 1] ?? "";
|
|
4097
4226
|
if (/^_(app|document|middleware)\./.test(base)) return false;
|
|
4098
|
-
return JS_ROUTE_EXTENSIONS.has(
|
|
4227
|
+
return JS_ROUTE_EXTENSIONS.has(import_node_path8.default.extname(base));
|
|
4099
4228
|
}
|
|
4100
4229
|
function nextSegment(seg) {
|
|
4101
4230
|
if (seg.startsWith("(") && seg.endsWith(")")) return null;
|
|
@@ -4427,9 +4556,9 @@ function rubyRocketRoute(args) {
|
|
|
4427
4556
|
if (!pair || pair.type !== "pair") continue;
|
|
4428
4557
|
const k = pair.childForFieldName("key");
|
|
4429
4558
|
if (k?.type !== "string") continue;
|
|
4430
|
-
const
|
|
4431
|
-
if (
|
|
4432
|
-
return { path:
|
|
4559
|
+
const path82 = rubyLiteral(k);
|
|
4560
|
+
if (path82 === null) continue;
|
|
4561
|
+
return { path: path82, target: rubyLiteral(pair.childForFieldName("value")) };
|
|
4433
4562
|
}
|
|
4434
4563
|
return null;
|
|
4435
4564
|
}
|
|
@@ -5277,12 +5406,12 @@ async function expressMountPrefixes(files, serviceDir, tsPaths) {
|
|
|
5277
5406
|
const jsParser = makeJsParser2();
|
|
5278
5407
|
const fileInfo = /* @__PURE__ */ new Map();
|
|
5279
5408
|
for (const f of files) {
|
|
5280
|
-
if (!JS_ROUTE_EXTENSIONS.has(
|
|
5409
|
+
if (!JS_ROUTE_EXTENSIONS.has(import_node_path8.default.extname(f.path))) continue;
|
|
5281
5410
|
if (isTestPath(f.path)) continue;
|
|
5282
|
-
const rel = toPosix(
|
|
5411
|
+
const rel = toPosix(import_node_path8.default.relative(serviceDir, f.path));
|
|
5283
5412
|
try {
|
|
5284
5413
|
const tree = parseSource2(jsParser, f.content);
|
|
5285
|
-
fileInfo.set(rel, analyzeExpressFile(tree.rootNode,
|
|
5414
|
+
fileInfo.set(rel, analyzeExpressFile(tree.rootNode, import_node_path8.default.dirname(f.path)));
|
|
5286
5415
|
} catch {
|
|
5287
5416
|
}
|
|
5288
5417
|
}
|
|
@@ -5381,14 +5510,14 @@ async function addRoutes(graph, services) {
|
|
|
5381
5510
|
const mountPrefixes = hasExpress ? await expressMountPrefixes(files, service.dir, await loadTsPathConfig(service.dir)) : /* @__PURE__ */ new Map();
|
|
5382
5511
|
for (const file of files) {
|
|
5383
5512
|
if (isTestPath(file.path)) continue;
|
|
5384
|
-
const ext =
|
|
5513
|
+
const ext = import_node_path8.default.extname(file.path);
|
|
5385
5514
|
const isPy = ext === ".py";
|
|
5386
5515
|
const isGo = ext === ".go";
|
|
5387
5516
|
const isRb = ext === ".rb";
|
|
5388
5517
|
const isPhp = ext === ".php";
|
|
5389
5518
|
const isRs = ext === ".rs";
|
|
5390
5519
|
if (!JS_ROUTE_EXTENSIONS.has(ext) && !isPy && !isGo && !isRb && !isPhp && !isRs) continue;
|
|
5391
|
-
const relFile = toPosix(
|
|
5520
|
+
const relFile = toPosix(import_node_path8.default.relative(service.dir, file.path));
|
|
5392
5521
|
let routes;
|
|
5393
5522
|
try {
|
|
5394
5523
|
if (isPhp) {
|
|
@@ -5896,7 +6025,7 @@ function languageForExt(relPath) {
|
|
|
5896
6025
|
function relPathForRuntimeFile(filepath, serviceNode, scanPath) {
|
|
5897
6026
|
let p = toPosix2(filepath).replace(/^file:\/\//, "");
|
|
5898
6027
|
if (scanPath && scanPath.length > 0) {
|
|
5899
|
-
const absRoot = toPosix2(
|
|
6028
|
+
const absRoot = toPosix2(import_node_path9.default.resolve(scanPath, serviceNode?.repoPath ?? ""));
|
|
5900
6029
|
const anchor = absRoot.endsWith("/") ? absRoot : `${absRoot}/`;
|
|
5901
6030
|
if (p.startsWith(anchor)) return p.slice(anchor.length);
|
|
5902
6031
|
}
|
|
@@ -5924,10 +6053,10 @@ function resolveDistToSrc(absFilepath, line) {
|
|
|
5924
6053
|
entry2 = null;
|
|
5925
6054
|
const mapPath = `${absFilepath}.map`;
|
|
5926
6055
|
try {
|
|
5927
|
-
if ((0,
|
|
5928
|
-
const raw = JSON.parse((0,
|
|
6056
|
+
if ((0, import_node_fs8.existsSync)(mapPath)) {
|
|
6057
|
+
const raw = JSON.parse((0, import_node_fs8.readFileSync)(mapPath, "utf8"));
|
|
5929
6058
|
const consumer = new sourceMapJs.SourceMapConsumer(raw);
|
|
5930
|
-
entry2 = { consumer, dir:
|
|
6059
|
+
entry2 = { consumer, dir: import_node_path9.default.dirname(mapPath) };
|
|
5931
6060
|
}
|
|
5932
6061
|
} catch {
|
|
5933
6062
|
entry2 = null;
|
|
@@ -5947,7 +6076,7 @@ function resolveDistToSrc(absFilepath, line) {
|
|
|
5947
6076
|
}
|
|
5948
6077
|
if (!pos || !pos.source) return null;
|
|
5949
6078
|
const root = entry2.consumer.sourceRoot ?? "";
|
|
5950
|
-
const resolved =
|
|
6079
|
+
const resolved = import_node_path9.default.resolve(entry2.dir, root, pos.source);
|
|
5951
6080
|
return { filepath: resolved, ...pos.line ? { line: pos.line } : {} };
|
|
5952
6081
|
} catch {
|
|
5953
6082
|
return null;
|
|
@@ -6491,8 +6620,8 @@ function emitIncidentEvent(project, ev) {
|
|
|
6491
6620
|
});
|
|
6492
6621
|
}
|
|
6493
6622
|
async function appendErrorEvent(ctx, ev) {
|
|
6494
|
-
await
|
|
6495
|
-
await
|
|
6623
|
+
await import_node_fs8.promises.mkdir(import_node_path9.default.dirname(ctx.errorsPath), { recursive: true });
|
|
6624
|
+
await import_node_fs8.promises.appendFile(ctx.errorsPath, JSON.stringify(ev) + "\n", "utf8");
|
|
6496
6625
|
emitIncidentEvent(ctx.project ?? DEFAULT_PROJECT, ev);
|
|
6497
6626
|
}
|
|
6498
6627
|
async function appendConnectorIncident(errorsPath, input, project) {
|
|
@@ -6507,8 +6636,8 @@ async function appendConnectorIncident(errorsPath, input, project) {
|
|
|
6507
6636
|
...input.attributes && Object.keys(input.attributes).length > 0 ? { attributes: input.attributes } : {},
|
|
6508
6637
|
affectedNode: input.affectedNode
|
|
6509
6638
|
};
|
|
6510
|
-
await
|
|
6511
|
-
await
|
|
6639
|
+
await import_node_fs8.promises.mkdir(import_node_path9.default.dirname(errorsPath), { recursive: true });
|
|
6640
|
+
await import_node_fs8.promises.appendFile(errorsPath, JSON.stringify(ev) + "\n", "utf8");
|
|
6512
6641
|
if (project) emitIncidentEvent(project, ev);
|
|
6513
6642
|
}
|
|
6514
6643
|
function landIncidentCallSite(span, callSite, trusted, graph) {
|
|
@@ -6630,8 +6759,8 @@ function makeErrorSpanWriter(errorsPath, graph, scanPath, project = DEFAULT_PROJ
|
|
|
6630
6759
|
return async (span) => {
|
|
6631
6760
|
const ev = buildErrorEventForReceiver(span, graph, scanPath);
|
|
6632
6761
|
if (!ev) return;
|
|
6633
|
-
await
|
|
6634
|
-
await
|
|
6762
|
+
await import_node_fs8.promises.mkdir(import_node_path9.default.dirname(errorsPath), { recursive: true });
|
|
6763
|
+
await import_node_fs8.promises.appendFile(errorsPath, JSON.stringify(ev) + "\n", "utf8");
|
|
6635
6764
|
emitIncidentEvent(project, ev);
|
|
6636
6765
|
};
|
|
6637
6766
|
}
|
|
@@ -7131,13 +7260,13 @@ async function markStaleEdges(graph, options = {}) {
|
|
|
7131
7260
|
return { count: events.length, events };
|
|
7132
7261
|
}
|
|
7133
7262
|
async function appendStaleEvents(staleEventsPath, events) {
|
|
7134
|
-
await
|
|
7263
|
+
await import_node_fs8.promises.mkdir(import_node_path9.default.dirname(staleEventsPath), { recursive: true });
|
|
7135
7264
|
const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
7136
|
-
await
|
|
7265
|
+
await import_node_fs8.promises.appendFile(staleEventsPath, lines, "utf8");
|
|
7137
7266
|
}
|
|
7138
7267
|
async function readStaleEvents(staleEventsPath) {
|
|
7139
7268
|
try {
|
|
7140
|
-
const raw = await
|
|
7269
|
+
const raw = await import_node_fs8.promises.readFile(staleEventsPath, "utf8");
|
|
7141
7270
|
return raw.split("\n").filter((line) => line.length > 0).map((line) => JSON.parse(line));
|
|
7142
7271
|
} catch (err) {
|
|
7143
7272
|
if (err.code === "ENOENT") return [];
|
|
@@ -7173,7 +7302,7 @@ function startStalenessLoop(graph, options = {}) {
|
|
|
7173
7302
|
var INCIDENT_READ_MAX_BYTES = 32 * 1024 * 1024;
|
|
7174
7303
|
var INCIDENT_READ_MAX_EVENTS = 5e3;
|
|
7175
7304
|
async function readErrorFileTail(errorsPath, maxBytes) {
|
|
7176
|
-
const handle = await
|
|
7305
|
+
const handle = await import_node_fs8.promises.open(errorsPath, "r");
|
|
7177
7306
|
try {
|
|
7178
7307
|
const { size } = await handle.stat();
|
|
7179
7308
|
if (size <= maxBytes) {
|
|
@@ -7298,16 +7427,16 @@ function mergeSnapshot(graph, snapshot) {
|
|
|
7298
7427
|
|
|
7299
7428
|
// src/extract/services.ts
|
|
7300
7429
|
init_cjs_shims();
|
|
7301
|
-
var
|
|
7302
|
-
var
|
|
7303
|
-
var
|
|
7430
|
+
var import_node_fs19 = require("fs");
|
|
7431
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
7432
|
+
var import_ignore2 = __toESM(require("ignore"), 1);
|
|
7304
7433
|
var import_minimatch2 = require("minimatch");
|
|
7305
7434
|
var import_types18 = require("@neat.is/types");
|
|
7306
7435
|
|
|
7307
7436
|
// src/extract/python.ts
|
|
7308
7437
|
init_cjs_shims();
|
|
7309
|
-
var
|
|
7310
|
-
var
|
|
7438
|
+
var import_node_fs9 = require("fs");
|
|
7439
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
7311
7440
|
var import_smol_toml = require("smol-toml");
|
|
7312
7441
|
var REQUIREMENT_LINE = /^\s*([A-Za-z0-9_.-]+)(?:\[[^\]]*\])?\s*(?:(==)\s*([A-Za-z0-9_.+-]+))?/;
|
|
7313
7442
|
function parseRequirementsTxt(content) {
|
|
@@ -7340,25 +7469,25 @@ function depsFromPyProject(pyproject) {
|
|
|
7340
7469
|
return out;
|
|
7341
7470
|
}
|
|
7342
7471
|
async function discoverPythonService(serviceDir) {
|
|
7343
|
-
const pyprojectPath =
|
|
7344
|
-
const requirementsPath =
|
|
7345
|
-
const setupPath =
|
|
7472
|
+
const pyprojectPath = import_node_path10.default.join(serviceDir, "pyproject.toml");
|
|
7473
|
+
const requirementsPath = import_node_path10.default.join(serviceDir, "requirements.txt");
|
|
7474
|
+
const setupPath = import_node_path10.default.join(serviceDir, "setup.py");
|
|
7346
7475
|
const hasPyproject = await exists(pyprojectPath);
|
|
7347
7476
|
const hasRequirements = await exists(requirementsPath);
|
|
7348
7477
|
const hasSetup = await exists(setupPath);
|
|
7349
7478
|
if (!hasPyproject && !hasRequirements && !hasSetup) return null;
|
|
7350
|
-
let name =
|
|
7479
|
+
let name = import_node_path10.default.basename(serviceDir);
|
|
7351
7480
|
let version;
|
|
7352
7481
|
const dependencies = {};
|
|
7353
7482
|
if (hasPyproject) {
|
|
7354
|
-
const raw = await
|
|
7483
|
+
const raw = await import_node_fs9.promises.readFile(pyprojectPath, "utf8");
|
|
7355
7484
|
const pyproject = (0, import_smol_toml.parse)(raw);
|
|
7356
7485
|
name = pyproject.project?.name ?? pyproject.tool?.poetry?.name ?? name;
|
|
7357
7486
|
version = pyproject.project?.version ?? pyproject.tool?.poetry?.version ?? void 0;
|
|
7358
7487
|
Object.assign(dependencies, depsFromPyProject(pyproject));
|
|
7359
7488
|
}
|
|
7360
7489
|
if (hasRequirements) {
|
|
7361
|
-
const raw = await
|
|
7490
|
+
const raw = await import_node_fs9.promises.readFile(requirementsPath, "utf8");
|
|
7362
7491
|
Object.assign(dependencies, parseRequirementsTxt(raw));
|
|
7363
7492
|
}
|
|
7364
7493
|
return { name, version, dependencies };
|
|
@@ -7373,8 +7502,8 @@ function pythonToPackage(service) {
|
|
|
7373
7502
|
|
|
7374
7503
|
// src/extract/go.ts
|
|
7375
7504
|
init_cjs_shims();
|
|
7376
|
-
var
|
|
7377
|
-
var
|
|
7505
|
+
var import_node_fs10 = require("fs");
|
|
7506
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
7378
7507
|
var import_types9 = require("@neat.is/types");
|
|
7379
7508
|
function parseGoMod(source) {
|
|
7380
7509
|
const module2 = source.match(/^\s*module\s+(\S+)\s*$/m)?.[1];
|
|
@@ -7401,7 +7530,7 @@ function goFramework(deps) {
|
|
|
7401
7530
|
async function discoverGoService(scanPath, dir) {
|
|
7402
7531
|
let raw;
|
|
7403
7532
|
try {
|
|
7404
|
-
raw = await
|
|
7533
|
+
raw = await import_node_fs10.promises.readFile(import_node_path11.default.join(dir, "go.mod"), "utf8");
|
|
7405
7534
|
} catch {
|
|
7406
7535
|
return null;
|
|
7407
7536
|
}
|
|
@@ -7416,7 +7545,7 @@ async function discoverGoService(scanPath, dir) {
|
|
|
7416
7545
|
name,
|
|
7417
7546
|
language: "go",
|
|
7418
7547
|
dependencies: mod.dependencies,
|
|
7419
|
-
repoPath:
|
|
7548
|
+
repoPath: import_node_path11.default.relative(scanPath, dir),
|
|
7420
7549
|
...framework ? { framework } : {}
|
|
7421
7550
|
};
|
|
7422
7551
|
return { pkg, dir, node };
|
|
@@ -7424,8 +7553,8 @@ async function discoverGoService(scanPath, dir) {
|
|
|
7424
7553
|
|
|
7425
7554
|
// src/extract/ruby.ts
|
|
7426
7555
|
init_cjs_shims();
|
|
7427
|
-
var
|
|
7428
|
-
var
|
|
7556
|
+
var import_node_fs11 = require("fs");
|
|
7557
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
7429
7558
|
var import_types10 = require("@neat.is/types");
|
|
7430
7559
|
function parseGemfile(source) {
|
|
7431
7560
|
const dependencies = {};
|
|
@@ -7442,12 +7571,12 @@ function parseGemfile(source) {
|
|
|
7442
7571
|
async function discoverRubyService(scanPath, dir) {
|
|
7443
7572
|
let raw;
|
|
7444
7573
|
try {
|
|
7445
|
-
raw = await
|
|
7574
|
+
raw = await import_node_fs11.promises.readFile(import_node_path12.default.join(dir, "Gemfile"), "utf8");
|
|
7446
7575
|
} catch {
|
|
7447
7576
|
return null;
|
|
7448
7577
|
}
|
|
7449
7578
|
const gemfile = parseGemfile(raw);
|
|
7450
|
-
const name =
|
|
7579
|
+
const name = import_node_path12.default.basename(dir);
|
|
7451
7580
|
const pkg = { name, dependencies: gemfile.dependencies };
|
|
7452
7581
|
const node = {
|
|
7453
7582
|
id: (0, import_types10.serviceId)(name),
|
|
@@ -7455,7 +7584,7 @@ async function discoverRubyService(scanPath, dir) {
|
|
|
7455
7584
|
name,
|
|
7456
7585
|
language: "ruby",
|
|
7457
7586
|
dependencies: gemfile.dependencies,
|
|
7458
|
-
repoPath:
|
|
7587
|
+
repoPath: import_node_path12.default.relative(scanPath, dir),
|
|
7459
7588
|
...gemfile.dependencies["rails"] !== void 0 ? { framework: "rails" } : {}
|
|
7460
7589
|
};
|
|
7461
7590
|
return { pkg, dir, node };
|
|
@@ -7463,7 +7592,7 @@ async function discoverRubyService(scanPath, dir) {
|
|
|
7463
7592
|
|
|
7464
7593
|
// src/extract/php.ts
|
|
7465
7594
|
init_cjs_shims();
|
|
7466
|
-
var
|
|
7595
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
7467
7596
|
var import_types11 = require("@neat.is/types");
|
|
7468
7597
|
function parseComposerJson(composer) {
|
|
7469
7598
|
return {
|
|
@@ -7476,12 +7605,12 @@ function parseComposerJson(composer) {
|
|
|
7476
7605
|
async function discoverPhpService(scanPath, dir) {
|
|
7477
7606
|
let composer;
|
|
7478
7607
|
try {
|
|
7479
|
-
composer = await readJson(
|
|
7608
|
+
composer = await readJson(import_node_path13.default.join(dir, "composer.json"));
|
|
7480
7609
|
} catch {
|
|
7481
7610
|
return null;
|
|
7482
7611
|
}
|
|
7483
7612
|
const { dependencies } = parseComposerJson(composer);
|
|
7484
|
-
const name =
|
|
7613
|
+
const name = import_node_path13.default.basename(dir);
|
|
7485
7614
|
const pkg = { name, dependencies };
|
|
7486
7615
|
const node = {
|
|
7487
7616
|
id: (0, import_types11.serviceId)(name),
|
|
@@ -7489,7 +7618,7 @@ async function discoverPhpService(scanPath, dir) {
|
|
|
7489
7618
|
name,
|
|
7490
7619
|
language: "php",
|
|
7491
7620
|
dependencies,
|
|
7492
|
-
repoPath:
|
|
7621
|
+
repoPath: import_node_path13.default.relative(scanPath, dir),
|
|
7493
7622
|
...dependencies["laravel/framework"] !== void 0 ? { framework: "laravel" } : {}
|
|
7494
7623
|
};
|
|
7495
7624
|
return { pkg, dir, node };
|
|
@@ -7497,23 +7626,23 @@ async function discoverPhpService(scanPath, dir) {
|
|
|
7497
7626
|
|
|
7498
7627
|
// src/extract/csharp.ts
|
|
7499
7628
|
init_cjs_shims();
|
|
7500
|
-
var
|
|
7501
|
-
var
|
|
7629
|
+
var import_node_fs12 = require("fs");
|
|
7630
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
7502
7631
|
var import_types12 = require("@neat.is/types");
|
|
7503
7632
|
var CSHARP_PROJECT_EXTS = /* @__PURE__ */ new Set([".csproj", ".sln"]);
|
|
7504
7633
|
async function projectFiles(dir) {
|
|
7505
|
-
const entries = await
|
|
7634
|
+
const entries = await import_node_fs12.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
7506
7635
|
const out = [];
|
|
7507
7636
|
for (const entry2 of entries) {
|
|
7508
7637
|
if (!entry2.isFile()) continue;
|
|
7509
|
-
if (CSHARP_PROJECT_EXTS.has(
|
|
7638
|
+
if (CSHARP_PROJECT_EXTS.has(import_node_path14.default.extname(entry2.name).toLowerCase())) out.push(entry2.name);
|
|
7510
7639
|
}
|
|
7511
7640
|
return out.sort();
|
|
7512
7641
|
}
|
|
7513
7642
|
var NESTED_PROJECT_DIR = "src";
|
|
7514
7643
|
async function resolveProjectDir(dir) {
|
|
7515
7644
|
if ((await projectFiles(dir)).length > 0) return dir;
|
|
7516
|
-
const nested =
|
|
7645
|
+
const nested = import_node_path14.default.join(dir, NESTED_PROJECT_DIR);
|
|
7517
7646
|
if ((await projectFiles(nested)).length > 0) return nested;
|
|
7518
7647
|
return null;
|
|
7519
7648
|
}
|
|
@@ -7538,10 +7667,10 @@ async function discoverCsharpService(scanPath, dir) {
|
|
|
7538
7667
|
if (projectDir === null) return null;
|
|
7539
7668
|
const projects = await projectFiles(projectDir);
|
|
7540
7669
|
const csproj = projects.find((p) => p.toLowerCase().endsWith(".csproj"));
|
|
7541
|
-
const name = csproj ?
|
|
7670
|
+
const name = csproj ? import_node_path14.default.basename(csproj, import_node_path14.default.extname(csproj)) : import_node_path14.default.basename(dir);
|
|
7542
7671
|
let dependencies = {};
|
|
7543
7672
|
if (csproj) {
|
|
7544
|
-
const raw = await
|
|
7673
|
+
const raw = await import_node_fs12.promises.readFile(import_node_path14.default.join(projectDir, csproj), "utf8").catch(() => "");
|
|
7545
7674
|
dependencies = parseCsproj(raw).dependencies;
|
|
7546
7675
|
}
|
|
7547
7676
|
const pkg = { name, dependencies };
|
|
@@ -7553,20 +7682,20 @@ async function discoverCsharpService(scanPath, dir) {
|
|
|
7553
7682
|
dependencies,
|
|
7554
7683
|
// Anchor on the directory that holds the project and its `.cs` files, so file
|
|
7555
7684
|
// attribution reaches the source whether it sits at the root or under `src/`.
|
|
7556
|
-
repoPath:
|
|
7685
|
+
repoPath: import_node_path14.default.relative(scanPath, projectDir)
|
|
7557
7686
|
};
|
|
7558
7687
|
return { pkg, dir: projectDir, node };
|
|
7559
7688
|
}
|
|
7560
7689
|
|
|
7561
7690
|
// src/extract/java.ts
|
|
7562
7691
|
init_cjs_shims();
|
|
7563
|
-
var
|
|
7564
|
-
var
|
|
7692
|
+
var import_node_fs13 = require("fs");
|
|
7693
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
7565
7694
|
var import_types13 = require("@neat.is/types");
|
|
7566
7695
|
var JAVA_MANIFESTS = ["pom.xml", "build.gradle", "build.gradle.kts"];
|
|
7567
7696
|
async function hasJavaManifest(dir) {
|
|
7568
7697
|
for (const manifest of JAVA_MANIFESTS) {
|
|
7569
|
-
if (await exists(
|
|
7698
|
+
if (await exists(import_node_path15.default.join(dir, manifest))) return true;
|
|
7570
7699
|
}
|
|
7571
7700
|
return false;
|
|
7572
7701
|
}
|
|
@@ -7601,19 +7730,19 @@ function parseGradle(source) {
|
|
|
7601
7730
|
return { dependencies };
|
|
7602
7731
|
}
|
|
7603
7732
|
async function discoverJavaService(scanPath, dir) {
|
|
7604
|
-
const pomPath =
|
|
7605
|
-
const gradlePath =
|
|
7606
|
-
const gradleKtsPath =
|
|
7733
|
+
const pomPath = import_node_path15.default.join(dir, "pom.xml");
|
|
7734
|
+
const gradlePath = import_node_path15.default.join(dir, "build.gradle");
|
|
7735
|
+
const gradleKtsPath = import_node_path15.default.join(dir, "build.gradle.kts");
|
|
7607
7736
|
let manifest = null;
|
|
7608
7737
|
if (await exists(pomPath)) {
|
|
7609
|
-
manifest = parsePomXml(await
|
|
7738
|
+
manifest = parsePomXml(await import_node_fs13.promises.readFile(pomPath, "utf8").catch(() => ""));
|
|
7610
7739
|
} else if (await exists(gradlePath)) {
|
|
7611
|
-
manifest = parseGradle(await
|
|
7740
|
+
manifest = parseGradle(await import_node_fs13.promises.readFile(gradlePath, "utf8").catch(() => ""));
|
|
7612
7741
|
} else if (await exists(gradleKtsPath)) {
|
|
7613
|
-
manifest = parseGradle(await
|
|
7742
|
+
manifest = parseGradle(await import_node_fs13.promises.readFile(gradleKtsPath, "utf8").catch(() => ""));
|
|
7614
7743
|
}
|
|
7615
7744
|
if (!manifest) return null;
|
|
7616
|
-
const name = manifest.name?.trim() ||
|
|
7745
|
+
const name = manifest.name?.trim() || import_node_path15.default.basename(dir);
|
|
7617
7746
|
const dependencies = manifest.dependencies;
|
|
7618
7747
|
const pkg = { name, dependencies };
|
|
7619
7748
|
const node = {
|
|
@@ -7622,15 +7751,15 @@ async function discoverJavaService(scanPath, dir) {
|
|
|
7622
7751
|
name,
|
|
7623
7752
|
language: "java",
|
|
7624
7753
|
dependencies,
|
|
7625
|
-
repoPath:
|
|
7754
|
+
repoPath: import_node_path15.default.relative(scanPath, dir)
|
|
7626
7755
|
};
|
|
7627
7756
|
return { pkg, dir, node };
|
|
7628
7757
|
}
|
|
7629
7758
|
|
|
7630
7759
|
// src/extract/kotlin.ts
|
|
7631
7760
|
init_cjs_shims();
|
|
7632
|
-
var
|
|
7633
|
-
var
|
|
7761
|
+
var import_node_fs14 = require("fs");
|
|
7762
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
7634
7763
|
var import_types14 = require("@neat.is/types");
|
|
7635
7764
|
var KOTLIN_SOURCE_EXT = ".kt";
|
|
7636
7765
|
var JAVA_SOURCE_EXT = ".java";
|
|
@@ -7640,15 +7769,15 @@ async function dominantJvmSourceLanguage(dir) {
|
|
|
7640
7769
|
let java = 0;
|
|
7641
7770
|
async function recurse(current, depth) {
|
|
7642
7771
|
if (depth > SOURCE_PROBE_MAX_DEPTH) return;
|
|
7643
|
-
const entries = await
|
|
7772
|
+
const entries = await import_node_fs14.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
7644
7773
|
for (const entry2 of entries) {
|
|
7645
7774
|
if (entry2.isDirectory()) {
|
|
7646
7775
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
7647
|
-
await recurse(
|
|
7776
|
+
await recurse(import_node_path16.default.join(current, entry2.name), depth + 1);
|
|
7648
7777
|
continue;
|
|
7649
7778
|
}
|
|
7650
7779
|
if (!entry2.isFile()) continue;
|
|
7651
|
-
const ext =
|
|
7780
|
+
const ext = import_node_path16.default.extname(entry2.name).toLowerCase();
|
|
7652
7781
|
if (ext === KOTLIN_SOURCE_EXT) kt++;
|
|
7653
7782
|
else if (ext === JAVA_SOURCE_EXT) java++;
|
|
7654
7783
|
}
|
|
@@ -7659,17 +7788,17 @@ async function dominantJvmSourceLanguage(dir) {
|
|
|
7659
7788
|
return void 0;
|
|
7660
7789
|
}
|
|
7661
7790
|
async function readJvmManifest(dir) {
|
|
7662
|
-
const pomPath =
|
|
7663
|
-
const gradlePath =
|
|
7664
|
-
const gradleKtsPath =
|
|
7791
|
+
const pomPath = import_node_path16.default.join(dir, JAVA_MANIFESTS[0]);
|
|
7792
|
+
const gradlePath = import_node_path16.default.join(dir, JAVA_MANIFESTS[1]);
|
|
7793
|
+
const gradleKtsPath = import_node_path16.default.join(dir, JAVA_MANIFESTS[2]);
|
|
7665
7794
|
if (await exists(pomPath)) {
|
|
7666
|
-
return parsePomXml(await
|
|
7795
|
+
return parsePomXml(await import_node_fs14.promises.readFile(pomPath, "utf8").catch(() => ""));
|
|
7667
7796
|
}
|
|
7668
7797
|
if (await exists(gradlePath)) {
|
|
7669
|
-
return parseGradle(await
|
|
7798
|
+
return parseGradle(await import_node_fs14.promises.readFile(gradlePath, "utf8").catch(() => ""));
|
|
7670
7799
|
}
|
|
7671
7800
|
if (await exists(gradleKtsPath)) {
|
|
7672
|
-
return parseGradle(await
|
|
7801
|
+
return parseGradle(await import_node_fs14.promises.readFile(gradleKtsPath, "utf8").catch(() => ""));
|
|
7673
7802
|
}
|
|
7674
7803
|
return null;
|
|
7675
7804
|
}
|
|
@@ -7678,7 +7807,7 @@ async function discoverKotlinService(scanPath, dir) {
|
|
|
7678
7807
|
if (await dominantJvmSourceLanguage(dir) !== "kotlin") return null;
|
|
7679
7808
|
const manifest = await readJvmManifest(dir);
|
|
7680
7809
|
if (!manifest) return null;
|
|
7681
|
-
const name = manifest.name?.trim() ||
|
|
7810
|
+
const name = manifest.name?.trim() || import_node_path16.default.basename(dir);
|
|
7682
7811
|
const dependencies = manifest.dependencies;
|
|
7683
7812
|
const pkg = { name, dependencies };
|
|
7684
7813
|
const node = {
|
|
@@ -7687,20 +7816,20 @@ async function discoverKotlinService(scanPath, dir) {
|
|
|
7687
7816
|
name,
|
|
7688
7817
|
language: "kotlin",
|
|
7689
7818
|
dependencies,
|
|
7690
|
-
repoPath:
|
|
7819
|
+
repoPath: import_node_path16.default.relative(scanPath, dir)
|
|
7691
7820
|
};
|
|
7692
7821
|
return { pkg, dir, node };
|
|
7693
7822
|
}
|
|
7694
7823
|
|
|
7695
7824
|
// src/extract/rust.ts
|
|
7696
7825
|
init_cjs_shims();
|
|
7697
|
-
var
|
|
7698
|
-
var
|
|
7826
|
+
var import_node_fs15 = require("fs");
|
|
7827
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
7699
7828
|
var import_smol_toml2 = require("smol-toml");
|
|
7700
7829
|
var import_types15 = require("@neat.is/types");
|
|
7701
7830
|
var CARGO_MANIFEST = "Cargo.toml";
|
|
7702
7831
|
async function hasRustManifest(dir) {
|
|
7703
|
-
return exists(
|
|
7832
|
+
return exists(import_node_path17.default.join(dir, CARGO_MANIFEST));
|
|
7704
7833
|
}
|
|
7705
7834
|
function parseCargoToml(source) {
|
|
7706
7835
|
const dependencies = {};
|
|
@@ -7725,10 +7854,10 @@ function parseCargoToml(source) {
|
|
|
7725
7854
|
return { name, dependencies };
|
|
7726
7855
|
}
|
|
7727
7856
|
async function discoverRustService(scanPath, dir) {
|
|
7728
|
-
const cargoPath =
|
|
7857
|
+
const cargoPath = import_node_path17.default.join(dir, CARGO_MANIFEST);
|
|
7729
7858
|
if (!await exists(cargoPath)) return null;
|
|
7730
|
-
const manifest = parseCargoToml(await
|
|
7731
|
-
const name = manifest.name?.trim() ||
|
|
7859
|
+
const manifest = parseCargoToml(await import_node_fs15.promises.readFile(cargoPath, "utf8").catch(() => ""));
|
|
7860
|
+
const name = manifest.name?.trim() || import_node_path17.default.basename(dir);
|
|
7732
7861
|
const dependencies = manifest.dependencies;
|
|
7733
7862
|
const pkg = { name, dependencies };
|
|
7734
7863
|
const node = {
|
|
@@ -7737,19 +7866,19 @@ async function discoverRustService(scanPath, dir) {
|
|
|
7737
7866
|
name,
|
|
7738
7867
|
language: "rust",
|
|
7739
7868
|
dependencies,
|
|
7740
|
-
repoPath:
|
|
7869
|
+
repoPath: import_node_path17.default.relative(scanPath, dir)
|
|
7741
7870
|
};
|
|
7742
7871
|
return { pkg, dir, node };
|
|
7743
7872
|
}
|
|
7744
7873
|
|
|
7745
7874
|
// src/extract/cpp.ts
|
|
7746
7875
|
init_cjs_shims();
|
|
7747
|
-
var
|
|
7748
|
-
var
|
|
7876
|
+
var import_node_fs16 = require("fs");
|
|
7877
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
7749
7878
|
var import_types16 = require("@neat.is/types");
|
|
7750
7879
|
var CMAKE_MANIFEST = "CMakeLists.txt";
|
|
7751
7880
|
async function hasCppManifest(dir) {
|
|
7752
|
-
return exists(
|
|
7881
|
+
return exists(import_node_path18.default.join(dir, CMAKE_MANIFEST));
|
|
7753
7882
|
}
|
|
7754
7883
|
function parseCMakeProjectName(source) {
|
|
7755
7884
|
const withoutComments = source.replace(/#.*$/gm, "");
|
|
@@ -7757,10 +7886,10 @@ function parseCMakeProjectName(source) {
|
|
|
7757
7886
|
return m?.[1];
|
|
7758
7887
|
}
|
|
7759
7888
|
async function discoverCppService(scanPath, dir) {
|
|
7760
|
-
const cmakePath =
|
|
7889
|
+
const cmakePath = import_node_path18.default.join(dir, CMAKE_MANIFEST);
|
|
7761
7890
|
if (!await exists(cmakePath)) return null;
|
|
7762
|
-
const source = await
|
|
7763
|
-
const name = parseCMakeProjectName(source)?.trim() ||
|
|
7891
|
+
const source = await import_node_fs16.promises.readFile(cmakePath, "utf8").catch(() => "");
|
|
7892
|
+
const name = parseCMakeProjectName(source)?.trim() || import_node_path18.default.basename(dir);
|
|
7764
7893
|
const dependencies = {};
|
|
7765
7894
|
const pkg = { name, dependencies };
|
|
7766
7895
|
const node = {
|
|
@@ -7769,15 +7898,15 @@ async function discoverCppService(scanPath, dir) {
|
|
|
7769
7898
|
name,
|
|
7770
7899
|
language: "cpp",
|
|
7771
7900
|
dependencies,
|
|
7772
|
-
repoPath:
|
|
7901
|
+
repoPath: import_node_path18.default.relative(scanPath, dir)
|
|
7773
7902
|
};
|
|
7774
7903
|
return { pkg, dir, node };
|
|
7775
7904
|
}
|
|
7776
7905
|
|
|
7777
7906
|
// src/extract/dockerfile-service.ts
|
|
7778
7907
|
init_cjs_shims();
|
|
7779
|
-
var
|
|
7780
|
-
var
|
|
7908
|
+
var import_node_fs17 = require("fs");
|
|
7909
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
7781
7910
|
var import_types17 = require("@neat.is/types");
|
|
7782
7911
|
function languageForSourceExt(ext) {
|
|
7783
7912
|
switch (ext) {
|
|
@@ -7819,12 +7948,12 @@ function languageForSourceExt(ext) {
|
|
|
7819
7948
|
}
|
|
7820
7949
|
var LANGUAGE_PRECEDENCE = ["typescript", "javascript", "python", "go", "ruby", "php", "csharp", "java", "kotlin", "rust", "cpp"];
|
|
7821
7950
|
async function inferServiceLanguage(dir) {
|
|
7822
|
-
const entries = await
|
|
7951
|
+
const entries = await import_node_fs17.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
7823
7952
|
const counts = /* @__PURE__ */ new Map();
|
|
7824
7953
|
for (const entry2 of entries) {
|
|
7825
7954
|
if (!entry2.isFile()) continue;
|
|
7826
7955
|
if (isNeatAuthoredSourceFile(entry2.name)) continue;
|
|
7827
|
-
const ext =
|
|
7956
|
+
const ext = import_node_path19.default.extname(entry2.name).toLowerCase();
|
|
7828
7957
|
if (!SERVICE_FILE_EXTENSIONS.has(ext)) continue;
|
|
7829
7958
|
const lang = languageForSourceExt(ext);
|
|
7830
7959
|
if (!lang) continue;
|
|
@@ -7843,7 +7972,7 @@ async function inferServiceLanguage(dir) {
|
|
|
7843
7972
|
return best;
|
|
7844
7973
|
}
|
|
7845
7974
|
async function hasLanguageManifest(dir) {
|
|
7846
|
-
return await exists(
|
|
7975
|
+
return await exists(import_node_path19.default.join(dir, "package.json")) || await exists(import_node_path19.default.join(dir, "pyproject.toml")) || await exists(import_node_path19.default.join(dir, "requirements.txt")) || await exists(import_node_path19.default.join(dir, "setup.py")) || await exists(import_node_path19.default.join(dir, "go.mod")) || await exists(import_node_path19.default.join(dir, "Gemfile")) || await exists(import_node_path19.default.join(dir, "composer.json")) || // C#'s marker is a glob (`*.csproj` / `*.sln`), so it reads the directory
|
|
7847
7976
|
// rather than probing a fixed filename (ADR-196).
|
|
7848
7977
|
await hasCsharpProject(dir) || // Java (and its JVM sibling Kotlin, ADR-199) key on the same Maven / Gradle
|
|
7849
7978
|
// build manifest (ADR-197), so this one check stands the Dockerfile fallback
|
|
@@ -7853,15 +7982,15 @@ async function hasLanguageManifest(dir) {
|
|
|
7853
7982
|
await hasCppManifest(dir);
|
|
7854
7983
|
}
|
|
7855
7984
|
async function hasDockerfileDeclaredService(dir) {
|
|
7856
|
-
if (!await exists(
|
|
7985
|
+
if (!await exists(import_node_path19.default.join(dir, "Dockerfile"))) return false;
|
|
7857
7986
|
return await inferServiceLanguage(dir) !== null;
|
|
7858
7987
|
}
|
|
7859
7988
|
async function discoverDockerfileService(scanPath, dir) {
|
|
7860
|
-
if (!await exists(
|
|
7989
|
+
if (!await exists(import_node_path19.default.join(dir, "Dockerfile"))) return null;
|
|
7861
7990
|
if (await hasLanguageManifest(dir)) return null;
|
|
7862
7991
|
const language = await inferServiceLanguage(dir);
|
|
7863
7992
|
if (!language) return null;
|
|
7864
|
-
const name =
|
|
7993
|
+
const name = import_node_path19.default.basename(dir);
|
|
7865
7994
|
const pkg = { name, dependencies: {} };
|
|
7866
7995
|
const node = {
|
|
7867
7996
|
id: (0, import_types17.serviceId)(name),
|
|
@@ -7869,24 +7998,24 @@ async function discoverDockerfileService(scanPath, dir) {
|
|
|
7869
7998
|
name,
|
|
7870
7999
|
language,
|
|
7871
8000
|
dependencies: {},
|
|
7872
|
-
repoPath:
|
|
8001
|
+
repoPath: import_node_path19.default.relative(scanPath, dir)
|
|
7873
8002
|
};
|
|
7874
8003
|
return { pkg, dir, node };
|
|
7875
8004
|
}
|
|
7876
8005
|
|
|
7877
8006
|
// src/extract/owners.ts
|
|
7878
8007
|
init_cjs_shims();
|
|
7879
|
-
var
|
|
7880
|
-
var
|
|
8008
|
+
var import_node_fs18 = require("fs");
|
|
8009
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
7881
8010
|
var import_minimatch = require("minimatch");
|
|
7882
8011
|
async function loadCodeowners(scanPath) {
|
|
7883
8012
|
const candidates = [
|
|
7884
|
-
|
|
7885
|
-
|
|
8013
|
+
import_node_path20.default.join(scanPath, "CODEOWNERS"),
|
|
8014
|
+
import_node_path20.default.join(scanPath, ".github", "CODEOWNERS")
|
|
7886
8015
|
];
|
|
7887
8016
|
for (const file of candidates) {
|
|
7888
8017
|
if (await exists(file)) {
|
|
7889
|
-
const raw = await
|
|
8018
|
+
const raw = await import_node_fs18.promises.readFile(file, "utf8");
|
|
7890
8019
|
return parseCodeowners(raw);
|
|
7891
8020
|
}
|
|
7892
8021
|
}
|
|
@@ -7904,7 +8033,7 @@ function parseCodeowners(raw) {
|
|
|
7904
8033
|
return { rules };
|
|
7905
8034
|
}
|
|
7906
8035
|
function matchOwner(file, repoPath) {
|
|
7907
|
-
const normalized = repoPath.split(
|
|
8036
|
+
const normalized = repoPath.split(import_node_path20.default.sep).join("/");
|
|
7908
8037
|
for (const rule of file.rules) {
|
|
7909
8038
|
if (matchesPattern(rule.pattern, normalized)) return rule.owners;
|
|
7910
8039
|
}
|
|
@@ -7920,7 +8049,7 @@ function matchesPattern(rawPattern, repoPath) {
|
|
|
7920
8049
|
return false;
|
|
7921
8050
|
}
|
|
7922
8051
|
async function readPackageJsonAuthor(serviceDir) {
|
|
7923
|
-
const pkgPath =
|
|
8052
|
+
const pkgPath = import_node_path20.default.join(serviceDir, "package.json");
|
|
7924
8053
|
if (!await exists(pkgPath)) return null;
|
|
7925
8054
|
try {
|
|
7926
8055
|
const pkg = await readJson(pkgPath);
|
|
@@ -7957,36 +8086,36 @@ function workspaceGlobs(pkg) {
|
|
|
7957
8086
|
return null;
|
|
7958
8087
|
}
|
|
7959
8088
|
async function hasPythonManifest(dir) {
|
|
7960
|
-
return await exists(
|
|
8089
|
+
return await exists(import_node_path21.default.join(dir, "pyproject.toml")) || await exists(import_node_path21.default.join(dir, "requirements.txt")) || await exists(import_node_path21.default.join(dir, "setup.py"));
|
|
7961
8090
|
}
|
|
7962
8091
|
async function hasGoManifest(dir) {
|
|
7963
|
-
return exists(
|
|
8092
|
+
return exists(import_node_path21.default.join(dir, "go.mod"));
|
|
7964
8093
|
}
|
|
7965
8094
|
async function hasRubyManifest(dir) {
|
|
7966
|
-
return exists(
|
|
8095
|
+
return exists(import_node_path21.default.join(dir, "Gemfile"));
|
|
7967
8096
|
}
|
|
7968
8097
|
async function hasPhpManifest(dir) {
|
|
7969
|
-
return exists(
|
|
8098
|
+
return exists(import_node_path21.default.join(dir, "composer.json"));
|
|
7970
8099
|
}
|
|
7971
8100
|
async function hasCsharpManifest(dir) {
|
|
7972
8101
|
return hasCsharpProject(dir);
|
|
7973
8102
|
}
|
|
7974
8103
|
async function loadGitignore(scanPath) {
|
|
7975
|
-
const gitignorePath =
|
|
8104
|
+
const gitignorePath = import_node_path21.default.join(scanPath, ".gitignore");
|
|
7976
8105
|
if (!await exists(gitignorePath)) return null;
|
|
7977
|
-
const raw = await
|
|
7978
|
-
return (0,
|
|
8106
|
+
const raw = await import_node_fs19.promises.readFile(gitignorePath, "utf8");
|
|
8107
|
+
return (0, import_ignore2.default)().add(raw);
|
|
7979
8108
|
}
|
|
7980
8109
|
async function walkDirs(start, scanPath, options, visit) {
|
|
7981
8110
|
async function recurse(current, depth) {
|
|
7982
8111
|
if (depth > options.maxDepth) return;
|
|
7983
|
-
const entries = await
|
|
8112
|
+
const entries = await import_node_fs19.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
7984
8113
|
for (const entry2 of entries) {
|
|
7985
8114
|
if (!entry2.isDirectory()) continue;
|
|
7986
8115
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
7987
|
-
const child =
|
|
8116
|
+
const child = import_node_path21.default.join(current, entry2.name);
|
|
7988
8117
|
if (options.ig) {
|
|
7989
|
-
const rel =
|
|
8118
|
+
const rel = import_node_path21.default.relative(scanPath, child).split(import_node_path21.default.sep).join("/");
|
|
7990
8119
|
if (rel && options.ig.ignores(rel + "/")) continue;
|
|
7991
8120
|
}
|
|
7992
8121
|
if (await isPythonVenvDir(child)) continue;
|
|
@@ -8002,8 +8131,8 @@ async function expandWorkspaceGlobs(scanPath, globs) {
|
|
|
8002
8131
|
for (const raw of globs) {
|
|
8003
8132
|
const pattern = raw.replace(/^\.\//, "");
|
|
8004
8133
|
if (!pattern.includes("*")) {
|
|
8005
|
-
const candidate =
|
|
8006
|
-
if (await exists(
|
|
8134
|
+
const candidate = import_node_path21.default.join(scanPath, pattern);
|
|
8135
|
+
if (await exists(import_node_path21.default.join(candidate, "package.json"))) found.add(candidate);
|
|
8007
8136
|
continue;
|
|
8008
8137
|
}
|
|
8009
8138
|
const segments = pattern.split("/");
|
|
@@ -8012,13 +8141,13 @@ async function expandWorkspaceGlobs(scanPath, globs) {
|
|
|
8012
8141
|
if (seg.includes("*")) break;
|
|
8013
8142
|
staticSegments.push(seg);
|
|
8014
8143
|
}
|
|
8015
|
-
const start =
|
|
8144
|
+
const start = import_node_path21.default.join(scanPath, ...staticSegments);
|
|
8016
8145
|
if (!await exists(start)) continue;
|
|
8017
8146
|
const hasDoubleStar = pattern.includes("**");
|
|
8018
8147
|
const walkDepth = hasDoubleStar ? scanDepth : Math.max(0, segments.length - staticSegments.length - 1);
|
|
8019
8148
|
await walkDirs(start, scanPath, { maxDepth: walkDepth, ig: null }, async (dir) => {
|
|
8020
|
-
const rel =
|
|
8021
|
-
if ((0, import_minimatch2.minimatch)(rel, pattern) && await exists(
|
|
8149
|
+
const rel = import_node_path21.default.relative(scanPath, dir).split(import_node_path21.default.sep).join("/");
|
|
8150
|
+
if ((0, import_minimatch2.minimatch)(rel, pattern) && await exists(import_node_path21.default.join(dir, "package.json"))) {
|
|
8022
8151
|
found.add(dir);
|
|
8023
8152
|
}
|
|
8024
8153
|
});
|
|
@@ -8041,18 +8170,18 @@ function detectJsFramework(pkg) {
|
|
|
8041
8170
|
async function detectJsServiceLanguage(dir, pkg) {
|
|
8042
8171
|
const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
8043
8172
|
if (deps["typescript"] !== void 0) return "typescript";
|
|
8044
|
-
const entries = await
|
|
8173
|
+
const entries = await import_node_fs19.promises.readdir(dir).catch(() => []);
|
|
8045
8174
|
if (entries.some((name) => /^tsconfig(\..+)?\.json$/.test(name))) return "typescript";
|
|
8046
8175
|
return "javascript";
|
|
8047
8176
|
}
|
|
8048
8177
|
async function discoverNodeService(scanPath, dir) {
|
|
8049
|
-
const pkgPath =
|
|
8178
|
+
const pkgPath = import_node_path21.default.join(dir, "package.json");
|
|
8050
8179
|
if (!await exists(pkgPath)) return null;
|
|
8051
8180
|
let pkg;
|
|
8052
8181
|
try {
|
|
8053
8182
|
pkg = await readJson(pkgPath);
|
|
8054
8183
|
} catch (err) {
|
|
8055
|
-
recordExtractionError("services",
|
|
8184
|
+
recordExtractionError("services", import_node_path21.default.relative(scanPath, pkgPath), err);
|
|
8056
8185
|
return null;
|
|
8057
8186
|
}
|
|
8058
8187
|
if (!pkg.name) return null;
|
|
@@ -8065,7 +8194,7 @@ async function discoverNodeService(scanPath, dir) {
|
|
|
8065
8194
|
language,
|
|
8066
8195
|
version: pkg.version,
|
|
8067
8196
|
dependencies: pkg.dependencies ?? {},
|
|
8068
|
-
repoPath:
|
|
8197
|
+
repoPath: import_node_path21.default.relative(scanPath, dir),
|
|
8069
8198
|
...pkg.engines?.node ? { nodeEngine: pkg.engines.node } : {},
|
|
8070
8199
|
...framework ? { framework } : {}
|
|
8071
8200
|
};
|
|
@@ -8082,12 +8211,12 @@ async function discoverPyService(scanPath, dir) {
|
|
|
8082
8211
|
language: "python",
|
|
8083
8212
|
version: py.version,
|
|
8084
8213
|
dependencies: py.dependencies,
|
|
8085
|
-
repoPath:
|
|
8214
|
+
repoPath: import_node_path21.default.relative(scanPath, dir)
|
|
8086
8215
|
};
|
|
8087
8216
|
return { pkg, dir, node };
|
|
8088
8217
|
}
|
|
8089
8218
|
async function discoverServices(scanPath) {
|
|
8090
|
-
const rootPkgPath =
|
|
8219
|
+
const rootPkgPath = import_node_path21.default.join(scanPath, "package.json");
|
|
8091
8220
|
let rootPkg = null;
|
|
8092
8221
|
if (await exists(rootPkgPath)) {
|
|
8093
8222
|
try {
|
|
@@ -8095,7 +8224,7 @@ async function discoverServices(scanPath) {
|
|
|
8095
8224
|
} catch (err) {
|
|
8096
8225
|
recordExtractionError(
|
|
8097
8226
|
"services workspaces",
|
|
8098
|
-
|
|
8227
|
+
import_node_path21.default.relative(scanPath, rootPkgPath),
|
|
8099
8228
|
err
|
|
8100
8229
|
);
|
|
8101
8230
|
}
|
|
@@ -8116,7 +8245,7 @@ async function discoverServices(scanPath) {
|
|
|
8116
8245
|
scanPath,
|
|
8117
8246
|
{ maxDepth: parseScanDepth(), ig },
|
|
8118
8247
|
async (dir) => {
|
|
8119
|
-
if (await exists(
|
|
8248
|
+
if (await exists(import_node_path21.default.join(dir, "package.json"))) {
|
|
8120
8249
|
candidateDirs.push(dir);
|
|
8121
8250
|
} else if (await hasPythonManifest(dir) || await hasGoManifest(dir) || await hasRubyManifest(dir) || await hasPhpManifest(dir) || await hasCsharpManifest(dir) || await hasJavaManifest(dir) || await hasRustManifest(dir) || await hasCppManifest(dir)) {
|
|
8122
8251
|
candidateDirs.push(dir);
|
|
@@ -8144,8 +8273,8 @@ async function discoverServices(scanPath) {
|
|
|
8144
8273
|
seenDirs.add(service.dir);
|
|
8145
8274
|
const existingDir = seen.get(service.node.name);
|
|
8146
8275
|
if (existingDir !== void 0) {
|
|
8147
|
-
const a =
|
|
8148
|
-
const b =
|
|
8276
|
+
const a = import_node_path21.default.relative(scanPath, existingDir) || ".";
|
|
8277
|
+
const b = import_node_path21.default.relative(scanPath, dir) || ".";
|
|
8149
8278
|
console.warn(
|
|
8150
8279
|
`[neat] duplicate package name "${service.node.name}" \u2014 keeping ${a}, ignoring ${b}`
|
|
8151
8280
|
);
|
|
@@ -8159,14 +8288,14 @@ async function discoverServices(scanPath) {
|
|
|
8159
8288
|
const owner = await computeServiceOwner(codeowners, service.node.repoPath, service.dir);
|
|
8160
8289
|
if (owner !== void 0) service.node.owner = owner;
|
|
8161
8290
|
}
|
|
8162
|
-
const resolvedDirs = out.map((s) =>
|
|
8291
|
+
const resolvedDirs = out.map((s) => import_node_path21.default.resolve(s.dir));
|
|
8163
8292
|
for (let i = 0; i < out.length; i++) {
|
|
8164
8293
|
const self = resolvedDirs[i];
|
|
8165
8294
|
const nested = [];
|
|
8166
8295
|
for (let j = 0; j < out.length; j++) {
|
|
8167
8296
|
if (i === j) continue;
|
|
8168
8297
|
const other = resolvedDirs[j];
|
|
8169
|
-
if (other.startsWith(self +
|
|
8298
|
+
if (other.startsWith(self + import_node_path21.default.sep)) nested.push(other);
|
|
8170
8299
|
}
|
|
8171
8300
|
out[i].excludeDirs = nested;
|
|
8172
8301
|
}
|
|
@@ -8193,8 +8322,8 @@ function addServiceNodes(graph, services) {
|
|
|
8193
8322
|
|
|
8194
8323
|
// src/extract/aliases.ts
|
|
8195
8324
|
init_cjs_shims();
|
|
8196
|
-
var
|
|
8197
|
-
var
|
|
8325
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
8326
|
+
var import_node_fs20 = require("fs");
|
|
8198
8327
|
var import_yaml2 = require("yaml");
|
|
8199
8328
|
var import_types19 = require("@neat.is/types");
|
|
8200
8329
|
var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
@@ -8221,14 +8350,14 @@ function indexServicesByName(services) {
|
|
|
8221
8350
|
const map = /* @__PURE__ */ new Map();
|
|
8222
8351
|
for (const s of services) {
|
|
8223
8352
|
map.set(s.node.name, s.node.id);
|
|
8224
|
-
map.set(
|
|
8353
|
+
map.set(import_node_path22.default.basename(s.dir), s.node.id);
|
|
8225
8354
|
}
|
|
8226
8355
|
return map;
|
|
8227
8356
|
}
|
|
8228
8357
|
async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
8229
8358
|
let composePath = null;
|
|
8230
8359
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
8231
|
-
const abs =
|
|
8360
|
+
const abs = import_node_path22.default.join(scanPath, name);
|
|
8232
8361
|
if (await exists(abs)) {
|
|
8233
8362
|
composePath = abs;
|
|
8234
8363
|
break;
|
|
@@ -8241,7 +8370,7 @@ async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
|
8241
8370
|
} catch (err) {
|
|
8242
8371
|
recordExtractionError(
|
|
8243
8372
|
"aliases compose",
|
|
8244
|
-
|
|
8373
|
+
import_node_path22.default.relative(scanPath, composePath),
|
|
8245
8374
|
err
|
|
8246
8375
|
);
|
|
8247
8376
|
return;
|
|
@@ -8284,11 +8413,11 @@ function parseDockerfileLabels(content) {
|
|
|
8284
8413
|
}
|
|
8285
8414
|
async function collectDockerfileAliases(graph, services) {
|
|
8286
8415
|
for (const service of services) {
|
|
8287
|
-
const dockerfilePath =
|
|
8416
|
+
const dockerfilePath = import_node_path22.default.join(service.dir, "Dockerfile");
|
|
8288
8417
|
if (!await exists(dockerfilePath)) continue;
|
|
8289
8418
|
let content;
|
|
8290
8419
|
try {
|
|
8291
|
-
content = await
|
|
8420
|
+
content = await import_node_fs20.promises.readFile(dockerfilePath, "utf8");
|
|
8292
8421
|
} catch (err) {
|
|
8293
8422
|
recordExtractionError("aliases dockerfile", dockerfilePath, err);
|
|
8294
8423
|
continue;
|
|
@@ -8300,15 +8429,15 @@ async function collectDockerfileAliases(graph, services) {
|
|
|
8300
8429
|
async function walkYamlFiles(start, depth = 0, max = 5) {
|
|
8301
8430
|
if (depth > max) return [];
|
|
8302
8431
|
const out = [];
|
|
8303
|
-
const entries = await
|
|
8432
|
+
const entries = await import_node_fs20.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
8304
8433
|
for (const entry2 of entries) {
|
|
8305
8434
|
if (entry2.isDirectory()) {
|
|
8306
8435
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
8307
|
-
const child =
|
|
8436
|
+
const child = import_node_path22.default.join(start, entry2.name);
|
|
8308
8437
|
if (await isPythonVenvDir(child)) continue;
|
|
8309
8438
|
out.push(...await walkYamlFiles(child, depth + 1, max));
|
|
8310
|
-
} else if (entry2.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
8311
|
-
out.push(
|
|
8439
|
+
} else if (entry2.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path22.default.extname(entry2.name))) {
|
|
8440
|
+
out.push(import_node_path22.default.join(start, entry2.name));
|
|
8312
8441
|
}
|
|
8313
8442
|
}
|
|
8314
8443
|
return out;
|
|
@@ -8335,7 +8464,7 @@ function k8sServiceTarget(doc, byName) {
|
|
|
8335
8464
|
async function collectK8sAliases(graph, scanPath, serviceIndex) {
|
|
8336
8465
|
const files = await walkYamlFiles(scanPath);
|
|
8337
8466
|
for (const file of files) {
|
|
8338
|
-
const content = await
|
|
8467
|
+
const content = await import_node_fs20.promises.readFile(file, "utf8");
|
|
8339
8468
|
let docs;
|
|
8340
8469
|
try {
|
|
8341
8470
|
docs = (0, import_yaml2.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
@@ -8360,14 +8489,14 @@ async function addServiceAliases(graph, scanPath, services) {
|
|
|
8360
8489
|
|
|
8361
8490
|
// src/extract/files.ts
|
|
8362
8491
|
init_cjs_shims();
|
|
8363
|
-
var
|
|
8492
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
8364
8493
|
async function addFiles(graph, services) {
|
|
8365
8494
|
let nodesAdded = 0;
|
|
8366
8495
|
let edgesAdded = 0;
|
|
8367
8496
|
for (const service of services) {
|
|
8368
8497
|
const filePaths = await walkSourceFiles(service.dir, service.excludeDirs);
|
|
8369
8498
|
for (const filePath of filePaths) {
|
|
8370
|
-
const relPath = toPosix(
|
|
8499
|
+
const relPath = toPosix(import_node_path23.default.relative(service.dir, filePath));
|
|
8371
8500
|
const { nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
8372
8501
|
graph,
|
|
8373
8502
|
service.pkg.name,
|
|
@@ -8383,7 +8512,7 @@ async function addFiles(graph, services) {
|
|
|
8383
8512
|
|
|
8384
8513
|
// src/extract/symbols.ts
|
|
8385
8514
|
init_cjs_shims();
|
|
8386
|
-
var
|
|
8515
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
8387
8516
|
var import_tree_sitter3 = __toESM(require("tree-sitter"), 1);
|
|
8388
8517
|
var import_tree_sitter_javascript3 = __toESM(require("tree-sitter-javascript"), 1);
|
|
8389
8518
|
var import_tree_sitter_typescript = __toESM(require("tree-sitter-typescript"), 1);
|
|
@@ -9135,10 +9264,10 @@ async function addSymbols(graph, services) {
|
|
|
9135
9264
|
for (const service of services) {
|
|
9136
9265
|
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
9137
9266
|
for (const file of files) {
|
|
9138
|
-
const ext =
|
|
9267
|
+
const ext = import_node_path24.default.extname(file.path);
|
|
9139
9268
|
const parser = parserForExt5(ext);
|
|
9140
9269
|
if (!parser) continue;
|
|
9141
|
-
const relPath = toPosix(
|
|
9270
|
+
const relPath = toPosix(import_node_path24.default.relative(service.dir, file.path));
|
|
9142
9271
|
let defs;
|
|
9143
9272
|
try {
|
|
9144
9273
|
const tree = parseSource3(parser, file.content);
|
|
@@ -9198,7 +9327,7 @@ async function addSymbols(graph, services) {
|
|
|
9198
9327
|
|
|
9199
9328
|
// src/extract/symbol-edges.ts
|
|
9200
9329
|
init_cjs_shims();
|
|
9201
|
-
var
|
|
9330
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
9202
9331
|
var import_tree_sitter4 = __toESM(require("tree-sitter"), 1);
|
|
9203
9332
|
var import_types21 = require("@neat.is/types");
|
|
9204
9333
|
function extendsInfo(classHeritage) {
|
|
@@ -9305,10 +9434,10 @@ async function addSymbolEdges(graph, services) {
|
|
|
9305
9434
|
const tsPaths = await loadTsPathConfig(service.dir);
|
|
9306
9435
|
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
9307
9436
|
for (const file of files) {
|
|
9308
|
-
const parser = parserForExt5(
|
|
9437
|
+
const parser = parserForExt5(import_node_path25.default.extname(file.path));
|
|
9309
9438
|
if (!parser) continue;
|
|
9310
|
-
const relPath = toPosix(
|
|
9311
|
-
const fileDir =
|
|
9439
|
+
const relPath = toPosix(import_node_path25.default.relative(service.dir, file.path));
|
|
9440
|
+
const fileDir = import_node_path25.default.dirname(file.path);
|
|
9312
9441
|
let root;
|
|
9313
9442
|
try {
|
|
9314
9443
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -9443,7 +9572,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
9443
9572
|
|
|
9444
9573
|
// src/extract/actions.ts
|
|
9445
9574
|
init_cjs_shims();
|
|
9446
|
-
var
|
|
9575
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
9447
9576
|
var import_tree_sitter5 = __toESM(require("tree-sitter"), 1);
|
|
9448
9577
|
var import_types22 = require("@neat.is/types");
|
|
9449
9578
|
function stringLiteralText2(node) {
|
|
@@ -9590,9 +9719,9 @@ async function addServerActions(graph, services) {
|
|
|
9590
9719
|
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
9591
9720
|
for (const file of files) {
|
|
9592
9721
|
if (isTestPath(file.path)) continue;
|
|
9593
|
-
const parser = parserForExt5(
|
|
9722
|
+
const parser = parserForExt5(import_node_path26.default.extname(file.path));
|
|
9594
9723
|
if (!parser) continue;
|
|
9595
|
-
const relPath = toPosix(
|
|
9724
|
+
const relPath = toPosix(import_node_path26.default.relative(service.dir, file.path));
|
|
9596
9725
|
let root;
|
|
9597
9726
|
try {
|
|
9598
9727
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -9653,10 +9782,10 @@ async function addServerActions(graph, services) {
|
|
|
9653
9782
|
}
|
|
9654
9783
|
for (const file of files) {
|
|
9655
9784
|
if (isTestPath(file.path)) continue;
|
|
9656
|
-
const parser = parserForExt5(
|
|
9785
|
+
const parser = parserForExt5(import_node_path26.default.extname(file.path));
|
|
9657
9786
|
if (!parser) continue;
|
|
9658
|
-
const relPath = toPosix(
|
|
9659
|
-
const fileDir =
|
|
9787
|
+
const relPath = toPosix(import_node_path26.default.relative(service.dir, file.path));
|
|
9788
|
+
const fileDir = import_node_path26.default.dirname(file.path);
|
|
9660
9789
|
let root;
|
|
9661
9790
|
try {
|
|
9662
9791
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -9709,14 +9838,14 @@ async function addServerActions(graph, services) {
|
|
|
9709
9838
|
|
|
9710
9839
|
// src/extract/databases/index.ts
|
|
9711
9840
|
init_cjs_shims();
|
|
9712
|
-
var
|
|
9841
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
9713
9842
|
var import_types23 = require("@neat.is/types");
|
|
9714
9843
|
|
|
9715
9844
|
// src/extract/databases/db-config-yaml.ts
|
|
9716
9845
|
init_cjs_shims();
|
|
9717
|
-
var
|
|
9846
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
9718
9847
|
async function parse(serviceDir) {
|
|
9719
|
-
const yamlPath =
|
|
9848
|
+
const yamlPath = import_node_path27.default.join(serviceDir, "db-config.yaml");
|
|
9720
9849
|
if (!await exists(yamlPath)) return [];
|
|
9721
9850
|
const raw = await readYaml(yamlPath);
|
|
9722
9851
|
return [
|
|
@@ -9734,13 +9863,13 @@ var dbConfigYamlParser = { name: "db-config.yaml", parse };
|
|
|
9734
9863
|
|
|
9735
9864
|
// src/extract/databases/dotenv.ts
|
|
9736
9865
|
init_cjs_shims();
|
|
9737
|
-
var
|
|
9738
|
-
var
|
|
9866
|
+
var import_node_fs22 = require("fs");
|
|
9867
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
9739
9868
|
|
|
9740
9869
|
// src/extract/databases/shared.ts
|
|
9741
9870
|
init_cjs_shims();
|
|
9742
|
-
var
|
|
9743
|
-
var
|
|
9871
|
+
var import_node_fs21 = require("fs");
|
|
9872
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
9744
9873
|
function schemeToEngine(scheme) {
|
|
9745
9874
|
const s = scheme.toLowerCase().split("+")[0];
|
|
9746
9875
|
switch (s) {
|
|
@@ -9779,18 +9908,18 @@ function parseConnectionString(url) {
|
|
|
9779
9908
|
}
|
|
9780
9909
|
async function readIfExists(filePath) {
|
|
9781
9910
|
try {
|
|
9782
|
-
return await
|
|
9911
|
+
return await import_node_fs21.promises.readFile(filePath, "utf8");
|
|
9783
9912
|
} catch {
|
|
9784
9913
|
return null;
|
|
9785
9914
|
}
|
|
9786
9915
|
}
|
|
9787
9916
|
async function resolveEnvVar(serviceDir, name) {
|
|
9788
|
-
const entries = await
|
|
9917
|
+
const entries = await import_node_fs21.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
9789
9918
|
const envNames = entries.filter((e) => e.isFile() && (e.name === ".env" || e.name.startsWith(".env."))).map((e) => e.name);
|
|
9790
9919
|
const rank = (n) => n === ".env.local" ? 0 : n === ".env" ? 1 : 2;
|
|
9791
9920
|
envNames.sort((a, b) => rank(a) - rank(b) || a.localeCompare(b));
|
|
9792
9921
|
for (const fileName of envNames) {
|
|
9793
|
-
const content = await readIfExists(
|
|
9922
|
+
const content = await readIfExists(import_node_path28.default.join(serviceDir, fileName));
|
|
9794
9923
|
if (!content) continue;
|
|
9795
9924
|
for (const line of content.split("\n")) {
|
|
9796
9925
|
const trimmed = line.trim();
|
|
@@ -9809,7 +9938,7 @@ async function resolveEnvVar(serviceDir, name) {
|
|
|
9809
9938
|
}
|
|
9810
9939
|
async function findFirst(serviceDir, candidates) {
|
|
9811
9940
|
for (const rel of candidates) {
|
|
9812
|
-
const abs =
|
|
9941
|
+
const abs = import_node_path28.default.join(serviceDir, rel);
|
|
9813
9942
|
const content = await readIfExists(abs);
|
|
9814
9943
|
if (content !== null) return abs;
|
|
9815
9944
|
}
|
|
@@ -9867,15 +9996,15 @@ function parseDotenvLine(line) {
|
|
|
9867
9996
|
return { key, value };
|
|
9868
9997
|
}
|
|
9869
9998
|
async function parse2(serviceDir) {
|
|
9870
|
-
const entries = await
|
|
9999
|
+
const entries = await import_node_fs22.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
9871
10000
|
const configs = [];
|
|
9872
10001
|
const seen = /* @__PURE__ */ new Set();
|
|
9873
10002
|
for (const entry2 of entries) {
|
|
9874
10003
|
if (!entry2.isFile()) continue;
|
|
9875
10004
|
const match = isConfigFile(entry2.name);
|
|
9876
10005
|
if (!match.match || match.fileType !== "env") continue;
|
|
9877
|
-
const filePath =
|
|
9878
|
-
const content = await
|
|
10006
|
+
const filePath = import_node_path29.default.join(serviceDir, entry2.name);
|
|
10007
|
+
const content = await import_node_fs22.promises.readFile(filePath, "utf8");
|
|
9879
10008
|
for (const line of content.split("\n")) {
|
|
9880
10009
|
const parsed = parseDotenvLine(line);
|
|
9881
10010
|
if (!parsed) continue;
|
|
@@ -9894,9 +10023,9 @@ var dotenvParser = { name: ".env", parse: parse2 };
|
|
|
9894
10023
|
|
|
9895
10024
|
// src/extract/databases/prisma.ts
|
|
9896
10025
|
init_cjs_shims();
|
|
9897
|
-
var
|
|
10026
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
9898
10027
|
async function parse3(serviceDir) {
|
|
9899
|
-
const schemaPath =
|
|
10028
|
+
const schemaPath = import_node_path30.default.join(serviceDir, "prisma", "schema.prisma");
|
|
9900
10029
|
const content = await readIfExists(schemaPath);
|
|
9901
10030
|
if (!content) return [];
|
|
9902
10031
|
const block = content.match(/datasource\s+\w+\s*\{([^}]*)\}/s);
|
|
@@ -10054,10 +10183,10 @@ var knexParser = { name: "knex", parse: parse5 };
|
|
|
10054
10183
|
|
|
10055
10184
|
// src/extract/databases/ormconfig.ts
|
|
10056
10185
|
init_cjs_shims();
|
|
10057
|
-
var
|
|
10186
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
10058
10187
|
async function parse6(serviceDir) {
|
|
10059
10188
|
for (const candidate of ["ormconfig.json", "ormconfig.yaml", "ormconfig.yml"]) {
|
|
10060
|
-
const abs =
|
|
10189
|
+
const abs = import_node_path31.default.join(serviceDir, candidate);
|
|
10061
10190
|
if (!await exists(abs)) continue;
|
|
10062
10191
|
const raw = candidate.endsWith(".json") ? await readJson(abs) : await readYaml(abs);
|
|
10063
10192
|
const entries = Array.isArray(raw) ? raw : [raw];
|
|
@@ -10117,9 +10246,9 @@ var typeormParser = { name: "typeorm", parse: parse7 };
|
|
|
10117
10246
|
|
|
10118
10247
|
// src/extract/databases/sequelize.ts
|
|
10119
10248
|
init_cjs_shims();
|
|
10120
|
-
var
|
|
10249
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
10121
10250
|
async function parse8(serviceDir) {
|
|
10122
|
-
const configPath =
|
|
10251
|
+
const configPath = import_node_path32.default.join(serviceDir, "config", "config.json");
|
|
10123
10252
|
if (!await exists(configPath)) return [];
|
|
10124
10253
|
const raw = await readJson(configPath);
|
|
10125
10254
|
const out = [];
|
|
@@ -10146,8 +10275,8 @@ var sequelizeParser = { name: "sequelize", parse: parse8 };
|
|
|
10146
10275
|
|
|
10147
10276
|
// src/extract/databases/csharp.ts
|
|
10148
10277
|
init_cjs_shims();
|
|
10149
|
-
var
|
|
10150
|
-
var
|
|
10278
|
+
var import_node_fs23 = require("fs");
|
|
10279
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
10151
10280
|
var CS_EXT = ".cs";
|
|
10152
10281
|
var NPGSQL_GATE = /\bUseNpgsql\b|\bNpgsql\b/;
|
|
10153
10282
|
var REDIS_GATE = /\bConnectionMultiplexer\b|\bStackExchange\.Redis\b|\bConfigurationOptions\.Parse\b|\bAddStackExchangeRedisCache\b/;
|
|
@@ -10194,12 +10323,12 @@ function parseRedisEndpoint(raw) {
|
|
|
10194
10323
|
return { host, port, database: "", engine: "redis", engineVersion: "unknown" };
|
|
10195
10324
|
}
|
|
10196
10325
|
async function resolveEnvUpTree(startDir, name) {
|
|
10197
|
-
let dir =
|
|
10326
|
+
let dir = import_node_path33.default.resolve(startDir);
|
|
10198
10327
|
for (let depth = 0; depth < 12; depth++) {
|
|
10199
10328
|
const value = await resolveEnvVar(dir, name);
|
|
10200
10329
|
if (value !== null) return value;
|
|
10201
|
-
const atRepoRoot = await
|
|
10202
|
-
const parent =
|
|
10330
|
+
const atRepoRoot = await import_node_fs23.promises.access(import_node_path33.default.join(dir, ".git")).then(() => true).catch(() => false);
|
|
10331
|
+
const parent = import_node_path33.default.dirname(dir);
|
|
10203
10332
|
if (atRepoRoot || parent === dir) break;
|
|
10204
10333
|
dir = parent;
|
|
10205
10334
|
}
|
|
@@ -10254,12 +10383,12 @@ async function resolveConfigs(literals, keys, serviceDir, looksLike, parse11) {
|
|
|
10254
10383
|
}
|
|
10255
10384
|
async function parse9(serviceDir) {
|
|
10256
10385
|
const files = (await walkSourceFiles(serviceDir).catch(() => [])).filter(
|
|
10257
|
-
(f) =>
|
|
10386
|
+
(f) => import_node_path33.default.extname(f) === CS_EXT
|
|
10258
10387
|
);
|
|
10259
10388
|
if (files.length === 0) return [];
|
|
10260
10389
|
const sources = [];
|
|
10261
10390
|
for (const file of files) {
|
|
10262
|
-
const content = await
|
|
10391
|
+
const content = await import_node_fs23.promises.readFile(file, "utf8").catch(() => null);
|
|
10263
10392
|
if (content !== null) sources.push({ file, content });
|
|
10264
10393
|
}
|
|
10265
10394
|
let pgGateFile = null;
|
|
@@ -10300,7 +10429,7 @@ var csharpParser = { name: "csharp", parse: parse9 };
|
|
|
10300
10429
|
|
|
10301
10430
|
// src/extract/databases/docker-compose.ts
|
|
10302
10431
|
init_cjs_shims();
|
|
10303
|
-
var
|
|
10432
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
10304
10433
|
function portFromService(svc) {
|
|
10305
10434
|
for (const raw of svc.ports ?? []) {
|
|
10306
10435
|
const str = String(raw);
|
|
@@ -10327,7 +10456,7 @@ function databaseFromEnv(svc) {
|
|
|
10327
10456
|
}
|
|
10328
10457
|
async function parse10(serviceDir) {
|
|
10329
10458
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
10330
|
-
const abs =
|
|
10459
|
+
const abs = import_node_path34.default.join(serviceDir, name);
|
|
10331
10460
|
if (!await exists(abs)) continue;
|
|
10332
10461
|
const raw = await readYaml(abs);
|
|
10333
10462
|
if (!raw?.services) return [];
|
|
@@ -10500,7 +10629,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
10500
10629
|
discoveredVia: mergedDiscoveredVia
|
|
10501
10630
|
});
|
|
10502
10631
|
}
|
|
10503
|
-
const relConfigFile = toPosix(
|
|
10632
|
+
const relConfigFile = toPosix(import_node_path35.default.relative(service.dir, config.sourceFile));
|
|
10504
10633
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
10505
10634
|
graph,
|
|
10506
10635
|
service.pkg.name,
|
|
@@ -10509,7 +10638,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
10509
10638
|
);
|
|
10510
10639
|
nodesAdded += fn;
|
|
10511
10640
|
edgesAdded += fe;
|
|
10512
|
-
const evidenceFile = toPosix(
|
|
10641
|
+
const evidenceFile = toPosix(import_node_path35.default.relative(scanPath, config.sourceFile));
|
|
10513
10642
|
const edge = {
|
|
10514
10643
|
id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id, import_types23.EdgeType.CONNECTS_TO),
|
|
10515
10644
|
source: fileNodeId,
|
|
@@ -10530,15 +10659,15 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
10530
10659
|
if (allConfigs.length === 1) {
|
|
10531
10660
|
const primary = allConfigs[0];
|
|
10532
10661
|
service.node.dbConnectionTarget = primary.port ? `${primary.host}:${primary.port}` : primary.host;
|
|
10533
|
-
const relPath =
|
|
10662
|
+
const relPath = import_node_path35.default.relative(scanPath, primary.sourceFile);
|
|
10534
10663
|
const cfgId = (0, import_types23.configId)(relPath);
|
|
10535
10664
|
if (!graph.hasNode(cfgId)) {
|
|
10536
10665
|
const cfgNode = {
|
|
10537
10666
|
id: cfgId,
|
|
10538
10667
|
type: import_types23.NodeType.ConfigNode,
|
|
10539
|
-
name:
|
|
10668
|
+
name: import_node_path35.default.basename(primary.sourceFile),
|
|
10540
10669
|
path: relPath,
|
|
10541
|
-
fileType: isConfigFile(
|
|
10670
|
+
fileType: isConfigFile(import_node_path35.default.basename(primary.sourceFile)).fileType || "config"
|
|
10542
10671
|
};
|
|
10543
10672
|
graph.addNode(cfgId, cfgNode);
|
|
10544
10673
|
nodesAdded++;
|
|
@@ -10579,19 +10708,19 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
10579
10708
|
|
|
10580
10709
|
// src/extract/configs.ts
|
|
10581
10710
|
init_cjs_shims();
|
|
10582
|
-
var
|
|
10583
|
-
var
|
|
10711
|
+
var import_node_fs24 = require("fs");
|
|
10712
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
10584
10713
|
var import_types24 = require("@neat.is/types");
|
|
10585
10714
|
async function walkConfigFiles(dir, excludeDirs = []) {
|
|
10586
|
-
const excluded = new Set(excludeDirs.map((d) =>
|
|
10715
|
+
const excluded = new Set(excludeDirs.map((d) => import_node_path36.default.resolve(d)));
|
|
10587
10716
|
const out = [];
|
|
10588
10717
|
async function walk11(current) {
|
|
10589
|
-
const entries = await
|
|
10718
|
+
const entries = await import_node_fs24.promises.readdir(current, { withFileTypes: true });
|
|
10590
10719
|
for (const entry2 of entries) {
|
|
10591
|
-
const full =
|
|
10720
|
+
const full = import_node_path36.default.join(current, entry2.name);
|
|
10592
10721
|
if (entry2.isDirectory()) {
|
|
10593
10722
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
10594
|
-
if (excluded.has(
|
|
10723
|
+
if (excluded.has(import_node_path36.default.resolve(full))) continue;
|
|
10595
10724
|
if (await isPythonVenvDir(full)) continue;
|
|
10596
10725
|
await walk11(full);
|
|
10597
10726
|
} else if (entry2.isFile() && isConfigFile(entry2.name).match) {
|
|
@@ -10608,19 +10737,19 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
10608
10737
|
for (const service of services) {
|
|
10609
10738
|
const configFiles = await walkConfigFiles(service.dir, service.excludeDirs);
|
|
10610
10739
|
for (const file of configFiles) {
|
|
10611
|
-
const relPath =
|
|
10740
|
+
const relPath = import_node_path36.default.relative(scanPath, file);
|
|
10612
10741
|
const node = {
|
|
10613
10742
|
id: (0, import_types24.configId)(relPath),
|
|
10614
10743
|
type: import_types24.NodeType.ConfigNode,
|
|
10615
|
-
name:
|
|
10744
|
+
name: import_node_path36.default.basename(file),
|
|
10616
10745
|
path: relPath,
|
|
10617
|
-
fileType: isConfigFile(
|
|
10746
|
+
fileType: isConfigFile(import_node_path36.default.basename(file)).fileType
|
|
10618
10747
|
};
|
|
10619
10748
|
if (!graph.hasNode(node.id)) {
|
|
10620
10749
|
graph.addNode(node.id, node);
|
|
10621
10750
|
nodesAdded++;
|
|
10622
10751
|
}
|
|
10623
|
-
const relToService = toPosix(
|
|
10752
|
+
const relToService = toPosix(import_node_path36.default.relative(service.dir, file));
|
|
10624
10753
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
10625
10754
|
graph,
|
|
10626
10755
|
service.pkg.name,
|
|
@@ -10636,7 +10765,7 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
10636
10765
|
type: import_types24.EdgeType.CONFIGURED_BY,
|
|
10637
10766
|
provenance: import_types24.Provenance.EXTRACTED,
|
|
10638
10767
|
confidence: (0, import_types24.confidenceForExtracted)("structural"),
|
|
10639
|
-
evidence: { file: relPath.split(
|
|
10768
|
+
evidence: { file: relPath.split(import_node_path36.default.sep).join("/") }
|
|
10640
10769
|
};
|
|
10641
10770
|
if (!graph.hasEdge(edge.id)) {
|
|
10642
10771
|
graph.addEdgeWithKey(edge.id, edge.source, edge.target, edge);
|
|
@@ -10649,8 +10778,8 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
10649
10778
|
|
|
10650
10779
|
// src/extract/proto.ts
|
|
10651
10780
|
init_cjs_shims();
|
|
10652
|
-
var
|
|
10653
|
-
var
|
|
10781
|
+
var import_node_fs25 = require("fs");
|
|
10782
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
10654
10783
|
var import_types25 = require("@neat.is/types");
|
|
10655
10784
|
var PROTO_EXTENSION = ".proto";
|
|
10656
10785
|
function packageOf(content) {
|
|
@@ -10688,18 +10817,18 @@ function grpcMethodsFromProto(content, fqPackage) {
|
|
|
10688
10817
|
return out;
|
|
10689
10818
|
}
|
|
10690
10819
|
async function walkProtoFiles(dir, excludeDirs = []) {
|
|
10691
|
-
const excluded = new Set(excludeDirs.map((d) =>
|
|
10820
|
+
const excluded = new Set(excludeDirs.map((d) => import_node_path37.default.resolve(d)));
|
|
10692
10821
|
const out = [];
|
|
10693
10822
|
async function walk11(current) {
|
|
10694
|
-
const entries = await
|
|
10823
|
+
const entries = await import_node_fs25.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
10695
10824
|
for (const entry2 of entries) {
|
|
10696
|
-
const full =
|
|
10825
|
+
const full = import_node_path37.default.join(current, entry2.name);
|
|
10697
10826
|
if (entry2.isDirectory()) {
|
|
10698
10827
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
10699
|
-
if (excluded.has(
|
|
10828
|
+
if (excluded.has(import_node_path37.default.resolve(full))) continue;
|
|
10700
10829
|
if (await isPythonVenvDir(full)) continue;
|
|
10701
10830
|
await walk11(full);
|
|
10702
|
-
} else if (entry2.isFile() &&
|
|
10831
|
+
} else if (entry2.isFile() && import_node_path37.default.extname(entry2.name) === PROTO_EXTENSION) {
|
|
10703
10832
|
out.push(full);
|
|
10704
10833
|
}
|
|
10705
10834
|
}
|
|
@@ -10714,10 +10843,10 @@ async function addGrpcMethods(graph, services) {
|
|
|
10714
10843
|
const protoPaths = await walkProtoFiles(service.dir, service.excludeDirs);
|
|
10715
10844
|
for (const protoPath of protoPaths) {
|
|
10716
10845
|
if (isTestPath(protoPath)) continue;
|
|
10717
|
-
const relFile = toPosix(
|
|
10846
|
+
const relFile = toPosix(import_node_path37.default.relative(service.dir, protoPath));
|
|
10718
10847
|
let content;
|
|
10719
10848
|
try {
|
|
10720
|
-
content = await
|
|
10849
|
+
content = await import_node_fs25.promises.readFile(protoPath, "utf8");
|
|
10721
10850
|
} catch (err) {
|
|
10722
10851
|
recordExtractionError("proto extraction", protoPath, err);
|
|
10723
10852
|
continue;
|
|
@@ -10776,7 +10905,7 @@ var import_types45 = require("@neat.is/types");
|
|
|
10776
10905
|
|
|
10777
10906
|
// src/extract/calls/http.ts
|
|
10778
10907
|
init_cjs_shims();
|
|
10779
|
-
var
|
|
10908
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
10780
10909
|
var import_tree_sitter6 = __toESM(require("tree-sitter"), 1);
|
|
10781
10910
|
var import_tree_sitter_javascript4 = __toESM(require("tree-sitter-javascript"), 1);
|
|
10782
10911
|
var import_tree_sitter_typescript2 = __toESM(require("tree-sitter-typescript"), 1);
|
|
@@ -10859,7 +10988,7 @@ async function addHttpCallEdges(graph, services) {
|
|
|
10859
10988
|
const seen = /* @__PURE__ */ new Set();
|
|
10860
10989
|
for (const file of files) {
|
|
10861
10990
|
if (isTestPath(file.path)) continue;
|
|
10862
|
-
const parser = parserForExt(
|
|
10991
|
+
const parser = parserForExt(import_node_path38.default.extname(file.path), parserCache);
|
|
10863
10992
|
let sites;
|
|
10864
10993
|
try {
|
|
10865
10994
|
sites = callsFromSource(file.content, parser, knownHosts);
|
|
@@ -10868,7 +10997,7 @@ async function addHttpCallEdges(graph, services) {
|
|
|
10868
10997
|
continue;
|
|
10869
10998
|
}
|
|
10870
10999
|
if (sites.length === 0) continue;
|
|
10871
|
-
const relFile = toPosix(
|
|
11000
|
+
const relFile = toPosix(import_node_path38.default.relative(service.dir, file.path));
|
|
10872
11001
|
for (const site of sites) {
|
|
10873
11002
|
const targetId = hostToNodeId.get(site.host);
|
|
10874
11003
|
if (!targetId || targetId === service.node.id) continue;
|
|
@@ -10922,7 +11051,7 @@ async function addHttpCallEdges(graph, services) {
|
|
|
10922
11051
|
|
|
10923
11052
|
// src/extract/calls/route-match.ts
|
|
10924
11053
|
init_cjs_shims();
|
|
10925
|
-
var
|
|
11054
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
10926
11055
|
var import_tree_sitter7 = __toESM(require("tree-sitter"), 1);
|
|
10927
11056
|
var import_tree_sitter_javascript5 = __toESM(require("tree-sitter-javascript"), 1);
|
|
10928
11057
|
var import_types27 = require("@neat.is/types");
|
|
@@ -11200,7 +11329,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
11200
11329
|
const seen = /* @__PURE__ */ new Set();
|
|
11201
11330
|
for (const file of files) {
|
|
11202
11331
|
if (isTestPath(file.path)) continue;
|
|
11203
|
-
if (!JS_CLIENT_EXTENSIONS.has(
|
|
11332
|
+
if (!JS_CLIENT_EXTENSIONS.has(import_node_path39.default.extname(file.path))) continue;
|
|
11204
11333
|
let sites;
|
|
11205
11334
|
try {
|
|
11206
11335
|
sites = clientCallSitesFromSource(file.content, jsParser, knownHosts);
|
|
@@ -11209,7 +11338,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
11209
11338
|
continue;
|
|
11210
11339
|
}
|
|
11211
11340
|
if (sites.length === 0) continue;
|
|
11212
|
-
const relFile = toPosix(
|
|
11341
|
+
const relFile = toPosix(import_node_path39.default.relative(service.dir, file.path));
|
|
11213
11342
|
for (const site of sites) {
|
|
11214
11343
|
if (site.host === null) {
|
|
11215
11344
|
const dedupKey2 = `${relFile}|unresolved-host`;
|
|
@@ -11302,7 +11431,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
11302
11431
|
|
|
11303
11432
|
// src/extract/calls/kafka.ts
|
|
11304
11433
|
init_cjs_shims();
|
|
11305
|
-
var
|
|
11434
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
11306
11435
|
var import_types28 = require("@neat.is/types");
|
|
11307
11436
|
var PRODUCER_TOPIC_RE = /(?:producer|kafkaProducer)[\s\S]{0,40}?\.send\s*\(\s*\{[\s\S]{0,200}?topic\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
11308
11437
|
var CONSUMER_TOPIC_RE = /(?:consumer|kafkaConsumer)[\s\S]{0,40}?\.(?:subscribe|run)\s*\(\s*\{[\s\S]{0,200}?topic[s]?\s*:\s*(?:\[\s*)?['"`]([^'"`]+)['"`]/g;
|
|
@@ -11390,13 +11519,13 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
11390
11519
|
// call sites — verified-call-site tier (ADR-066).
|
|
11391
11520
|
confidenceKind: "verified-call-site",
|
|
11392
11521
|
evidence: {
|
|
11393
|
-
file:
|
|
11522
|
+
file: import_node_path40.default.relative(serviceDir, file.path),
|
|
11394
11523
|
line,
|
|
11395
11524
|
snippet: snippet(file.content, line)
|
|
11396
11525
|
}
|
|
11397
11526
|
});
|
|
11398
11527
|
};
|
|
11399
|
-
if (
|
|
11528
|
+
if (import_node_path40.default.extname(file.path) === ".go") {
|
|
11400
11529
|
goSaramaEndpoints(file.content, make);
|
|
11401
11530
|
} else {
|
|
11402
11531
|
for (const { topic } of findAll(PRODUCER_TOPIC_RE, file.content)) make(topic, "PUBLISHES_TO");
|
|
@@ -11407,7 +11536,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
11407
11536
|
|
|
11408
11537
|
// src/extract/calls/redis.ts
|
|
11409
11538
|
init_cjs_shims();
|
|
11410
|
-
var
|
|
11539
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
11411
11540
|
var import_types29 = require("@neat.is/types");
|
|
11412
11541
|
var REDIS_URL_RE = /redis(?:s)?:\/\/(?:[^@'"`\s]+@)?([^:/'"`\s]+)(?::(\d+))?/g;
|
|
11413
11542
|
function redisEndpointsFromFile(file, serviceDir) {
|
|
@@ -11430,7 +11559,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
11430
11559
|
// support tier (ADR-066).
|
|
11431
11560
|
confidenceKind: "url-with-structural-support",
|
|
11432
11561
|
evidence: {
|
|
11433
|
-
file:
|
|
11562
|
+
file: import_node_path41.default.relative(serviceDir, file.path),
|
|
11434
11563
|
line,
|
|
11435
11564
|
snippet: snippet(file.content, line)
|
|
11436
11565
|
}
|
|
@@ -11441,7 +11570,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
11441
11570
|
|
|
11442
11571
|
// src/extract/calls/aws.ts
|
|
11443
11572
|
init_cjs_shims();
|
|
11444
|
-
var
|
|
11573
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
11445
11574
|
var import_types30 = require("@neat.is/types");
|
|
11446
11575
|
var S3_BUCKET_RE = /Bucket\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
11447
11576
|
var DYNAMO_TABLE_RE = /TableName\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
@@ -11475,7 +11604,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
11475
11604
|
// (ADR-066).
|
|
11476
11605
|
confidenceKind: "verified-call-site",
|
|
11477
11606
|
evidence: {
|
|
11478
|
-
file:
|
|
11607
|
+
file: import_node_path42.default.relative(serviceDir, file.path),
|
|
11479
11608
|
line,
|
|
11480
11609
|
snippet: snippet(file.content, line)
|
|
11481
11610
|
}
|
|
@@ -11500,7 +11629,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
11500
11629
|
|
|
11501
11630
|
// src/extract/calls/grpc.ts
|
|
11502
11631
|
init_cjs_shims();
|
|
11503
|
-
var
|
|
11632
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
11504
11633
|
var import_types31 = require("@neat.is/types");
|
|
11505
11634
|
var GRPC_CLIENT_RE = /new\s+([A-Z][A-Za-z0-9_]*)Client\s*\(\s*['"`]?([^,'"`)]+)?/g;
|
|
11506
11635
|
var AWS_SDK_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@aws-sdk\/client-([a-z0-9-]+)['"`]/g;
|
|
@@ -11559,7 +11688,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
11559
11688
|
// tier (ADR-066).
|
|
11560
11689
|
confidenceKind: "verified-call-site",
|
|
11561
11690
|
evidence: {
|
|
11562
|
-
file:
|
|
11691
|
+
file: import_node_path43.default.relative(serviceDir, file.path),
|
|
11563
11692
|
line,
|
|
11564
11693
|
snippet: snippet(file.content, line)
|
|
11565
11694
|
}
|
|
@@ -11570,7 +11699,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
11570
11699
|
|
|
11571
11700
|
// src/extract/calls/supabase.ts
|
|
11572
11701
|
init_cjs_shims();
|
|
11573
|
-
var
|
|
11702
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
11574
11703
|
var import_types32 = require("@neat.is/types");
|
|
11575
11704
|
var SUPABASE_JS_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/supabase-js['"`]/;
|
|
11576
11705
|
var SUPABASE_SSR_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/ssr['"`]/;
|
|
@@ -11629,7 +11758,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
11629
11758
|
// tier (ADR-066), the same grade aws.ts / grpc.ts emit at.
|
|
11630
11759
|
confidenceKind: "verified-call-site",
|
|
11631
11760
|
evidence: {
|
|
11632
|
-
file:
|
|
11761
|
+
file: import_node_path44.default.relative(serviceDir, file.path),
|
|
11633
11762
|
line,
|
|
11634
11763
|
snippet: snippet(file.content, line)
|
|
11635
11764
|
}
|
|
@@ -11656,7 +11785,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
11656
11785
|
edgeType: "CALLS",
|
|
11657
11786
|
confidenceKind: "verified-call-site",
|
|
11658
11787
|
evidence: {
|
|
11659
|
-
file:
|
|
11788
|
+
file: import_node_path44.default.relative(serviceDir, file.path),
|
|
11660
11789
|
line,
|
|
11661
11790
|
snippet: snippet(file.content, line)
|
|
11662
11791
|
}
|
|
@@ -11668,7 +11797,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
11668
11797
|
|
|
11669
11798
|
// src/extract/calls/firestore.ts
|
|
11670
11799
|
init_cjs_shims();
|
|
11671
|
-
var
|
|
11800
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
11672
11801
|
var import_tree_sitter8 = __toESM(require("tree-sitter"), 1);
|
|
11673
11802
|
var import_tree_sitter_javascript6 = __toESM(require("tree-sitter-javascript"), 1);
|
|
11674
11803
|
var import_types33 = require("@neat.is/types");
|
|
@@ -11841,7 +11970,7 @@ function firestoreEndpointsFromFile(file, serviceDir, imported) {
|
|
|
11841
11970
|
if (!hasClient && !hasAdmin && importedNames.size === 0) return [];
|
|
11842
11971
|
const ownSdk = hasClient && !hasAdmin ? "client" : hasAdmin && !hasClient ? "admin" : null;
|
|
11843
11972
|
const fileSdk = !hasClient && !hasAdmin ? imported?.sdk ?? null : ownSdk;
|
|
11844
|
-
const tree = parseSource3(parserForExt2(
|
|
11973
|
+
const tree = parseSource3(parserForExt2(import_node_path45.default.extname(file.path)), file.content);
|
|
11845
11974
|
const clientVars = firestoreClientVars(tree.rootNode);
|
|
11846
11975
|
for (const n of importedNames) clientVars.add(n);
|
|
11847
11976
|
const collLine = /* @__PURE__ */ new Map();
|
|
@@ -11946,7 +12075,7 @@ function firestoreEndpointsFromFile(file, serviceDir, imported) {
|
|
|
11946
12075
|
...columnSet.size > 0 ? { columns: [...columnSet] } : {},
|
|
11947
12076
|
...sdkWrites ? { sdkWrites } : {},
|
|
11948
12077
|
evidence: {
|
|
11949
|
-
file:
|
|
12078
|
+
file: import_node_path45.default.relative(serviceDir, file.path),
|
|
11950
12079
|
line,
|
|
11951
12080
|
snippet: snippet(file.content, line)
|
|
11952
12081
|
}
|
|
@@ -12006,7 +12135,7 @@ function sdkOf(content) {
|
|
|
12006
12135
|
return hasClient && !hasAdmin ? "client" : hasAdmin && !hasClient ? "admin" : null;
|
|
12007
12136
|
}
|
|
12008
12137
|
function parseOrNull(file) {
|
|
12009
|
-
const ext =
|
|
12138
|
+
const ext = import_node_path45.default.extname(file.path);
|
|
12010
12139
|
if (!(ext in GRAMMAR_BY_EXT)) return null;
|
|
12011
12140
|
try {
|
|
12012
12141
|
return parseSource3(parserForExt2(ext), file.content).rootNode;
|
|
@@ -12022,7 +12151,7 @@ async function firestoreCrossFileEndpoints(files, serviceDir) {
|
|
|
12022
12151
|
if (!root) continue;
|
|
12023
12152
|
const names = exportedFirestoreClients(root);
|
|
12024
12153
|
if (names.size === 0) continue;
|
|
12025
|
-
registry.set(toPosix(
|
|
12154
|
+
registry.set(toPosix(import_node_path45.default.relative(serviceDir, f.path)), { names, sdk: sdkOf(f.content) });
|
|
12026
12155
|
}
|
|
12027
12156
|
if (registry.size === 0) return [];
|
|
12028
12157
|
const out = [];
|
|
@@ -12035,7 +12164,7 @@ async function firestoreCrossFileEndpoints(files, serviceDir) {
|
|
|
12035
12164
|
const names = /* @__PURE__ */ new Set();
|
|
12036
12165
|
let sdk = null;
|
|
12037
12166
|
for (const b of bindings) {
|
|
12038
|
-
const rel = await resolveJsImport(b.specifier,
|
|
12167
|
+
const rel = await resolveJsImport(b.specifier, import_node_path45.default.dirname(f.path), serviceDir, null);
|
|
12039
12168
|
if (!rel) continue;
|
|
12040
12169
|
const entry2 = registry.get(rel);
|
|
12041
12170
|
if (!entry2 || !entry2.names.has(b.imported)) continue;
|
|
@@ -12050,7 +12179,7 @@ async function firestoreCrossFileEndpoints(files, serviceDir) {
|
|
|
12050
12179
|
|
|
12051
12180
|
// src/extract/calls/mongoose.ts
|
|
12052
12181
|
init_cjs_shims();
|
|
12053
|
-
var
|
|
12182
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
12054
12183
|
var import_types34 = require("@neat.is/types");
|
|
12055
12184
|
var MONGOOSE_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongoose['"`]/;
|
|
12056
12185
|
var MONGODB_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongodb['"`]/;
|
|
@@ -12201,7 +12330,7 @@ function endpoint(r, file, serviceDir, matchText) {
|
|
|
12201
12330
|
kind: r.kind,
|
|
12202
12331
|
edgeType: "CALLS",
|
|
12203
12332
|
confidenceKind: "verified-call-site",
|
|
12204
|
-
evidence: { file:
|
|
12333
|
+
evidence: { file: import_node_path46.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
12205
12334
|
};
|
|
12206
12335
|
}
|
|
12207
12336
|
function mongooseEndpointsFromFile(file, serviceDir) {
|
|
@@ -12291,7 +12420,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
12291
12420
|
const registry = /* @__PURE__ */ new Map();
|
|
12292
12421
|
for (const f of mongooseFiles) {
|
|
12293
12422
|
const fx = fileExportsOf(f.content, pluralizeOn);
|
|
12294
|
-
if (fx) registry.set(toPosix(
|
|
12423
|
+
if (fx) registry.set(toPosix(import_node_path46.default.relative(serviceDir, f.path)), fx);
|
|
12295
12424
|
}
|
|
12296
12425
|
if (registry.size === 0) return [];
|
|
12297
12426
|
const out = [];
|
|
@@ -12302,7 +12431,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
12302
12431
|
const directColl = /* @__PURE__ */ new Map();
|
|
12303
12432
|
const nsExports = /* @__PURE__ */ new Map();
|
|
12304
12433
|
for (const b of bindings) {
|
|
12305
|
-
const resolvedRel = await resolveJsImport(b.specifier,
|
|
12434
|
+
const resolvedRel = await resolveJsImport(b.specifier, import_node_path46.default.dirname(f.path), serviceDir, null);
|
|
12306
12435
|
if (!resolvedRel) continue;
|
|
12307
12436
|
const fx = registry.get(resolvedRel);
|
|
12308
12437
|
if (!fx) continue;
|
|
@@ -12346,7 +12475,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
12346
12475
|
|
|
12347
12476
|
// src/extract/calls/sqlalchemy.ts
|
|
12348
12477
|
init_cjs_shims();
|
|
12349
|
-
var
|
|
12478
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
12350
12479
|
var import_tree_sitter9 = __toESM(require("tree-sitter"), 1);
|
|
12351
12480
|
var import_tree_sitter_python5 = __toESM(require("tree-sitter-python"), 1);
|
|
12352
12481
|
var import_types35 = require("@neat.is/types");
|
|
@@ -12485,7 +12614,7 @@ function sqlalchemyForeignKeys(file, serviceDir) {
|
|
|
12485
12614
|
childTable,
|
|
12486
12615
|
parentTable,
|
|
12487
12616
|
evidence: {
|
|
12488
|
-
file:
|
|
12617
|
+
file: import_node_path47.default.relative(serviceDir, file.path),
|
|
12489
12618
|
line,
|
|
12490
12619
|
snippet: snippet(file.content, line)
|
|
12491
12620
|
}
|
|
@@ -12510,7 +12639,7 @@ function sqlalchemyEndpointsFromFile(file, serviceDir) {
|
|
|
12510
12639
|
confidenceKind: "verified-call-site",
|
|
12511
12640
|
...columns && columns.length > 0 ? { columns } : {},
|
|
12512
12641
|
evidence: {
|
|
12513
|
-
file:
|
|
12642
|
+
file: import_node_path47.default.relative(serviceDir, file.path),
|
|
12514
12643
|
line,
|
|
12515
12644
|
snippet: snippet(file.content, line)
|
|
12516
12645
|
}
|
|
@@ -12617,7 +12746,7 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
|
|
|
12617
12746
|
edgeType: "CALLS",
|
|
12618
12747
|
confidenceKind: "verified-call-site",
|
|
12619
12748
|
evidence: {
|
|
12620
|
-
file:
|
|
12749
|
+
file: import_node_path47.default.relative(serviceDir, file.path),
|
|
12621
12750
|
line,
|
|
12622
12751
|
snippet: snippet(file.content, line)
|
|
12623
12752
|
}
|
|
@@ -12629,7 +12758,7 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
|
|
|
12629
12758
|
|
|
12630
12759
|
// src/extract/calls/socket.ts
|
|
12631
12760
|
init_cjs_shims();
|
|
12632
|
-
var
|
|
12761
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
12633
12762
|
var import_tree_sitter10 = __toESM(require("tree-sitter"), 1);
|
|
12634
12763
|
var import_tree_sitter_python6 = __toESM(require("tree-sitter-python"), 1);
|
|
12635
12764
|
var import_types36 = require("@neat.is/types");
|
|
@@ -12705,7 +12834,7 @@ function socketEndpointsFromFile(file, serviceDir) {
|
|
|
12705
12834
|
// A verified `socket.socket(...)` + `.connect((host, port))` call site.
|
|
12706
12835
|
confidenceKind: "verified-call-site",
|
|
12707
12836
|
evidence: {
|
|
12708
|
-
file:
|
|
12837
|
+
file: import_node_path48.default.relative(serviceDir, file.path),
|
|
12709
12838
|
line,
|
|
12710
12839
|
snippet: snippet(file.content, line)
|
|
12711
12840
|
}
|
|
@@ -12716,7 +12845,7 @@ function socketEndpointsFromFile(file, serviceDir) {
|
|
|
12716
12845
|
|
|
12717
12846
|
// src/extract/calls/django-orm.ts
|
|
12718
12847
|
init_cjs_shims();
|
|
12719
|
-
var
|
|
12848
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
12720
12849
|
var import_tree_sitter11 = __toESM(require("tree-sitter"), 1);
|
|
12721
12850
|
var import_tree_sitter_python7 = __toESM(require("tree-sitter-python"), 1);
|
|
12722
12851
|
var import_types37 = require("@neat.is/types");
|
|
@@ -12786,7 +12915,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
12786
12915
|
const tree = parseSource8(makePyParser5(), file.content);
|
|
12787
12916
|
const out = [];
|
|
12788
12917
|
const seen = /* @__PURE__ */ new Set();
|
|
12789
|
-
const defaultAppLabel =
|
|
12918
|
+
const defaultAppLabel = import_node_path49.default.basename(import_node_path49.default.dirname(file.path));
|
|
12790
12919
|
walk5(tree.rootNode, (node) => {
|
|
12791
12920
|
if (node.type !== "class_definition") return;
|
|
12792
12921
|
if (!extendsDjangoModel(node)) return;
|
|
@@ -12804,7 +12933,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
12804
12933
|
kind: "sql-table",
|
|
12805
12934
|
edgeType: "CALLS",
|
|
12806
12935
|
confidenceKind: "verified-call-site",
|
|
12807
|
-
evidence: { file:
|
|
12936
|
+
evidence: { file: import_node_path49.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
12808
12937
|
});
|
|
12809
12938
|
});
|
|
12810
12939
|
return out;
|
|
@@ -12812,7 +12941,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
12812
12941
|
|
|
12813
12942
|
// src/extract/calls/drizzle.ts
|
|
12814
12943
|
init_cjs_shims();
|
|
12815
|
-
var
|
|
12944
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
12816
12945
|
var import_tree_sitter12 = __toESM(require("tree-sitter"), 1);
|
|
12817
12946
|
var import_tree_sitter_javascript7 = __toESM(require("tree-sitter-javascript"), 1);
|
|
12818
12947
|
var import_types38 = require("@neat.is/types");
|
|
@@ -12890,7 +13019,7 @@ function columnsFromObject(obj) {
|
|
|
12890
13019
|
}
|
|
12891
13020
|
function drizzleEndpointsFromFile(file, serviceDir) {
|
|
12892
13021
|
if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
|
|
12893
|
-
const tree = parseSource3(parserForExt3(
|
|
13022
|
+
const tree = parseSource3(parserForExt3(import_node_path50.default.extname(file.path)), file.content);
|
|
12894
13023
|
const out = [];
|
|
12895
13024
|
const seen = /* @__PURE__ */ new Set();
|
|
12896
13025
|
const walk11 = (node) => {
|
|
@@ -12913,7 +13042,7 @@ function drizzleEndpointsFromFile(file, serviceDir) {
|
|
|
12913
13042
|
confidenceKind: "structural",
|
|
12914
13043
|
columns,
|
|
12915
13044
|
evidence: {
|
|
12916
|
-
file:
|
|
13045
|
+
file: import_node_path50.default.relative(serviceDir, file.path),
|
|
12917
13046
|
line,
|
|
12918
13047
|
snippet: snippet(file.content, line)
|
|
12919
13048
|
}
|
|
@@ -12979,7 +13108,7 @@ function referencesTargetVar(call) {
|
|
|
12979
13108
|
}
|
|
12980
13109
|
function drizzleForeignKeys(file, serviceDir) {
|
|
12981
13110
|
if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
|
|
12982
|
-
const tree = parseSource3(parserForExt3(
|
|
13111
|
+
const tree = parseSource3(parserForExt3(import_node_path50.default.extname(file.path)), file.content);
|
|
12983
13112
|
const { tables, varToTable } = collectDrizzleTables(tree.rootNode);
|
|
12984
13113
|
const out = [];
|
|
12985
13114
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -12998,7 +13127,7 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
12998
13127
|
childTable: table.tableName,
|
|
12999
13128
|
parentTable,
|
|
13000
13129
|
evidence: {
|
|
13001
|
-
file:
|
|
13130
|
+
file: import_node_path50.default.relative(serviceDir, file.path),
|
|
13002
13131
|
line,
|
|
13003
13132
|
snippet: snippet(file.content, line)
|
|
13004
13133
|
}
|
|
@@ -13015,7 +13144,7 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
13015
13144
|
|
|
13016
13145
|
// src/extract/calls/prisma.ts
|
|
13017
13146
|
init_cjs_shims();
|
|
13018
|
-
var
|
|
13147
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
13019
13148
|
var import_types39 = require("@neat.is/types");
|
|
13020
13149
|
var SCALAR_TYPES = /* @__PURE__ */ new Set([
|
|
13021
13150
|
"Int",
|
|
@@ -13071,7 +13200,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
|
|
|
13071
13200
|
confidenceKind: "structural",
|
|
13072
13201
|
columns: b.columns,
|
|
13073
13202
|
evidence: {
|
|
13074
|
-
file:
|
|
13203
|
+
file: import_node_path51.default.relative(serviceDir, file.path),
|
|
13075
13204
|
line: b.startLine,
|
|
13076
13205
|
snippet: snippet(content, b.startLine)
|
|
13077
13206
|
}
|
|
@@ -13132,7 +13261,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
|
|
|
13132
13261
|
}
|
|
13133
13262
|
async function prismaColumnEndpoints(serviceDir) {
|
|
13134
13263
|
const schemaPath = await findFirst(serviceDir, [
|
|
13135
|
-
|
|
13264
|
+
import_node_path51.default.join("prisma", "schema.prisma"),
|
|
13136
13265
|
"schema.prisma"
|
|
13137
13266
|
]);
|
|
13138
13267
|
if (!schemaPath) return [];
|
|
@@ -13207,7 +13336,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
|
|
|
13207
13336
|
childTable: current.table,
|
|
13208
13337
|
parentTable,
|
|
13209
13338
|
evidence: {
|
|
13210
|
-
file:
|
|
13339
|
+
file: import_node_path51.default.relative(serviceDir, file.path),
|
|
13211
13340
|
line: lineNo,
|
|
13212
13341
|
snippet: snippet(content, lineNo)
|
|
13213
13342
|
}
|
|
@@ -13222,7 +13351,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
|
|
|
13222
13351
|
}
|
|
13223
13352
|
async function prismaForeignKeys(serviceDir) {
|
|
13224
13353
|
const schemaPath = await findFirst(serviceDir, [
|
|
13225
|
-
|
|
13354
|
+
import_node_path51.default.join("prisma", "schema.prisma"),
|
|
13226
13355
|
"schema.prisma"
|
|
13227
13356
|
]);
|
|
13228
13357
|
if (!schemaPath) return [];
|
|
@@ -13233,7 +13362,7 @@ async function prismaForeignKeys(serviceDir) {
|
|
|
13233
13362
|
|
|
13234
13363
|
// src/extract/calls/activerecord.ts
|
|
13235
13364
|
init_cjs_shims();
|
|
13236
|
-
var
|
|
13365
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
13237
13366
|
var import_tree_sitter13 = __toESM(require("tree-sitter"), 1);
|
|
13238
13367
|
var import_tree_sitter_ruby3 = __toESM(require("tree-sitter-ruby"), 1);
|
|
13239
13368
|
var import_types40 = require("@neat.is/types");
|
|
@@ -13441,7 +13570,7 @@ function railsSchemaEndpointsFromFile(file, serviceDir) {
|
|
|
13441
13570
|
confidenceKind: "structural",
|
|
13442
13571
|
...table.columns.length > 0 ? { columns: table.columns } : {},
|
|
13443
13572
|
evidence: {
|
|
13444
|
-
file:
|
|
13573
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
13445
13574
|
line: table.line,
|
|
13446
13575
|
snippet: snippet(file.content, table.line)
|
|
13447
13576
|
}
|
|
@@ -13463,7 +13592,7 @@ function railsSchemaForeignKeys(file, serviceDir) {
|
|
|
13463
13592
|
childTable,
|
|
13464
13593
|
parentTable,
|
|
13465
13594
|
evidence: {
|
|
13466
|
-
file:
|
|
13595
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
13467
13596
|
line,
|
|
13468
13597
|
snippet: snippet(file.content, line)
|
|
13469
13598
|
}
|
|
@@ -13546,7 +13675,7 @@ function railsModelEndpointsFromFile(file, serviceDir) {
|
|
|
13546
13675
|
edgeType: "CALLS",
|
|
13547
13676
|
confidenceKind: "verified-call-site",
|
|
13548
13677
|
evidence: {
|
|
13549
|
-
file:
|
|
13678
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
13550
13679
|
line,
|
|
13551
13680
|
snippet: snippet(file.content, line)
|
|
13552
13681
|
}
|
|
@@ -13583,7 +13712,7 @@ function railsModelForeignKeys(file, serviceDir) {
|
|
|
13583
13712
|
childTable,
|
|
13584
13713
|
parentTable,
|
|
13585
13714
|
evidence: {
|
|
13586
|
-
file:
|
|
13715
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
13587
13716
|
line,
|
|
13588
13717
|
snippet: snippet(file.content, line)
|
|
13589
13718
|
}
|
|
@@ -13595,7 +13724,7 @@ function railsModelForeignKeys(file, serviceDir) {
|
|
|
13595
13724
|
|
|
13596
13725
|
// src/extract/calls/eloquent.ts
|
|
13597
13726
|
init_cjs_shims();
|
|
13598
|
-
var
|
|
13727
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
13599
13728
|
var import_tree_sitter14 = __toESM(require("tree-sitter"), 1);
|
|
13600
13729
|
var import_tree_sitter_php3 = __toESM(require("tree-sitter-php"), 1);
|
|
13601
13730
|
var import_types41 = require("@neat.is/types");
|
|
@@ -13852,7 +13981,7 @@ function laravelMigrationEndpointsFromFile(file, serviceDir) {
|
|
|
13852
13981
|
confidenceKind: "structural",
|
|
13853
13982
|
...columns.length > 0 ? { columns } : {},
|
|
13854
13983
|
evidence: {
|
|
13855
|
-
file:
|
|
13984
|
+
file: import_node_path53.default.relative(serviceDir, file.path),
|
|
13856
13985
|
line: bp.line,
|
|
13857
13986
|
snippet: snippet(file.content, bp.line)
|
|
13858
13987
|
}
|
|
@@ -13874,7 +14003,7 @@ function laravelMigrationForeignKeys(file, serviceDir) {
|
|
|
13874
14003
|
childTable,
|
|
13875
14004
|
parentTable,
|
|
13876
14005
|
evidence: {
|
|
13877
|
-
file:
|
|
14006
|
+
file: import_node_path53.default.relative(serviceDir, file.path),
|
|
13878
14007
|
line,
|
|
13879
14008
|
snippet: snippet(file.content, line)
|
|
13880
14009
|
}
|
|
@@ -13994,7 +14123,7 @@ function laravelModelEndpointsFromFile(file, serviceDir) {
|
|
|
13994
14123
|
edgeType: "CALLS",
|
|
13995
14124
|
confidenceKind: "verified-call-site",
|
|
13996
14125
|
evidence: {
|
|
13997
|
-
file:
|
|
14126
|
+
file: import_node_path53.default.relative(serviceDir, file.path),
|
|
13998
14127
|
line,
|
|
13999
14128
|
snippet: snippet(file.content, line)
|
|
14000
14129
|
}
|
|
@@ -14030,7 +14159,7 @@ function laravelModelForeignKeys(file, serviceDir) {
|
|
|
14030
14159
|
childTable,
|
|
14031
14160
|
parentTable,
|
|
14032
14161
|
evidence: {
|
|
14033
|
-
file:
|
|
14162
|
+
file: import_node_path53.default.relative(serviceDir, file.path),
|
|
14034
14163
|
line,
|
|
14035
14164
|
snippet: snippet(file.content, line)
|
|
14036
14165
|
}
|
|
@@ -14042,7 +14171,7 @@ function laravelModelForeignKeys(file, serviceDir) {
|
|
|
14042
14171
|
|
|
14043
14172
|
// src/extract/calls/go.ts
|
|
14044
14173
|
init_cjs_shims();
|
|
14045
|
-
var
|
|
14174
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
14046
14175
|
var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
|
|
14047
14176
|
var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
|
|
14048
14177
|
var import_types42 = require("@neat.is/types");
|
|
@@ -14117,7 +14246,7 @@ function firstStringLiteralArg(argsNode) {
|
|
|
14117
14246
|
return null;
|
|
14118
14247
|
}
|
|
14119
14248
|
function goSqlEndpointsFromFile(file, serviceDir) {
|
|
14120
|
-
if (
|
|
14249
|
+
if (import_node_path56.default.extname(file.path) !== ".go") return [];
|
|
14121
14250
|
if (!file.content.includes(DATABASE_SQL_IMPORT) && !file.content.includes(SQLX_IMPORT)) return [];
|
|
14122
14251
|
const tree = parseSource11(makeGoParser3(), file.content);
|
|
14123
14252
|
const importsDatabaseSql = goImportsAny(tree.rootNode, /* @__PURE__ */ new Set([DATABASE_SQL_IMPORT]));
|
|
@@ -14146,7 +14275,7 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
14146
14275
|
confidenceKind: "verified-call-site",
|
|
14147
14276
|
...columns.length > 0 ? { columns } : {},
|
|
14148
14277
|
evidence: {
|
|
14149
|
-
file: toPosix(
|
|
14278
|
+
file: toPosix(import_node_path56.default.relative(serviceDir, file.path)),
|
|
14150
14279
|
line,
|
|
14151
14280
|
snippet: snippet(file.content, line)
|
|
14152
14281
|
}
|
|
@@ -14157,7 +14286,7 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
14157
14286
|
|
|
14158
14287
|
// src/extract/calls/gorm.ts
|
|
14159
14288
|
init_cjs_shims();
|
|
14160
|
-
var
|
|
14289
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
14161
14290
|
var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
|
|
14162
14291
|
var import_tree_sitter_go5 = __toESM(require("tree-sitter-go"), 1);
|
|
14163
14292
|
var import_types43 = require("@neat.is/types");
|
|
@@ -14590,7 +14719,7 @@ function collectColumns(struct, structs, seen, prefix, out, emitted) {
|
|
|
14590
14719
|
seen.delete(struct.name);
|
|
14591
14720
|
}
|
|
14592
14721
|
function gormEndpointsFromFile(file, serviceDir) {
|
|
14593
|
-
if (
|
|
14722
|
+
if (import_node_path57.default.extname(file.path) !== ".go") return [];
|
|
14594
14723
|
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
14595
14724
|
const tree = parseSource12(makeGoParser4(), file.content);
|
|
14596
14725
|
const { structs, models, tableFor } = analyze(tree);
|
|
@@ -14612,7 +14741,7 @@ function gormEndpointsFromFile(file, serviceDir) {
|
|
|
14612
14741
|
confidenceKind: "structural",
|
|
14613
14742
|
...columns.length > 0 ? { columns } : {},
|
|
14614
14743
|
evidence: {
|
|
14615
|
-
file: toPosix(
|
|
14744
|
+
file: toPosix(import_node_path57.default.relative(serviceDir, file.path)),
|
|
14616
14745
|
line: struct.line,
|
|
14617
14746
|
snippet: snippet(file.content, struct.line)
|
|
14618
14747
|
}
|
|
@@ -14621,7 +14750,7 @@ function gormEndpointsFromFile(file, serviceDir) {
|
|
|
14621
14750
|
return out;
|
|
14622
14751
|
}
|
|
14623
14752
|
function gormForeignKeys(file, serviceDir) {
|
|
14624
|
-
if (
|
|
14753
|
+
if (import_node_path57.default.extname(file.path) !== ".go") return [];
|
|
14625
14754
|
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
14626
14755
|
const tree = parseSource12(makeGoParser4(), file.content);
|
|
14627
14756
|
const { structs, models, tableFor } = analyze(tree);
|
|
@@ -14636,7 +14765,7 @@ function gormForeignKeys(file, serviceDir) {
|
|
|
14636
14765
|
childTable,
|
|
14637
14766
|
parentTable,
|
|
14638
14767
|
evidence: {
|
|
14639
|
-
file: toPosix(
|
|
14768
|
+
file: toPosix(import_node_path57.default.relative(serviceDir, file.path)),
|
|
14640
14769
|
line,
|
|
14641
14770
|
snippet: snippet(file.content, line)
|
|
14642
14771
|
}
|
|
@@ -14673,7 +14802,7 @@ function gormForeignKeys(file, serviceDir) {
|
|
|
14673
14802
|
|
|
14674
14803
|
// src/extract/calls/efcore.ts
|
|
14675
14804
|
init_cjs_shims();
|
|
14676
|
-
var
|
|
14805
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
14677
14806
|
var import_tree_sitter17 = __toESM(require("tree-sitter"), 1);
|
|
14678
14807
|
var import_tree_sitter_c_sharp2 = __toESM(require("tree-sitter-c-sharp"), 1);
|
|
14679
14808
|
var import_types44 = require("@neat.is/types");
|
|
@@ -14752,7 +14881,7 @@ function tableFromToTable(call) {
|
|
|
14752
14881
|
return value ? csStringLiteral(value) : null;
|
|
14753
14882
|
}
|
|
14754
14883
|
function efcoreEndpointsFromFile(file, serviceDir) {
|
|
14755
|
-
if (
|
|
14884
|
+
if (import_node_path58.default.extname(file.path) !== ".cs") return [];
|
|
14756
14885
|
if (!EFCORE_GATE.test(file.content)) return [];
|
|
14757
14886
|
const tree = parseSource13(makeCsParser(), file.content);
|
|
14758
14887
|
const out = [];
|
|
@@ -14767,7 +14896,7 @@ function efcoreEndpointsFromFile(file, serviceDir) {
|
|
|
14767
14896
|
edgeType: "CALLS",
|
|
14768
14897
|
confidenceKind: "structural",
|
|
14769
14898
|
evidence: {
|
|
14770
|
-
file: toPosix(
|
|
14899
|
+
file: toPosix(import_node_path58.default.relative(serviceDir, file.path)),
|
|
14771
14900
|
line,
|
|
14772
14901
|
snippet: snippet(file.content, line)
|
|
14773
14902
|
}
|
|
@@ -15022,7 +15151,7 @@ init_cjs_shims();
|
|
|
15022
15151
|
|
|
15023
15152
|
// src/extract/infra/docker-compose.ts
|
|
15024
15153
|
init_cjs_shims();
|
|
15025
|
-
var
|
|
15154
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
15026
15155
|
var import_types48 = require("@neat.is/types");
|
|
15027
15156
|
|
|
15028
15157
|
// src/extract/infra/shared.ts
|
|
@@ -15093,7 +15222,7 @@ function dependsOnList(value) {
|
|
|
15093
15222
|
}
|
|
15094
15223
|
function serviceNameToServiceNode(name, services) {
|
|
15095
15224
|
for (const s of services) {
|
|
15096
|
-
if (s.node.name === name ||
|
|
15225
|
+
if (s.node.name === name || import_node_path59.default.basename(s.dir) === name) return s.node.id;
|
|
15097
15226
|
}
|
|
15098
15227
|
return null;
|
|
15099
15228
|
}
|
|
@@ -15102,7 +15231,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
15102
15231
|
let edgesAdded = 0;
|
|
15103
15232
|
let composePath = null;
|
|
15104
15233
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
15105
|
-
const abs =
|
|
15234
|
+
const abs = import_node_path59.default.join(scanPath, name);
|
|
15106
15235
|
if (await exists(abs)) {
|
|
15107
15236
|
composePath = abs;
|
|
15108
15237
|
break;
|
|
@@ -15115,13 +15244,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
15115
15244
|
} catch (err) {
|
|
15116
15245
|
recordExtractionError(
|
|
15117
15246
|
"infra docker-compose",
|
|
15118
|
-
|
|
15247
|
+
import_node_path59.default.relative(scanPath, composePath),
|
|
15119
15248
|
err
|
|
15120
15249
|
);
|
|
15121
15250
|
return { nodesAdded, edgesAdded };
|
|
15122
15251
|
}
|
|
15123
15252
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
15124
|
-
const evidenceFile =
|
|
15253
|
+
const evidenceFile = import_node_path59.default.relative(scanPath, composePath).split(import_node_path59.default.sep).join("/");
|
|
15125
15254
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
15126
15255
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
15127
15256
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -15163,8 +15292,8 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
15163
15292
|
|
|
15164
15293
|
// src/extract/infra/dockerfile.ts
|
|
15165
15294
|
init_cjs_shims();
|
|
15166
|
-
var
|
|
15167
|
-
var
|
|
15295
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
15296
|
+
var import_node_fs26 = require("fs");
|
|
15168
15297
|
var import_types49 = require("@neat.is/types");
|
|
15169
15298
|
function readDockerfile(content) {
|
|
15170
15299
|
let image = null;
|
|
@@ -15194,15 +15323,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
15194
15323
|
let nodesAdded = 0;
|
|
15195
15324
|
let edgesAdded = 0;
|
|
15196
15325
|
for (const service of services) {
|
|
15197
|
-
const dockerfilePath =
|
|
15326
|
+
const dockerfilePath = import_node_path60.default.join(service.dir, "Dockerfile");
|
|
15198
15327
|
if (!await exists(dockerfilePath)) continue;
|
|
15199
15328
|
let content;
|
|
15200
15329
|
try {
|
|
15201
|
-
content = await
|
|
15330
|
+
content = await import_node_fs26.promises.readFile(dockerfilePath, "utf8");
|
|
15202
15331
|
} catch (err) {
|
|
15203
15332
|
recordExtractionError(
|
|
15204
15333
|
"infra dockerfile",
|
|
15205
|
-
|
|
15334
|
+
import_node_path60.default.relative(scanPath, dockerfilePath),
|
|
15206
15335
|
err
|
|
15207
15336
|
);
|
|
15208
15337
|
continue;
|
|
@@ -15214,8 +15343,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
15214
15343
|
graph.addNode(node.id, node);
|
|
15215
15344
|
nodesAdded++;
|
|
15216
15345
|
}
|
|
15217
|
-
const relDockerfile = toPosix(
|
|
15218
|
-
const evidenceFile = toPosix(
|
|
15346
|
+
const relDockerfile = toPosix(import_node_path60.default.relative(service.dir, dockerfilePath));
|
|
15347
|
+
const evidenceFile = toPosix(import_node_path60.default.relative(scanPath, dockerfilePath));
|
|
15219
15348
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
15220
15349
|
graph,
|
|
15221
15350
|
service.pkg.name,
|
|
@@ -15267,23 +15396,23 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
15267
15396
|
|
|
15268
15397
|
// src/extract/infra/terraform.ts
|
|
15269
15398
|
init_cjs_shims();
|
|
15270
|
-
var
|
|
15271
|
-
var
|
|
15399
|
+
var import_node_fs27 = require("fs");
|
|
15400
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
15272
15401
|
var import_types50 = require("@neat.is/types");
|
|
15273
15402
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
15274
15403
|
var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
|
|
15275
15404
|
async function walkTfFiles(start, depth = 0, max = 5) {
|
|
15276
15405
|
if (depth > max) return [];
|
|
15277
15406
|
const out = [];
|
|
15278
|
-
const entries = await
|
|
15407
|
+
const entries = await import_node_fs27.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
15279
15408
|
for (const entry2 of entries) {
|
|
15280
15409
|
if (entry2.isDirectory()) {
|
|
15281
15410
|
if (IGNORED_DIRS.has(entry2.name) || entry2.name === ".terraform") continue;
|
|
15282
|
-
const child =
|
|
15411
|
+
const child = import_node_path61.default.join(start, entry2.name);
|
|
15283
15412
|
if (await isPythonVenvDir(child)) continue;
|
|
15284
15413
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
15285
15414
|
} else if (entry2.isFile() && entry2.name.endsWith(".tf")) {
|
|
15286
|
-
out.push(
|
|
15415
|
+
out.push(import_node_path61.default.join(start, entry2.name));
|
|
15287
15416
|
}
|
|
15288
15417
|
}
|
|
15289
15418
|
return out;
|
|
@@ -15314,8 +15443,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
15314
15443
|
let edgesAdded = 0;
|
|
15315
15444
|
const files = await walkTfFiles(scanPath);
|
|
15316
15445
|
for (const file of files) {
|
|
15317
|
-
const content = await
|
|
15318
|
-
const evidenceFile = toPosix(
|
|
15446
|
+
const content = await import_node_fs27.promises.readFile(file, "utf8");
|
|
15447
|
+
const evidenceFile = toPosix(import_node_path61.default.relative(scanPath, file));
|
|
15319
15448
|
const resources = [];
|
|
15320
15449
|
const byKey = /* @__PURE__ */ new Map();
|
|
15321
15450
|
RESOURCE_RE.lastIndex = 0;
|
|
@@ -15372,8 +15501,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
15372
15501
|
|
|
15373
15502
|
// src/extract/infra/k8s.ts
|
|
15374
15503
|
init_cjs_shims();
|
|
15375
|
-
var
|
|
15376
|
-
var
|
|
15504
|
+
var import_node_fs28 = require("fs");
|
|
15505
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
15377
15506
|
var import_yaml3 = require("yaml");
|
|
15378
15507
|
var import_types51 = require("@neat.is/types");
|
|
15379
15508
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
@@ -15389,15 +15518,15 @@ var WORKLOAD_KINDS = /* @__PURE__ */ new Set(["Deployment", "StatefulSet", "Daem
|
|
|
15389
15518
|
async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
15390
15519
|
if (depth > max) return [];
|
|
15391
15520
|
const out = [];
|
|
15392
|
-
const entries = await
|
|
15521
|
+
const entries = await import_node_fs28.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
15393
15522
|
for (const entry2 of entries) {
|
|
15394
15523
|
if (entry2.isDirectory()) {
|
|
15395
15524
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
15396
|
-
const child =
|
|
15525
|
+
const child = import_node_path62.default.join(start, entry2.name);
|
|
15397
15526
|
if (await isPythonVenvDir(child)) continue;
|
|
15398
15527
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
15399
|
-
} else if (entry2.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
15400
|
-
out.push(
|
|
15528
|
+
} else if (entry2.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path62.default.extname(entry2.name))) {
|
|
15529
|
+
out.push(import_node_path62.default.join(start, entry2.name));
|
|
15401
15530
|
}
|
|
15402
15531
|
}
|
|
15403
15532
|
return out;
|
|
@@ -15407,14 +15536,14 @@ async function addK8sResources(graph, scanPath) {
|
|
|
15407
15536
|
let edgesAdded = 0;
|
|
15408
15537
|
const files = await walkYamlFiles2(scanPath);
|
|
15409
15538
|
for (const file of files) {
|
|
15410
|
-
const content = await
|
|
15539
|
+
const content = await import_node_fs28.promises.readFile(file, "utf8");
|
|
15411
15540
|
let docs;
|
|
15412
15541
|
try {
|
|
15413
15542
|
docs = (0, import_yaml3.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
15414
15543
|
} catch {
|
|
15415
15544
|
continue;
|
|
15416
15545
|
}
|
|
15417
|
-
const relFile = toPosix(
|
|
15546
|
+
const relFile = toPosix(import_node_path62.default.relative(scanPath, file));
|
|
15418
15547
|
for (const doc of docs) {
|
|
15419
15548
|
if (!doc?.kind || !doc.metadata?.name) continue;
|
|
15420
15549
|
const infraKind = K8S_KIND_TO_INFRA_KIND[doc.kind];
|
|
@@ -15463,16 +15592,16 @@ async function addK8sResources(graph, scanPath) {
|
|
|
15463
15592
|
|
|
15464
15593
|
// src/extract/infra/cloudflare.ts
|
|
15465
15594
|
init_cjs_shims();
|
|
15466
|
-
var
|
|
15467
|
-
var
|
|
15595
|
+
var import_node_fs29 = require("fs");
|
|
15596
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
15468
15597
|
var import_smol_toml3 = require("smol-toml");
|
|
15469
15598
|
var import_types52 = require("@neat.is/types");
|
|
15470
15599
|
var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
|
|
15471
15600
|
async function readWranglerConfig(dir) {
|
|
15472
15601
|
for (const filename of WRANGLER_FILENAMES) {
|
|
15473
|
-
const abs =
|
|
15602
|
+
const abs = import_node_path63.default.join(dir, filename);
|
|
15474
15603
|
if (!await exists(abs)) continue;
|
|
15475
|
-
const raw = await
|
|
15604
|
+
const raw = await import_node_fs29.promises.readFile(abs, "utf8");
|
|
15476
15605
|
const config = filename === "wrangler.toml" ? (0, import_smol_toml3.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
15477
15606
|
return { config, relFile: filename, raw };
|
|
15478
15607
|
}
|
|
@@ -15533,11 +15662,11 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
15533
15662
|
try {
|
|
15534
15663
|
read = await readWranglerConfig(service.dir);
|
|
15535
15664
|
} catch (err) {
|
|
15536
|
-
recordExtractionError("infra cloudflare",
|
|
15665
|
+
recordExtractionError("infra cloudflare", import_node_path63.default.relative(scanPath, service.dir), err);
|
|
15537
15666
|
continue;
|
|
15538
15667
|
}
|
|
15539
15668
|
if (!read || !read.config.name) continue;
|
|
15540
|
-
const evidenceFile = toPosix(
|
|
15669
|
+
const evidenceFile = toPosix(import_node_path63.default.relative(scanPath, import_node_path63.default.join(service.dir, read.relFile)));
|
|
15541
15670
|
discovered.push({ service, config: read.config, relFile: read.relFile, raw: read.raw, evidenceFile });
|
|
15542
15671
|
}
|
|
15543
15672
|
for (const worker of discovered) {
|
|
@@ -15549,7 +15678,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
15549
15678
|
}
|
|
15550
15679
|
let anchorId = service.node.id;
|
|
15551
15680
|
if (config.main) {
|
|
15552
|
-
const entryRelPath = toPosix(
|
|
15681
|
+
const entryRelPath = toPosix(import_node_path63.default.normalize(config.main));
|
|
15553
15682
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
15554
15683
|
graph,
|
|
15555
15684
|
service.pkg.name,
|
|
@@ -15696,24 +15825,24 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
15696
15825
|
|
|
15697
15826
|
// src/extract/infra/vercel.ts
|
|
15698
15827
|
init_cjs_shims();
|
|
15699
|
-
var
|
|
15700
|
-
var
|
|
15828
|
+
var import_node_fs30 = require("fs");
|
|
15829
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
15701
15830
|
var import_types53 = require("@neat.is/types");
|
|
15702
15831
|
var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
|
|
15703
15832
|
async function readVercelConfig(dir) {
|
|
15704
15833
|
for (const filename of VERCEL_CONFIG_FILENAMES) {
|
|
15705
|
-
const abs =
|
|
15834
|
+
const abs = import_node_path64.default.join(dir, filename);
|
|
15706
15835
|
if (!await exists(abs)) continue;
|
|
15707
|
-
const raw = await
|
|
15836
|
+
const raw = await import_node_fs30.promises.readFile(abs, "utf8");
|
|
15708
15837
|
const config = JSON.parse(maskCommentsInSource(raw));
|
|
15709
15838
|
return { config, relFile: filename, raw };
|
|
15710
15839
|
}
|
|
15711
15840
|
return null;
|
|
15712
15841
|
}
|
|
15713
15842
|
async function readLinkedProjectName(dir) {
|
|
15714
|
-
const abs =
|
|
15843
|
+
const abs = import_node_path64.default.join(dir, ".vercel", "project.json");
|
|
15715
15844
|
if (!await exists(abs)) return void 0;
|
|
15716
|
-
const parsed = JSON.parse(await
|
|
15845
|
+
const parsed = JSON.parse(await import_node_fs30.promises.readFile(abs, "utf8"));
|
|
15717
15846
|
return typeof parsed.projectName === "string" ? parsed.projectName : void 0;
|
|
15718
15847
|
}
|
|
15719
15848
|
function routeSource(route) {
|
|
@@ -15729,7 +15858,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
15729
15858
|
read = await readVercelConfig(service.dir);
|
|
15730
15859
|
projectName = await readLinkedProjectName(service.dir);
|
|
15731
15860
|
} catch (err) {
|
|
15732
|
-
recordExtractionError("infra vercel",
|
|
15861
|
+
recordExtractionError("infra vercel", import_node_path64.default.relative(scanPath, service.dir), err);
|
|
15733
15862
|
continue;
|
|
15734
15863
|
}
|
|
15735
15864
|
if (!read && !projectName) continue;
|
|
@@ -15745,7 +15874,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
15745
15874
|
const anchorId = service.node.id;
|
|
15746
15875
|
if (!read) continue;
|
|
15747
15876
|
const { config, relFile, raw } = read;
|
|
15748
|
-
const evidenceFile = toPosix(
|
|
15877
|
+
const evidenceFile = toPosix(import_node_path64.default.relative(scanPath, import_node_path64.default.join(service.dir, relFile)));
|
|
15749
15878
|
const add = (edgeType, kind, name) => {
|
|
15750
15879
|
if (!name) return;
|
|
15751
15880
|
const result = emitPlatformResourceEdge(
|
|
@@ -15774,16 +15903,16 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
15774
15903
|
|
|
15775
15904
|
// src/extract/infra/railway.ts
|
|
15776
15905
|
init_cjs_shims();
|
|
15777
|
-
var
|
|
15778
|
-
var
|
|
15906
|
+
var import_node_fs31 = require("fs");
|
|
15907
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
15779
15908
|
var import_smol_toml4 = require("smol-toml");
|
|
15780
15909
|
var import_types54 = require("@neat.is/types");
|
|
15781
15910
|
var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
|
|
15782
15911
|
async function readRailwayConfig(dir) {
|
|
15783
15912
|
for (const filename of RAILWAY_FILENAMES) {
|
|
15784
|
-
const abs =
|
|
15913
|
+
const abs = import_node_path65.default.join(dir, filename);
|
|
15785
15914
|
if (!await exists(abs)) continue;
|
|
15786
|
-
const raw = await
|
|
15915
|
+
const raw = await import_node_fs31.promises.readFile(abs, "utf8");
|
|
15787
15916
|
const config = filename === "railway.toml" ? (0, import_smol_toml4.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
15788
15917
|
return { config, relFile: filename, raw };
|
|
15789
15918
|
}
|
|
@@ -15797,7 +15926,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
15797
15926
|
try {
|
|
15798
15927
|
read = await readRailwayConfig(service.dir);
|
|
15799
15928
|
} catch (err) {
|
|
15800
|
-
recordExtractionError("infra railway",
|
|
15929
|
+
recordExtractionError("infra railway", import_node_path65.default.relative(scanPath, service.dir), err);
|
|
15801
15930
|
continue;
|
|
15802
15931
|
}
|
|
15803
15932
|
if (!read) continue;
|
|
@@ -15807,7 +15936,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
15807
15936
|
}
|
|
15808
15937
|
const anchorId = service.node.id;
|
|
15809
15938
|
const { config, relFile, raw } = read;
|
|
15810
|
-
const evidenceFile = toPosix(
|
|
15939
|
+
const evidenceFile = toPosix(import_node_path65.default.relative(scanPath, import_node_path65.default.join(service.dir, relFile)));
|
|
15811
15940
|
const add = (edgeType, kind, name) => {
|
|
15812
15941
|
if (!name) return;
|
|
15813
15942
|
const result = emitPlatformResourceEdge(
|
|
@@ -15832,15 +15961,15 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
15832
15961
|
|
|
15833
15962
|
// src/extract/infra/supabase.ts
|
|
15834
15963
|
init_cjs_shims();
|
|
15835
|
-
var
|
|
15836
|
-
var
|
|
15964
|
+
var import_node_fs32 = require("fs");
|
|
15965
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
15837
15966
|
var import_smol_toml5 = require("smol-toml");
|
|
15838
15967
|
var import_types55 = require("@neat.is/types");
|
|
15839
15968
|
async function readSupabaseConfig(dir) {
|
|
15840
|
-
const relFile =
|
|
15841
|
-
const abs =
|
|
15969
|
+
const relFile = import_node_path66.default.join("supabase", "config.toml");
|
|
15970
|
+
const abs = import_node_path66.default.join(dir, relFile);
|
|
15842
15971
|
if (!await exists(abs)) return null;
|
|
15843
|
-
const raw = await
|
|
15972
|
+
const raw = await import_node_fs32.promises.readFile(abs, "utf8");
|
|
15844
15973
|
const config = (0, import_smol_toml5.parse)(raw);
|
|
15845
15974
|
return { config, relFile, raw };
|
|
15846
15975
|
}
|
|
@@ -15852,7 +15981,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
15852
15981
|
try {
|
|
15853
15982
|
read = await readSupabaseConfig(service.dir);
|
|
15854
15983
|
} catch (err) {
|
|
15855
|
-
recordExtractionError("infra supabase",
|
|
15984
|
+
recordExtractionError("infra supabase", import_node_path66.default.relative(scanPath, service.dir), err);
|
|
15856
15985
|
continue;
|
|
15857
15986
|
}
|
|
15858
15987
|
if (!read) continue;
|
|
@@ -15867,7 +15996,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
15867
15996
|
});
|
|
15868
15997
|
}
|
|
15869
15998
|
const anchorId = service.node.id;
|
|
15870
|
-
const evidenceFile = toPosix(
|
|
15999
|
+
const evidenceFile = toPosix(import_node_path66.default.relative(scanPath, import_node_path66.default.join(service.dir, relFile)));
|
|
15871
16000
|
const add = (edgeType, kind, name) => {
|
|
15872
16001
|
if (!name) return;
|
|
15873
16002
|
const result = emitPlatformResourceEdge(
|
|
@@ -15909,7 +16038,7 @@ async function addInfra(graph, scanPath, services) {
|
|
|
15909
16038
|
|
|
15910
16039
|
// src/extract/zod-shapes.ts
|
|
15911
16040
|
init_cjs_shims();
|
|
15912
|
-
var
|
|
16041
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
15913
16042
|
var import_tree_sitter18 = __toESM(require("tree-sitter"), 1);
|
|
15914
16043
|
var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
|
|
15915
16044
|
var import_types56 = require("@neat.is/types");
|
|
@@ -16004,7 +16133,7 @@ function topLevelSchemas(root) {
|
|
|
16004
16133
|
}
|
|
16005
16134
|
function zodShapesFromFile(file, serviceDir) {
|
|
16006
16135
|
if (!ZOD_IMPORT_RE.test(file.content)) return [];
|
|
16007
|
-
const tree = parseSource3(parserForExt4(
|
|
16136
|
+
const tree = parseSource3(parserForExt4(import_node_path67.default.extname(file.path)), file.content);
|
|
16008
16137
|
const out = [];
|
|
16009
16138
|
const seen = /* @__PURE__ */ new Set();
|
|
16010
16139
|
for (const { name, call } of topLevelSchemas(tree.rootNode)) {
|
|
@@ -16022,7 +16151,7 @@ function zodShapesFromFile(file, serviceDir) {
|
|
|
16022
16151
|
name,
|
|
16023
16152
|
fields,
|
|
16024
16153
|
evidence: {
|
|
16025
|
-
file:
|
|
16154
|
+
file: import_node_path67.default.relative(serviceDir, file.path),
|
|
16026
16155
|
line,
|
|
16027
16156
|
snippet: snippet(file.content, line)
|
|
16028
16157
|
}
|
|
@@ -16290,12 +16419,12 @@ async function addFirestoreRules(graph, services) {
|
|
|
16290
16419
|
}
|
|
16291
16420
|
|
|
16292
16421
|
// src/extract/index.ts
|
|
16293
|
-
var
|
|
16422
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
16294
16423
|
|
|
16295
16424
|
// src/extract/retire.ts
|
|
16296
16425
|
init_cjs_shims();
|
|
16297
|
-
var
|
|
16298
|
-
var
|
|
16426
|
+
var import_node_fs33 = require("fs");
|
|
16427
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
16299
16428
|
var import_types58 = require("@neat.is/types");
|
|
16300
16429
|
function dropOrphanedFileNodes(graph) {
|
|
16301
16430
|
const orphans = [];
|
|
@@ -16316,11 +16445,11 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
16316
16445
|
if (edge.provenance !== import_types58.Provenance.EXTRACTED) return;
|
|
16317
16446
|
const evidenceFile = edge.evidence?.file;
|
|
16318
16447
|
if (!evidenceFile) return;
|
|
16319
|
-
if (
|
|
16320
|
-
if (!(0,
|
|
16448
|
+
if (import_node_path68.default.isAbsolute(evidenceFile)) {
|
|
16449
|
+
if (!(0, import_node_fs33.existsSync)(evidenceFile)) toDrop.push(id);
|
|
16321
16450
|
return;
|
|
16322
16451
|
}
|
|
16323
|
-
const found = bases.some((base) => (0,
|
|
16452
|
+
const found = bases.some((base) => (0, import_node_fs33.existsSync)(import_node_path68.default.join(base, evidenceFile)));
|
|
16324
16453
|
if (!found) toDrop.push(id);
|
|
16325
16454
|
});
|
|
16326
16455
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -16332,6 +16461,7 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
16332
16461
|
async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
16333
16462
|
await ensureCompatLoaded();
|
|
16334
16463
|
drainExtractionErrors();
|
|
16464
|
+
drainSkippedFiles();
|
|
16335
16465
|
const services = await discoverServices(scanPath);
|
|
16336
16466
|
const phase1Nodes = addServiceNodes(graph, services);
|
|
16337
16467
|
await addServiceAliases(graph, scanPath, services);
|
|
@@ -16376,8 +16506,9 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
16376
16506
|
}
|
|
16377
16507
|
}
|
|
16378
16508
|
const droppedEntries = drainDroppedExtracted();
|
|
16509
|
+
const skippedEntries = drainSkippedFiles();
|
|
16379
16510
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
16380
|
-
const rejectedPath =
|
|
16511
|
+
const rejectedPath = import_node_path69.default.join(import_node_path69.default.dirname(opts.errorsPath), "rejected.ndjson");
|
|
16381
16512
|
try {
|
|
16382
16513
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
16383
16514
|
} catch (err) {
|
|
@@ -16394,7 +16525,9 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
16394
16525
|
errorEntries,
|
|
16395
16526
|
ghostsRetired,
|
|
16396
16527
|
extractedDropped: droppedEntries.length,
|
|
16397
|
-
droppedEntries
|
|
16528
|
+
droppedEntries,
|
|
16529
|
+
skippedFiles: skippedEntries.length,
|
|
16530
|
+
skippedEntries
|
|
16398
16531
|
};
|
|
16399
16532
|
emitNeatEvent({
|
|
16400
16533
|
type: "extraction-complete",
|
|
@@ -16411,8 +16544,8 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
16411
16544
|
|
|
16412
16545
|
// src/persist.ts
|
|
16413
16546
|
init_cjs_shims();
|
|
16414
|
-
var
|
|
16415
|
-
var
|
|
16547
|
+
var import_node_fs34 = require("fs");
|
|
16548
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
16416
16549
|
var import_types59 = require("@neat.is/types");
|
|
16417
16550
|
var SCHEMA_VERSION = 7;
|
|
16418
16551
|
function migrateV1ToV2(payload) {
|
|
@@ -16467,7 +16600,43 @@ function migrateV2ToV3(payload) {
|
|
|
16467
16600
|
return { ...payload, schemaVersion: 3 };
|
|
16468
16601
|
}
|
|
16469
16602
|
async function ensureDir(filePath) {
|
|
16470
|
-
await
|
|
16603
|
+
await import_node_fs34.promises.mkdir(import_node_path70.default.dirname(filePath), { recursive: true });
|
|
16604
|
+
}
|
|
16605
|
+
var WRITE_FLUSH_CHARS = 4 * 1024 * 1024;
|
|
16606
|
+
function jsonOrUndefined(value) {
|
|
16607
|
+
return JSON.stringify(value);
|
|
16608
|
+
}
|
|
16609
|
+
function* serializeArray(items) {
|
|
16610
|
+
yield "[";
|
|
16611
|
+
for (let i = 0; i < items.length; i++) {
|
|
16612
|
+
if (i > 0) yield ",";
|
|
16613
|
+
yield jsonOrUndefined(items[i]) ?? "null";
|
|
16614
|
+
}
|
|
16615
|
+
yield "]";
|
|
16616
|
+
}
|
|
16617
|
+
function isPlainObject(value) {
|
|
16618
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
16619
|
+
const proto = Object.getPrototypeOf(value);
|
|
16620
|
+
return proto === Object.prototype || proto === null;
|
|
16621
|
+
}
|
|
16622
|
+
function* serializeObject(obj) {
|
|
16623
|
+
yield "{";
|
|
16624
|
+
let first = true;
|
|
16625
|
+
for (const key of Object.keys(obj)) {
|
|
16626
|
+
const value = obj[key];
|
|
16627
|
+
const descend = Array.isArray(value) || isPlainObject(value);
|
|
16628
|
+
if (!descend && jsonOrUndefined(value) === void 0) continue;
|
|
16629
|
+
if (!first) yield ",";
|
|
16630
|
+
first = false;
|
|
16631
|
+
yield `${JSON.stringify(key)}:`;
|
|
16632
|
+
if (Array.isArray(value)) yield* serializeArray(value);
|
|
16633
|
+
else if (isPlainObject(value)) yield* serializeObject(value);
|
|
16634
|
+
else yield jsonOrUndefined(value);
|
|
16635
|
+
}
|
|
16636
|
+
yield "}";
|
|
16637
|
+
}
|
|
16638
|
+
function* serializeGraphChunks(payload) {
|
|
16639
|
+
yield* serializeObject(payload);
|
|
16471
16640
|
}
|
|
16472
16641
|
async function saveGraphToDisk(graph, outPath) {
|
|
16473
16642
|
await ensureDir(outPath);
|
|
@@ -16477,13 +16646,26 @@ async function saveGraphToDisk(graph, outPath) {
|
|
|
16477
16646
|
graph: graph.export()
|
|
16478
16647
|
};
|
|
16479
16648
|
const tmp = `${outPath}.tmp`;
|
|
16480
|
-
await
|
|
16481
|
-
|
|
16649
|
+
const handle = await import_node_fs34.promises.open(tmp, "w");
|
|
16650
|
+
try {
|
|
16651
|
+
let buffered = "";
|
|
16652
|
+
for (const chunk of serializeGraphChunks(payload)) {
|
|
16653
|
+
buffered += chunk;
|
|
16654
|
+
if (buffered.length >= WRITE_FLUSH_CHARS) {
|
|
16655
|
+
await handle.write(buffered, null, "utf8");
|
|
16656
|
+
buffered = "";
|
|
16657
|
+
}
|
|
16658
|
+
}
|
|
16659
|
+
if (buffered.length > 0) await handle.write(buffered, null, "utf8");
|
|
16660
|
+
} finally {
|
|
16661
|
+
await handle.close();
|
|
16662
|
+
}
|
|
16663
|
+
await import_node_fs34.promises.rename(tmp, outPath);
|
|
16482
16664
|
}
|
|
16483
16665
|
async function loadGraphFromDisk(graph, outPath) {
|
|
16484
16666
|
let raw;
|
|
16485
16667
|
try {
|
|
16486
|
-
raw = await
|
|
16668
|
+
raw = await import_node_fs34.promises.readFile(outPath, "utf8");
|
|
16487
16669
|
} catch (err) {
|
|
16488
16670
|
if (err.code === "ENOENT") return;
|
|
16489
16671
|
throw err;
|
|
@@ -16557,23 +16739,23 @@ function startPersistLoop(graph, outPath, opts = {}) {
|
|
|
16557
16739
|
|
|
16558
16740
|
// src/projects.ts
|
|
16559
16741
|
init_cjs_shims();
|
|
16560
|
-
var
|
|
16742
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
16561
16743
|
function pathsForProject(project, baseDir) {
|
|
16562
16744
|
if (project === DEFAULT_PROJECT) {
|
|
16563
16745
|
return {
|
|
16564
|
-
snapshotPath:
|
|
16565
|
-
errorsPath:
|
|
16566
|
-
staleEventsPath:
|
|
16567
|
-
embeddingsCachePath:
|
|
16568
|
-
policyViolationsPath:
|
|
16746
|
+
snapshotPath: import_node_path71.default.join(baseDir, "graph.json"),
|
|
16747
|
+
errorsPath: import_node_path71.default.join(baseDir, "errors.ndjson"),
|
|
16748
|
+
staleEventsPath: import_node_path71.default.join(baseDir, "stale-events.ndjson"),
|
|
16749
|
+
embeddingsCachePath: import_node_path71.default.join(baseDir, "embeddings.json"),
|
|
16750
|
+
policyViolationsPath: import_node_path71.default.join(baseDir, "policy-violations.ndjson")
|
|
16569
16751
|
};
|
|
16570
16752
|
}
|
|
16571
16753
|
return {
|
|
16572
|
-
snapshotPath:
|
|
16573
|
-
errorsPath:
|
|
16574
|
-
staleEventsPath:
|
|
16575
|
-
embeddingsCachePath:
|
|
16576
|
-
policyViolationsPath:
|
|
16754
|
+
snapshotPath: import_node_path71.default.join(baseDir, `${project}.json`),
|
|
16755
|
+
errorsPath: import_node_path71.default.join(baseDir, `errors.${project}.ndjson`),
|
|
16756
|
+
staleEventsPath: import_node_path71.default.join(baseDir, `stale-events.${project}.ndjson`),
|
|
16757
|
+
embeddingsCachePath: import_node_path71.default.join(baseDir, `embeddings.${project}.json`),
|
|
16758
|
+
policyViolationsPath: import_node_path71.default.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
16577
16759
|
};
|
|
16578
16760
|
}
|
|
16579
16761
|
var Projects = class {
|
|
@@ -16615,15 +16797,15 @@ var import_types101 = require("@neat.is/types");
|
|
|
16615
16797
|
|
|
16616
16798
|
// src/extend/index.ts
|
|
16617
16799
|
init_cjs_shims();
|
|
16618
|
-
var
|
|
16619
|
-
var
|
|
16800
|
+
var import_node_fs36 = require("fs");
|
|
16801
|
+
var import_node_path73 = __toESM(require("path"), 1);
|
|
16620
16802
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
16621
16803
|
var import_instrumentation_registry = require("@neat.is/instrumentation-registry");
|
|
16622
16804
|
|
|
16623
16805
|
// src/installers/package-manager.ts
|
|
16624
16806
|
init_cjs_shims();
|
|
16625
|
-
var
|
|
16626
|
-
var
|
|
16807
|
+
var import_node_fs35 = require("fs");
|
|
16808
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
16627
16809
|
var import_node_child_process = require("child_process");
|
|
16628
16810
|
var LOCKFILE_PRIORITY = [
|
|
16629
16811
|
{ lockfile: "bun.lockb", pm: "bun", args: ["install", "--no-summary"] },
|
|
@@ -16638,29 +16820,29 @@ var LOCKFILE_PRIORITY = [
|
|
|
16638
16820
|
var NPM_FALLBACK_ARGS = ["install", "--no-audit", "--no-fund", "--prefer-offline"];
|
|
16639
16821
|
async function exists2(p) {
|
|
16640
16822
|
try {
|
|
16641
|
-
await
|
|
16823
|
+
await import_node_fs35.promises.access(p);
|
|
16642
16824
|
return true;
|
|
16643
16825
|
} catch {
|
|
16644
16826
|
return false;
|
|
16645
16827
|
}
|
|
16646
16828
|
}
|
|
16647
16829
|
async function detectPackageManager(serviceDir) {
|
|
16648
|
-
let dir =
|
|
16830
|
+
let dir = import_node_path72.default.resolve(serviceDir);
|
|
16649
16831
|
const stops = /* @__PURE__ */ new Set();
|
|
16650
16832
|
for (let i = 0; i < 64; i++) {
|
|
16651
16833
|
if (stops.has(dir)) break;
|
|
16652
16834
|
stops.add(dir);
|
|
16653
16835
|
for (const candidate of LOCKFILE_PRIORITY) {
|
|
16654
|
-
const lockPath =
|
|
16836
|
+
const lockPath = import_node_path72.default.join(dir, candidate.lockfile);
|
|
16655
16837
|
if (await exists2(lockPath)) {
|
|
16656
16838
|
return { pm: candidate.pm, cwd: dir, args: [...candidate.args] };
|
|
16657
16839
|
}
|
|
16658
16840
|
}
|
|
16659
|
-
const parent =
|
|
16841
|
+
const parent = import_node_path72.default.dirname(dir);
|
|
16660
16842
|
if (parent === dir) break;
|
|
16661
16843
|
dir = parent;
|
|
16662
16844
|
}
|
|
16663
|
-
return { pm: "npm", cwd:
|
|
16845
|
+
return { pm: "npm", cwd: import_node_path72.default.resolve(serviceDir), args: [...NPM_FALLBACK_ARGS] };
|
|
16664
16846
|
}
|
|
16665
16847
|
async function runPackageManagerInstall(cmd) {
|
|
16666
16848
|
return new Promise((resolve) => {
|
|
@@ -16702,15 +16884,15 @@ ${err.message}`
|
|
|
16702
16884
|
// src/extend/index.ts
|
|
16703
16885
|
async function fileExists2(p) {
|
|
16704
16886
|
try {
|
|
16705
|
-
await
|
|
16887
|
+
await import_node_fs36.promises.access(p);
|
|
16706
16888
|
return true;
|
|
16707
16889
|
} catch {
|
|
16708
16890
|
return false;
|
|
16709
16891
|
}
|
|
16710
16892
|
}
|
|
16711
16893
|
async function readPackageJson(scanPath) {
|
|
16712
|
-
const pkgPath =
|
|
16713
|
-
const raw = await
|
|
16894
|
+
const pkgPath = import_node_path73.default.join(scanPath, "package.json");
|
|
16895
|
+
const raw = await import_node_fs36.promises.readFile(pkgPath, "utf8");
|
|
16714
16896
|
return JSON.parse(raw);
|
|
16715
16897
|
}
|
|
16716
16898
|
var HOOK_WALK_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -16724,15 +16906,15 @@ var HOOK_WALK_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
16724
16906
|
async function findHookFiles(scanPath) {
|
|
16725
16907
|
const found = [];
|
|
16726
16908
|
const walk11 = async (dir) => {
|
|
16727
|
-
const entries = await
|
|
16909
|
+
const entries = await import_node_fs36.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
16728
16910
|
for (const entry2 of entries) {
|
|
16729
16911
|
if (entry2.isDirectory()) {
|
|
16730
16912
|
if (entry2.name.startsWith(".") || HOOK_WALK_SKIP_DIRS.has(entry2.name)) continue;
|
|
16731
|
-
await walk11(
|
|
16913
|
+
await walk11(import_node_path73.default.join(dir, entry2.name));
|
|
16732
16914
|
} else if (entry2.isFile()) {
|
|
16733
16915
|
if ((entry2.name.startsWith("instrumentation") || entry2.name.startsWith("otel-init")) && /\.(ts|js|cjs|mjs)$/.test(entry2.name)) {
|
|
16734
|
-
const rel =
|
|
16735
|
-
found.push(rel.split(
|
|
16916
|
+
const rel = import_node_path73.default.relative(scanPath, import_node_path73.default.join(dir, entry2.name));
|
|
16917
|
+
found.push(rel.split(import_node_path73.default.sep).join("/"));
|
|
16736
16918
|
}
|
|
16737
16919
|
}
|
|
16738
16920
|
}
|
|
@@ -16743,7 +16925,7 @@ async function findHookFiles(scanPath) {
|
|
|
16743
16925
|
async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
|
|
16744
16926
|
let fallback = null;
|
|
16745
16927
|
for (const file of hookFiles) {
|
|
16746
|
-
const content = await
|
|
16928
|
+
const content = await import_node_fs36.promises.readFile(import_node_path73.default.join(scanPath, file), "utf8");
|
|
16747
16929
|
const patched = splicedContent(content, snippet2);
|
|
16748
16930
|
if (patched !== null) return { file, content, patched };
|
|
16749
16931
|
if (fallback === null) fallback = { file, content };
|
|
@@ -16751,12 +16933,12 @@ async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
|
|
|
16751
16933
|
return { file: fallback.file, content: fallback.content, patched: null };
|
|
16752
16934
|
}
|
|
16753
16935
|
function extendLogPath() {
|
|
16754
|
-
return process.env.NEAT_EXTEND_LOG ??
|
|
16936
|
+
return process.env.NEAT_EXTEND_LOG ?? import_node_path73.default.join(import_node_os2.default.homedir(), ".neat", "extend-log.ndjson");
|
|
16755
16937
|
}
|
|
16756
16938
|
async function appendExtendLog(entry2) {
|
|
16757
16939
|
const logPath = extendLogPath();
|
|
16758
|
-
await
|
|
16759
|
-
await
|
|
16940
|
+
await import_node_fs36.promises.mkdir(import_node_path73.default.dirname(logPath), { recursive: true });
|
|
16941
|
+
await import_node_fs36.promises.appendFile(logPath, JSON.stringify(entry2) + "\n", "utf8");
|
|
16760
16942
|
}
|
|
16761
16943
|
function splicedContent(fileContent, snippet2) {
|
|
16762
16944
|
if (fileContent.includes("__INSTRUMENTATION_BLOCK__")) {
|
|
@@ -16814,7 +16996,7 @@ function lookupInstrumentation(library, installedVersion) {
|
|
|
16814
16996
|
}
|
|
16815
16997
|
async function describeProjectInstrumentation(ctx) {
|
|
16816
16998
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
16817
|
-
const envNeat = await fileExists2(
|
|
16999
|
+
const envNeat = await fileExists2(import_node_path73.default.join(ctx.scanPath, ".env.neat"));
|
|
16818
17000
|
const registryInstrPackages = new Set(
|
|
16819
17001
|
(0, import_instrumentation_registry.list)().map((e) => e.instrumentation_package).filter((p) => !!p)
|
|
16820
17002
|
);
|
|
@@ -16836,7 +17018,7 @@ async function applyExtension(ctx, args, options) {
|
|
|
16836
17018
|
);
|
|
16837
17019
|
}
|
|
16838
17020
|
for (const file of hookFiles) {
|
|
16839
|
-
const content = await
|
|
17021
|
+
const content = await import_node_fs36.promises.readFile(import_node_path73.default.join(ctx.scanPath, file), "utf8");
|
|
16840
17022
|
if (content.includes(args.registration_snippet)) {
|
|
16841
17023
|
return { library: args.library, filesTouched: [], depsAdded: [], installOutput: "", alreadyApplied: true };
|
|
16842
17024
|
}
|
|
@@ -16848,18 +17030,18 @@ async function applyExtension(ctx, args, options) {
|
|
|
16848
17030
|
);
|
|
16849
17031
|
}
|
|
16850
17032
|
const primaryFile = primary.file;
|
|
16851
|
-
const primaryPath =
|
|
17033
|
+
const primaryPath = import_node_path73.default.join(ctx.scanPath, primaryFile);
|
|
16852
17034
|
const filesTouched = [];
|
|
16853
17035
|
const depsAdded = [];
|
|
16854
|
-
const pkgPath =
|
|
17036
|
+
const pkgPath = import_node_path73.default.join(ctx.scanPath, "package.json");
|
|
16855
17037
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
16856
17038
|
if (!(pkg.dependencies ?? {})[args.instrumentation_package]) {
|
|
16857
17039
|
pkg.dependencies = { ...pkg.dependencies ?? {}, [args.instrumentation_package]: args.version };
|
|
16858
|
-
await
|
|
17040
|
+
await import_node_fs36.promises.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
16859
17041
|
filesTouched.push("package.json");
|
|
16860
17042
|
depsAdded.push(`${args.instrumentation_package}@${args.version}`);
|
|
16861
17043
|
}
|
|
16862
|
-
await
|
|
17044
|
+
await import_node_fs36.promises.writeFile(primaryPath, primary.patched, "utf8");
|
|
16863
17045
|
filesTouched.push(primaryFile);
|
|
16864
17046
|
const cmd = await detectPackageManager(ctx.scanPath);
|
|
16865
17047
|
const installer = options?.runInstall ?? runPackageManagerInstall;
|
|
@@ -16890,7 +17072,7 @@ async function dryRunExtension(ctx, args) {
|
|
|
16890
17072
|
};
|
|
16891
17073
|
}
|
|
16892
17074
|
for (const file of hookFiles) {
|
|
16893
|
-
const content = await
|
|
17075
|
+
const content = await import_node_fs36.promises.readFile(import_node_path73.default.join(ctx.scanPath, file), "utf8");
|
|
16894
17076
|
if (content.includes(args.registration_snippet)) {
|
|
16895
17077
|
return {
|
|
16896
17078
|
library: args.library,
|
|
@@ -16925,28 +17107,28 @@ async function rollbackExtension(ctx, args) {
|
|
|
16925
17107
|
if (!await fileExists2(logPath)) {
|
|
16926
17108
|
return { undone: false, message: "no apply found for library" };
|
|
16927
17109
|
}
|
|
16928
|
-
const raw = await
|
|
17110
|
+
const raw = await import_node_fs36.promises.readFile(logPath, "utf8");
|
|
16929
17111
|
const entries = raw.trim().split("\n").filter(Boolean).map((line) => JSON.parse(line));
|
|
16930
17112
|
const match = [...entries].reverse().find((e) => e.project === ctx.project && e.library === args.library);
|
|
16931
17113
|
if (!match) {
|
|
16932
17114
|
return { undone: false, message: "no apply found for library" };
|
|
16933
17115
|
}
|
|
16934
|
-
const pkgPath =
|
|
17116
|
+
const pkgPath = import_node_path73.default.join(ctx.scanPath, "package.json");
|
|
16935
17117
|
if (await fileExists2(pkgPath)) {
|
|
16936
17118
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
16937
17119
|
if (pkg.dependencies?.[match.instrumentation_package]) {
|
|
16938
17120
|
const { [match.instrumentation_package]: _removed, ...rest } = pkg.dependencies;
|
|
16939
17121
|
pkg.dependencies = rest;
|
|
16940
|
-
await
|
|
17122
|
+
await import_node_fs36.promises.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
16941
17123
|
}
|
|
16942
17124
|
}
|
|
16943
17125
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
16944
17126
|
for (const file of hookFiles) {
|
|
16945
|
-
const filePath =
|
|
16946
|
-
const content = await
|
|
17127
|
+
const filePath = import_node_path73.default.join(ctx.scanPath, file);
|
|
17128
|
+
const content = await import_node_fs36.promises.readFile(filePath, "utf8");
|
|
16947
17129
|
if (content.includes(match.registration_snippet)) {
|
|
16948
17130
|
const filtered = content.split("\n").filter((line) => !line.includes(match.registration_snippet)).join("\n");
|
|
16949
|
-
await
|
|
17131
|
+
await import_node_fs36.promises.writeFile(filePath, filtered, "utf8");
|
|
16950
17132
|
break;
|
|
16951
17133
|
}
|
|
16952
17134
|
}
|
|
@@ -18583,7 +18765,7 @@ async function askGraph(graph, question, opts = {}) {
|
|
|
18583
18765
|
|
|
18584
18766
|
// src/diff.ts
|
|
18585
18767
|
init_cjs_shims();
|
|
18586
|
-
var
|
|
18768
|
+
var import_node_fs37 = require("fs");
|
|
18587
18769
|
async function loadSnapshotForDiff(target) {
|
|
18588
18770
|
if (/^https?:\/\//i.test(target)) {
|
|
18589
18771
|
const res = await fetch(target);
|
|
@@ -18592,7 +18774,7 @@ async function loadSnapshotForDiff(target) {
|
|
|
18592
18774
|
}
|
|
18593
18775
|
return await res.json();
|
|
18594
18776
|
}
|
|
18595
|
-
const raw = await
|
|
18777
|
+
const raw = await import_node_fs37.promises.readFile(target, "utf8");
|
|
18596
18778
|
return JSON.parse(raw);
|
|
18597
18779
|
}
|
|
18598
18780
|
function indexEntries(entries) {
|
|
@@ -18660,28 +18842,28 @@ function canonicalJson(value) {
|
|
|
18660
18842
|
|
|
18661
18843
|
// src/registry.ts
|
|
18662
18844
|
init_cjs_shims();
|
|
18663
|
-
var
|
|
18845
|
+
var import_node_fs38 = require("fs");
|
|
18664
18846
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
18665
|
-
var
|
|
18847
|
+
var import_node_path74 = __toESM(require("path"), 1);
|
|
18666
18848
|
var import_types63 = require("@neat.is/types");
|
|
18667
18849
|
var LOCK_TIMEOUT_MS = 5e3;
|
|
18668
18850
|
var LOCK_RETRY_MS = 50;
|
|
18669
18851
|
function neatHome() {
|
|
18670
18852
|
const override = process.env.NEAT_HOME;
|
|
18671
|
-
if (override && override.length > 0) return
|
|
18672
|
-
return
|
|
18853
|
+
if (override && override.length > 0) return import_node_path74.default.resolve(override);
|
|
18854
|
+
return import_node_path74.default.join(import_node_os3.default.homedir(), ".neat");
|
|
18673
18855
|
}
|
|
18674
18856
|
function registryPath() {
|
|
18675
|
-
return
|
|
18857
|
+
return import_node_path74.default.join(neatHome(), "projects.json");
|
|
18676
18858
|
}
|
|
18677
18859
|
function registryLockPath() {
|
|
18678
|
-
return
|
|
18860
|
+
return import_node_path74.default.join(neatHome(), "projects.json.lock");
|
|
18679
18861
|
}
|
|
18680
18862
|
function daemonPidPath() {
|
|
18681
|
-
return
|
|
18863
|
+
return import_node_path74.default.join(neatHome(), "neatd.pid");
|
|
18682
18864
|
}
|
|
18683
18865
|
function daemonsDir() {
|
|
18684
|
-
return
|
|
18866
|
+
return import_node_path74.default.join(neatHome(), "daemons");
|
|
18685
18867
|
}
|
|
18686
18868
|
function isFiniteInt(v) {
|
|
18687
18869
|
return typeof v === "number" && Number.isFinite(v);
|
|
@@ -18714,7 +18896,7 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
18714
18896
|
const dir = daemonsDir();
|
|
18715
18897
|
let names;
|
|
18716
18898
|
try {
|
|
18717
|
-
names = await
|
|
18899
|
+
names = await import_node_fs38.promises.readdir(dir);
|
|
18718
18900
|
} catch (err) {
|
|
18719
18901
|
if (err.code === "ENOENT") return [];
|
|
18720
18902
|
throw err;
|
|
@@ -18722,10 +18904,10 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
18722
18904
|
const out = [];
|
|
18723
18905
|
for (const name of names) {
|
|
18724
18906
|
if (!name.endsWith(".json")) continue;
|
|
18725
|
-
const file =
|
|
18907
|
+
const file = import_node_path74.default.join(dir, name);
|
|
18726
18908
|
let raw;
|
|
18727
18909
|
try {
|
|
18728
|
-
raw = await
|
|
18910
|
+
raw = await import_node_fs38.promises.readFile(file, "utf8");
|
|
18729
18911
|
} catch {
|
|
18730
18912
|
continue;
|
|
18731
18913
|
}
|
|
@@ -18751,7 +18933,7 @@ function isPidAliveDefault(pid) {
|
|
|
18751
18933
|
}
|
|
18752
18934
|
async function readPidFile(file) {
|
|
18753
18935
|
try {
|
|
18754
|
-
const raw = await
|
|
18936
|
+
const raw = await import_node_fs38.promises.readFile(file, "utf8");
|
|
18755
18937
|
const pid = Number.parseInt(raw.trim(), 10);
|
|
18756
18938
|
return Number.isInteger(pid) && pid > 0 ? pid : void 0;
|
|
18757
18939
|
} catch {
|
|
@@ -18795,28 +18977,28 @@ function lockHolderMessage(holder, lockPath, timeoutMs) {
|
|
|
18795
18977
|
case "command":
|
|
18796
18978
|
return `Another neat command (pid ${holder.pid}) is holding the registry lock. Wait for it to finish, or check \`ps\` if you're not sure what's running.`;
|
|
18797
18979
|
case "stale":
|
|
18798
|
-
return `
|
|
18980
|
+
return `timed out after ${timeoutMs}ms waiting for ${lockPath}. Another neat process is holding the lock; if no such process exists, remove the file by hand.`;
|
|
18799
18981
|
}
|
|
18800
18982
|
}
|
|
18801
18983
|
async function writeAtomically(target, contents) {
|
|
18802
|
-
await
|
|
18984
|
+
await import_node_fs38.promises.mkdir(import_node_path74.default.dirname(target), { recursive: true });
|
|
18803
18985
|
const tmp = `${target}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
18804
|
-
const fd = await
|
|
18986
|
+
const fd = await import_node_fs38.promises.open(tmp, "w");
|
|
18805
18987
|
try {
|
|
18806
18988
|
await fd.writeFile(contents, "utf8");
|
|
18807
18989
|
await fd.sync();
|
|
18808
18990
|
} finally {
|
|
18809
18991
|
await fd.close();
|
|
18810
18992
|
}
|
|
18811
|
-
await
|
|
18993
|
+
await import_node_fs38.promises.rename(tmp, target);
|
|
18812
18994
|
}
|
|
18813
18995
|
async function acquireLock(lockPath, timeoutMs = LOCK_TIMEOUT_MS, probe = defaultLockHolderProbe) {
|
|
18814
18996
|
const deadline = Date.now() + timeoutMs;
|
|
18815
|
-
await
|
|
18997
|
+
await import_node_fs38.promises.mkdir(import_node_path74.default.dirname(lockPath), { recursive: true });
|
|
18816
18998
|
let probedHolder = false;
|
|
18817
18999
|
while (true) {
|
|
18818
19000
|
try {
|
|
18819
|
-
const fd = await
|
|
19001
|
+
const fd = await import_node_fs38.promises.open(lockPath, "wx");
|
|
18820
19002
|
try {
|
|
18821
19003
|
await fd.writeFile(`${process.pid}
|
|
18822
19004
|
`, "utf8");
|
|
@@ -18830,18 +19012,36 @@ async function acquireLock(lockPath, timeoutMs = LOCK_TIMEOUT_MS, probe = defaul
|
|
|
18830
19012
|
if (!probedHolder) {
|
|
18831
19013
|
probedHolder = true;
|
|
18832
19014
|
const holder = await classifyLockHolder(lockPath, probe);
|
|
18833
|
-
if (holder.kind === "daemon")
|
|
19015
|
+
if (holder.kind === "daemon") {
|
|
19016
|
+
throw new RegistryLockError(lockHolderMessage(holder, lockPath, timeoutMs));
|
|
19017
|
+
}
|
|
19018
|
+
if (holder.kind === "stale" && await isReclaimableLock(lockPath)) {
|
|
19019
|
+
await import_node_fs38.promises.unlink(lockPath).catch(() => {
|
|
19020
|
+
});
|
|
19021
|
+
continue;
|
|
19022
|
+
}
|
|
18834
19023
|
}
|
|
18835
19024
|
if (Date.now() >= deadline) {
|
|
18836
19025
|
const holder = await classifyLockHolder(lockPath, probe);
|
|
18837
|
-
throw new
|
|
19026
|
+
throw new RegistryLockError(lockHolderMessage(holder, lockPath, timeoutMs));
|
|
18838
19027
|
}
|
|
18839
19028
|
await new Promise((r) => setTimeout(r, LOCK_RETRY_MS));
|
|
18840
19029
|
}
|
|
18841
19030
|
}
|
|
18842
19031
|
}
|
|
19032
|
+
var LOCK_UNSTAMPED_GRACE_MS = 5e3;
|
|
19033
|
+
async function isReclaimableLock(lockPath) {
|
|
19034
|
+
const pid = await readLockPid(lockPath);
|
|
19035
|
+
if (pid !== void 0) return true;
|
|
19036
|
+
try {
|
|
19037
|
+
const stat = await import_node_fs38.promises.stat(lockPath);
|
|
19038
|
+
return Date.now() - stat.mtimeMs > LOCK_UNSTAMPED_GRACE_MS;
|
|
19039
|
+
} catch {
|
|
19040
|
+
return false;
|
|
19041
|
+
}
|
|
19042
|
+
}
|
|
18843
19043
|
async function releaseLock(lockPath) {
|
|
18844
|
-
await
|
|
19044
|
+
await import_node_fs38.promises.unlink(lockPath).catch(() => {
|
|
18845
19045
|
});
|
|
18846
19046
|
}
|
|
18847
19047
|
async function withLock(fn) {
|
|
@@ -18857,7 +19057,7 @@ async function readRegistry() {
|
|
|
18857
19057
|
const file = registryPath();
|
|
18858
19058
|
let raw;
|
|
18859
19059
|
try {
|
|
18860
|
-
raw = await
|
|
19060
|
+
raw = await import_node_fs38.promises.readFile(file, "utf8");
|
|
18861
19061
|
} catch (err) {
|
|
18862
19062
|
if (err.code === "ENOENT") {
|
|
18863
19063
|
return { version: 1, projects: [] };
|
|
@@ -18871,6 +19071,18 @@ async function writeRegistry(reg) {
|
|
|
18871
19071
|
const validated = import_types63.RegistryFileSchema.parse(reg);
|
|
18872
19072
|
await writeAtomically(registryPath(), JSON.stringify(validated, null, 2) + "\n");
|
|
18873
19073
|
}
|
|
19074
|
+
var RegistryError = class extends Error {
|
|
19075
|
+
constructor(message) {
|
|
19076
|
+
super(message);
|
|
19077
|
+
this.name = "RegistryError";
|
|
19078
|
+
}
|
|
19079
|
+
};
|
|
19080
|
+
var RegistryLockError = class extends RegistryError {
|
|
19081
|
+
constructor(message) {
|
|
19082
|
+
super(message);
|
|
19083
|
+
this.name = "RegistryLockError";
|
|
19084
|
+
}
|
|
19085
|
+
};
|
|
18874
19086
|
async function getProject(name) {
|
|
18875
19087
|
const reg = await readRegistry();
|
|
18876
19088
|
return reg.projects.find((p) => p.name === name);
|
|
@@ -18883,7 +19095,7 @@ async function setStatus(name, status2) {
|
|
|
18883
19095
|
return withLock(async () => {
|
|
18884
19096
|
const reg = await readRegistry();
|
|
18885
19097
|
const entry2 = reg.projects.find((p) => p.name === name);
|
|
18886
|
-
if (!entry2) throw new
|
|
19098
|
+
if (!entry2) throw new RegistryError(`no project named "${name}"`);
|
|
18887
19099
|
entry2.status = status2;
|
|
18888
19100
|
await writeRegistry(reg);
|
|
18889
19101
|
return entry2;
|
|
@@ -18912,7 +19124,7 @@ function pruneTtlMs() {
|
|
|
18912
19124
|
}
|
|
18913
19125
|
async function statPathStatus(p) {
|
|
18914
19126
|
try {
|
|
18915
|
-
const stat = await
|
|
19127
|
+
const stat = await import_node_fs38.promises.stat(p);
|
|
18916
19128
|
return stat.isDirectory() ? "present" : "unknown";
|
|
18917
19129
|
} catch (err) {
|
|
18918
19130
|
return err.code === "ENOENT" ? "gone" : "unknown";
|
|
@@ -19013,8 +19225,8 @@ init_auth();
|
|
|
19013
19225
|
// src/connectors-config.ts
|
|
19014
19226
|
init_cjs_shims();
|
|
19015
19227
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
19016
|
-
var
|
|
19017
|
-
var
|
|
19228
|
+
var import_node_path75 = __toESM(require("path"), 1);
|
|
19229
|
+
var import_node_fs39 = require("fs");
|
|
19018
19230
|
var CONNECTORS_CONFIG_VERSION = 1;
|
|
19019
19231
|
var EnvRefUnsetError = class extends Error {
|
|
19020
19232
|
ref;
|
|
@@ -19028,17 +19240,17 @@ var EnvRefUnsetError = class extends Error {
|
|
|
19028
19240
|
};
|
|
19029
19241
|
function neatHome2() {
|
|
19030
19242
|
const override = process.env.NEAT_HOME;
|
|
19031
|
-
if (override && override.length > 0) return
|
|
19032
|
-
return
|
|
19243
|
+
if (override && override.length > 0) return import_node_path75.default.resolve(override);
|
|
19244
|
+
return import_node_path75.default.join(import_node_os4.default.homedir(), ".neat");
|
|
19033
19245
|
}
|
|
19034
19246
|
function connectorsConfigPath(home = neatHome2()) {
|
|
19035
|
-
return
|
|
19247
|
+
return import_node_path75.default.join(home, "connectors.json");
|
|
19036
19248
|
}
|
|
19037
19249
|
var MODE_MASK_LOOSER_THAN_0600 = 63;
|
|
19038
19250
|
async function warnIfModeLooserThan0600(file) {
|
|
19039
19251
|
if (process.platform === "win32") return;
|
|
19040
19252
|
try {
|
|
19041
|
-
const stat = await
|
|
19253
|
+
const stat = await import_node_fs39.promises.stat(file);
|
|
19042
19254
|
if ((stat.mode & MODE_MASK_LOOSER_THAN_0600) !== 0) {
|
|
19043
19255
|
const mode = (stat.mode & 511).toString(8).padStart(3, "0");
|
|
19044
19256
|
console.warn(
|
|
@@ -19052,7 +19264,7 @@ async function readConnectorsConfig(home = neatHome2()) {
|
|
|
19052
19264
|
const file = connectorsConfigPath(home);
|
|
19053
19265
|
let raw;
|
|
19054
19266
|
try {
|
|
19055
|
-
raw = await
|
|
19267
|
+
raw = await import_node_fs39.promises.readFile(file, "utf8");
|
|
19056
19268
|
} catch (err) {
|
|
19057
19269
|
if (err.code === "ENOENT") {
|
|
19058
19270
|
return { version: CONNECTORS_CONFIG_VERSION, connectors: [] };
|
|
@@ -19848,10 +20060,10 @@ var SUPABASE_RPC_TARGET_KIND = "supabase-rpc";
|
|
|
19848
20060
|
// src/connectors/supabase/map.ts
|
|
19849
20061
|
var REST_RPC_PATH_RE = /^\/rest\/v1\/rpc\/([^/?]+)/;
|
|
19850
20062
|
var REST_TABLE_PATH_RE = /^\/rest\/v1\/([^/?]+)/;
|
|
19851
|
-
function targetFromRestPath(
|
|
19852
|
-
const rpcMatch = REST_RPC_PATH_RE.exec(
|
|
20063
|
+
function targetFromRestPath(path82) {
|
|
20064
|
+
const rpcMatch = REST_RPC_PATH_RE.exec(path82);
|
|
19853
20065
|
if (rpcMatch) return { targetKind: SUPABASE_RPC_TARGET_KIND, name: rpcMatch[1] };
|
|
19854
|
-
const tableMatch = REST_TABLE_PATH_RE.exec(
|
|
20066
|
+
const tableMatch = REST_TABLE_PATH_RE.exec(path82);
|
|
19855
20067
|
if (tableMatch) return { targetKind: SUPABASE_TABLE_TARGET_KIND, name: tableMatch[1] };
|
|
19856
20068
|
return null;
|
|
19857
20069
|
}
|
|
@@ -20455,9 +20667,9 @@ function parseFirebaseTargetName(targetName) {
|
|
|
20455
20667
|
const secondSep = rest.indexOf(FIELD_SEP);
|
|
20456
20668
|
if (secondSep === -1) return null;
|
|
20457
20669
|
const method = rest.slice(0, secondSep);
|
|
20458
|
-
const
|
|
20459
|
-
if (!resourceName || !method || !
|
|
20460
|
-
return { resourceName, method, path:
|
|
20670
|
+
const path82 = rest.slice(secondSep + 1);
|
|
20671
|
+
if (!resourceName || !method || !path82) return null;
|
|
20672
|
+
return { resourceName, method, path: path82 };
|
|
20461
20673
|
}
|
|
20462
20674
|
function resourceNameFor(type, labels) {
|
|
20463
20675
|
if (!labels) return null;
|
|
@@ -20495,14 +20707,14 @@ function mapLogEntryToSignal(entry2) {
|
|
|
20495
20707
|
if (!req2) return null;
|
|
20496
20708
|
if (typeof req2.requestMethod !== "string" || req2.requestMethod.length === 0) return null;
|
|
20497
20709
|
const method = req2.requestMethod.toUpperCase();
|
|
20498
|
-
const
|
|
20499
|
-
if (
|
|
20710
|
+
const path82 = pathFromRequestUrl(req2.requestUrl);
|
|
20711
|
+
if (path82 === null) return null;
|
|
20500
20712
|
const timestamp = entry2.timestamp;
|
|
20501
20713
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
20502
20714
|
const isError = typeof req2.status === "number" && req2.status >= ERROR_STATUS_THRESHOLD2;
|
|
20503
20715
|
return {
|
|
20504
20716
|
targetKind: resourceType,
|
|
20505
|
-
targetName: packFirebaseTargetName({ resourceName, method, path:
|
|
20717
|
+
targetName: packFirebaseTargetName({ resourceName, method, path: path82 }),
|
|
20506
20718
|
callCount: 1,
|
|
20507
20719
|
errorCount: isError ? 1 : 0,
|
|
20508
20720
|
lastObservedIso: timestamp
|
|
@@ -20527,9 +20739,9 @@ var import_types71 = require("@neat.is/types");
|
|
|
20527
20739
|
function normalizeName(name) {
|
|
20528
20740
|
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
20529
20741
|
}
|
|
20530
|
-
function inferServiceName(graph, resourceName, method,
|
|
20742
|
+
function inferServiceName(graph, resourceName, method, path82) {
|
|
20531
20743
|
const wantedMethod = method.toUpperCase();
|
|
20532
|
-
const wantedPath = normalizePathTemplate(
|
|
20744
|
+
const wantedPath = normalizePathTemplate(path82);
|
|
20533
20745
|
const services = [];
|
|
20534
20746
|
const owners = /* @__PURE__ */ new Set();
|
|
20535
20747
|
graph.forEachNode((_id, attrs) => {
|
|
@@ -20746,7 +20958,7 @@ function mapEventToSignal(event) {
|
|
|
20746
20958
|
if (Number.isNaN(observedAt.getTime())) return null;
|
|
20747
20959
|
const statusCode = metadata?.statusCode;
|
|
20748
20960
|
const isError = typeof statusCode === "number" && statusCode >= ERROR_STATUS_THRESHOLD3;
|
|
20749
|
-
const
|
|
20961
|
+
const path82 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
|
|
20750
20962
|
return {
|
|
20751
20963
|
targetKind: CLOUDFLARE_TARGET_KIND,
|
|
20752
20964
|
targetName: scriptName,
|
|
@@ -20754,7 +20966,7 @@ function mapEventToSignal(event) {
|
|
|
20754
20966
|
errorCount: isError ? 1 : 0,
|
|
20755
20967
|
lastObservedIso: observedAt.toISOString(),
|
|
20756
20968
|
method,
|
|
20757
|
-
...
|
|
20969
|
+
...path82 ? { path: path82 } : {},
|
|
20758
20970
|
...typeof statusCode === "number" ? { statusCode } : {},
|
|
20759
20971
|
...typeof metadata?.duration === "number" ? { duration: metadata.duration } : {}
|
|
20760
20972
|
};
|
|
@@ -20800,8 +21012,8 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
20800
21012
|
});
|
|
20801
21013
|
return found;
|
|
20802
21014
|
}
|
|
20803
|
-
function findMatchingRouteNode(graph, serviceName, method,
|
|
20804
|
-
const normalizedPath = normalizePathTemplate(
|
|
21015
|
+
function findMatchingRouteNode(graph, serviceName, method, path82) {
|
|
21016
|
+
const normalizedPath = normalizePathTemplate(path82);
|
|
20805
21017
|
let found = null;
|
|
20806
21018
|
graph.forEachNode((id, attrs) => {
|
|
20807
21019
|
if (found) return;
|
|
@@ -20818,10 +21030,10 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
20818
21030
|
return (signal) => {
|
|
20819
21031
|
if (signal.targetKind !== CLOUDFLARE_TARGET_KIND) return null;
|
|
20820
21032
|
const scriptName = signal.targetName;
|
|
20821
|
-
const { method, path:
|
|
21033
|
+
const { method, path: path82 } = signal;
|
|
20822
21034
|
const resolveRouteGrain = (serviceName, wholeFileId) => {
|
|
20823
|
-
if (!method || !
|
|
20824
|
-
return findMatchingRouteNode(graph, serviceName, method,
|
|
21035
|
+
if (!method || !path82) return wholeFileId;
|
|
21036
|
+
return findMatchingRouteNode(graph, serviceName, method, path82) ?? wholeFileId;
|
|
20825
21037
|
};
|
|
20826
21038
|
const mapping = config.workers?.[scriptName];
|
|
20827
21039
|
if (mapping) {
|
|
@@ -21173,9 +21385,9 @@ function parseCloudRunTargetName(targetName) {
|
|
|
21173
21385
|
const secondSep = rest.indexOf(FIELD_SEP2);
|
|
21174
21386
|
if (secondSep === -1) return null;
|
|
21175
21387
|
const method = rest.slice(0, secondSep);
|
|
21176
|
-
const
|
|
21177
|
-
if (!serviceName || !method || !
|
|
21178
|
-
return { serviceName, method, path:
|
|
21388
|
+
const path82 = rest.slice(secondSep + 1);
|
|
21389
|
+
if (!serviceName || !method || !path82) return null;
|
|
21390
|
+
return { serviceName, method, path: path82 };
|
|
21179
21391
|
}
|
|
21180
21392
|
|
|
21181
21393
|
// src/connectors/cloud-run/map.ts
|
|
@@ -21204,14 +21416,14 @@ function mapLogEntryToSignal2(entry2) {
|
|
|
21204
21416
|
if (!req2) return null;
|
|
21205
21417
|
if (typeof req2.requestMethod !== "string" || req2.requestMethod.length === 0) return null;
|
|
21206
21418
|
const method = req2.requestMethod.toUpperCase();
|
|
21207
|
-
const
|
|
21208
|
-
if (
|
|
21419
|
+
const path82 = pathFromRequestUrl2(req2.requestUrl);
|
|
21420
|
+
if (path82 === null) return null;
|
|
21209
21421
|
const timestamp = entry2.timestamp;
|
|
21210
21422
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
21211
21423
|
const isError = typeof req2.status === "number" && req2.status >= ERROR_STATUS_THRESHOLD4;
|
|
21212
21424
|
return {
|
|
21213
21425
|
targetKind: CLOUD_RUN_TARGET_KIND,
|
|
21214
|
-
targetName: packCloudRunTargetName({ serviceName, method, path:
|
|
21426
|
+
targetName: packCloudRunTargetName({ serviceName, method, path: path82 }),
|
|
21215
21427
|
callCount: 1,
|
|
21216
21428
|
errorCount: isError ? 1 : 0,
|
|
21217
21429
|
lastObservedIso: timestamp
|
|
@@ -21250,14 +21462,14 @@ function createCloudRunResolveTarget(graph, config) {
|
|
|
21250
21462
|
if (signal.targetKind !== CLOUD_RUN_TARGET_KIND) return null;
|
|
21251
21463
|
const identity = parseCloudRunTargetName(signal.targetName);
|
|
21252
21464
|
if (!identity) return null;
|
|
21253
|
-
const { serviceName: gcpServiceName, method, path:
|
|
21254
|
-
const mappedService = config.serviceMap?.[gcpServiceName] ?? (config.inferServices ? inferServiceName(graph, gcpServiceName, method,
|
|
21465
|
+
const { serviceName: gcpServiceName, method, path: path82 } = identity;
|
|
21466
|
+
const mappedService = config.serviceMap?.[gcpServiceName] ?? (config.inferServices ? inferServiceName(graph, gcpServiceName, method, path82) ?? void 0 : void 0);
|
|
21255
21467
|
if (mappedService) {
|
|
21256
21468
|
const routeNodeId = findMatchingRouteNode2(
|
|
21257
21469
|
graph,
|
|
21258
21470
|
mappedService,
|
|
21259
21471
|
method,
|
|
21260
|
-
normalizePathTemplate(
|
|
21472
|
+
normalizePathTemplate(path82)
|
|
21261
21473
|
);
|
|
21262
21474
|
if (routeNodeId) {
|
|
21263
21475
|
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types82.EdgeType.CALLS };
|
|
@@ -21393,9 +21605,9 @@ function parseGcpLbTargetName(targetName) {
|
|
|
21393
21605
|
const secondSep = rest.indexOf(FIELD_SEP3);
|
|
21394
21606
|
if (secondSep === -1) return null;
|
|
21395
21607
|
const method = rest.slice(0, secondSep);
|
|
21396
|
-
const
|
|
21397
|
-
if (!backendServiceName || !method || !
|
|
21398
|
-
return { backendServiceName, method, path:
|
|
21608
|
+
const path82 = rest.slice(secondSep + 1);
|
|
21609
|
+
if (!backendServiceName || !method || !path82) return null;
|
|
21610
|
+
return { backendServiceName, method, path: path82 };
|
|
21399
21611
|
}
|
|
21400
21612
|
|
|
21401
21613
|
// src/connectors/gcp-lb/map.ts
|
|
@@ -21424,14 +21636,14 @@ function mapLogEntryToSignal3(entry2) {
|
|
|
21424
21636
|
if (!req2) return null;
|
|
21425
21637
|
if (typeof req2.requestMethod !== "string" || req2.requestMethod.length === 0) return null;
|
|
21426
21638
|
const method = req2.requestMethod.toUpperCase();
|
|
21427
|
-
const
|
|
21428
|
-
if (
|
|
21639
|
+
const path82 = pathFromRequestUrl3(req2.requestUrl);
|
|
21640
|
+
if (path82 === null) return null;
|
|
21429
21641
|
const timestamp = entry2.timestamp;
|
|
21430
21642
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
21431
21643
|
const isError = typeof req2.status === "number" && req2.status >= ERROR_STATUS_THRESHOLD5;
|
|
21432
21644
|
return {
|
|
21433
21645
|
targetKind: GCP_LB_TARGET_KIND,
|
|
21434
|
-
targetName: packGcpLbTargetName({ backendServiceName, method, path:
|
|
21646
|
+
targetName: packGcpLbTargetName({ backendServiceName, method, path: path82 }),
|
|
21435
21647
|
callCount: 1,
|
|
21436
21648
|
errorCount: isError ? 1 : 0,
|
|
21437
21649
|
lastObservedIso: timestamp
|
|
@@ -21470,14 +21682,14 @@ function createGcpLbResolveTarget(graph, config) {
|
|
|
21470
21682
|
if (signal.targetKind !== GCP_LB_TARGET_KIND) return null;
|
|
21471
21683
|
const identity = parseGcpLbTargetName(signal.targetName);
|
|
21472
21684
|
if (!identity) return null;
|
|
21473
|
-
const { backendServiceName, method, path:
|
|
21474
|
-
const mappedService = config.backendServiceMap?.[backendServiceName] ?? (config.inferServices ? inferServiceName(graph, backendServiceName, method,
|
|
21685
|
+
const { backendServiceName, method, path: path82 } = identity;
|
|
21686
|
+
const mappedService = config.backendServiceMap?.[backendServiceName] ?? (config.inferServices ? inferServiceName(graph, backendServiceName, method, path82) ?? void 0 : void 0);
|
|
21475
21687
|
if (mappedService) {
|
|
21476
21688
|
const routeNodeId = findMatchingRouteNode3(
|
|
21477
21689
|
graph,
|
|
21478
21690
|
mappedService,
|
|
21479
21691
|
method,
|
|
21480
|
-
normalizePathTemplate(
|
|
21692
|
+
normalizePathTemplate(path82)
|
|
21481
21693
|
);
|
|
21482
21694
|
if (routeNodeId) {
|
|
21483
21695
|
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types86.EdgeType.CALLS };
|
|
@@ -22795,16 +23007,18 @@ function serializeGraph(graph) {
|
|
|
22795
23007
|
});
|
|
22796
23008
|
return { nodes, edges };
|
|
22797
23009
|
}
|
|
22798
|
-
function projectFromReq(req2, singleProject) {
|
|
23010
|
+
function projectFromReq(req2, singleProject, registry) {
|
|
22799
23011
|
const params = req2.params;
|
|
22800
23012
|
const named2 = params.project;
|
|
22801
23013
|
if (singleProject) {
|
|
22802
23014
|
return named2 === void 0 || named2 === DEFAULT_PROJECT ? singleProject : named2;
|
|
22803
23015
|
}
|
|
22804
|
-
|
|
23016
|
+
if (named2 !== void 0) return named2;
|
|
23017
|
+
const hosted = registry?.list() ?? [];
|
|
23018
|
+
return hosted.length === 1 ? hosted[0] : DEFAULT_PROJECT;
|
|
22805
23019
|
}
|
|
22806
23020
|
function resolveProject(registry, req2, reply, bootstrap, singleProject) {
|
|
22807
|
-
const name = projectFromReq(req2, singleProject);
|
|
23021
|
+
const name = projectFromReq(req2, singleProject, registry);
|
|
22808
23022
|
const ctx = registry.get(name);
|
|
22809
23023
|
if (!ctx) {
|
|
22810
23024
|
const phase = bootstrap?.status(name);
|
|
@@ -22816,10 +23030,13 @@ function resolveProject(registry, req2, reply, bootstrap, singleProject) {
|
|
|
22816
23030
|
void reply.code(503).send({ ready: false, project: name, status: "broken" });
|
|
22817
23031
|
return null;
|
|
22818
23032
|
}
|
|
23033
|
+
const unnamed = req2.params.project === void 0;
|
|
23034
|
+
const hosted = registry.list();
|
|
23035
|
+
const hint = unnamed && name === DEFAULT_PROJECT && hosted.length > 1 ? `This daemon hosts ${hosted.length} projects and none is named \`default\`: ${hosted.join(", ")}. Name one as /projects/<name>/\u2026 , or reach that project's own daemon.` : "This daemon does not host that project. GET /projects lists what it serves (see hostedHere).";
|
|
22819
23036
|
void reply.code(404).send({
|
|
22820
23037
|
error: "project not found",
|
|
22821
23038
|
project: name,
|
|
22822
|
-
hint
|
|
23039
|
+
hint
|
|
22823
23040
|
});
|
|
22824
23041
|
return null;
|
|
22825
23042
|
}
|
|
@@ -23732,7 +23949,7 @@ async function reconcileFrontierSurfaces(graph, errorsPath) {
|
|
|
23732
23949
|
// src/connectors/hosted.ts
|
|
23733
23950
|
init_cjs_shims();
|
|
23734
23951
|
var import_promises = require("fs/promises");
|
|
23735
|
-
var
|
|
23952
|
+
var import_node_path76 = require("path");
|
|
23736
23953
|
|
|
23737
23954
|
// src/connectors/railway/target-ref.ts
|
|
23738
23955
|
init_cjs_shims();
|
|
@@ -23767,13 +23984,13 @@ function decodeRailwayTargetRef(ref) {
|
|
|
23767
23984
|
var CREDENTIAL_REFRESH_SKEW_MS = 6e4;
|
|
23768
23985
|
var CP_REQUEST_TIMEOUT_MS = 1e4;
|
|
23769
23986
|
var DEFAULT_RELIST_INTERVAL_MS = 6e4;
|
|
23770
|
-
async function cpGet(
|
|
23987
|
+
async function cpGet(path82, deps) {
|
|
23771
23988
|
const f = deps.fetchImpl ?? fetch;
|
|
23772
|
-
const res = await f(`${deps.cpUrl.replace(/\/+$/, "")}${
|
|
23989
|
+
const res = await f(`${deps.cpUrl.replace(/\/+$/, "")}${path82}`, {
|
|
23773
23990
|
headers: { authorization: `Bearer ${deps.daemonToken}`, accept: "application/json" },
|
|
23774
23991
|
signal: AbortSignal.timeout(CP_REQUEST_TIMEOUT_MS)
|
|
23775
23992
|
});
|
|
23776
|
-
if (!res.ok) throw new Error(`control plane ${
|
|
23993
|
+
if (!res.ok) throw new Error(`control plane ${path82} \u2192 HTTP ${res.status}`);
|
|
23777
23994
|
return await res.json();
|
|
23778
23995
|
}
|
|
23779
23996
|
function credentialRecord(provider, cred) {
|
|
@@ -23834,7 +24051,7 @@ function parseFirebaseServiceMap(raw) {
|
|
|
23834
24051
|
}
|
|
23835
24052
|
}
|
|
23836
24053
|
function pushHandlesPath(projectDir) {
|
|
23837
|
-
return (0,
|
|
24054
|
+
return (0, import_node_path76.join)(projectDir, "neat-out", "connectors-hosted.json");
|
|
23838
24055
|
}
|
|
23839
24056
|
async function readPushHandles(projectDir) {
|
|
23840
24057
|
try {
|
|
@@ -23845,14 +24062,14 @@ async function readPushHandles(projectDir) {
|
|
|
23845
24062
|
}
|
|
23846
24063
|
}
|
|
23847
24064
|
async function writePushHandle(projectDir, provider, handle) {
|
|
23848
|
-
const
|
|
24065
|
+
const path82 = pushHandlesPath(projectDir);
|
|
23849
24066
|
const handles = await readPushHandles(projectDir);
|
|
23850
24067
|
handles[provider] = handle;
|
|
23851
|
-
await (0, import_promises.mkdir)((0,
|
|
23852
|
-
const tmp = `${
|
|
24068
|
+
await (0, import_promises.mkdir)((0, import_node_path76.dirname)(path82), { recursive: true });
|
|
24069
|
+
const tmp = `${path82}.${process.pid}.tmp`;
|
|
23853
24070
|
await (0, import_promises.writeFile)(tmp, `${JSON.stringify(handles, null, 2)}
|
|
23854
24071
|
`, "utf8");
|
|
23855
|
-
await (0, import_promises.rename)(tmp,
|
|
24072
|
+
await (0, import_promises.rename)(tmp, path82);
|
|
23856
24073
|
}
|
|
23857
24074
|
function pushCredentialRecord(provider, cred, deps) {
|
|
23858
24075
|
switch (provider) {
|
|
@@ -24073,7 +24290,7 @@ async function maybeStartHostedConnectors(input) {
|
|
|
24073
24290
|
// src/connectors/hosted-repos.ts
|
|
24074
24291
|
init_cjs_shims();
|
|
24075
24292
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
24076
|
-
var
|
|
24293
|
+
var import_node_path77 = __toESM(require("path"), 1);
|
|
24077
24294
|
var import_promises2 = require("fs/promises");
|
|
24078
24295
|
var CP_REQUEST_TIMEOUT_MS2 = 1e4;
|
|
24079
24296
|
var DEFAULT_SYNC_INTERVAL_MS = 5 * 6e4;
|
|
@@ -24102,7 +24319,7 @@ async function cpPostStatus(deps, owner, name, body) {
|
|
|
24102
24319
|
if (!res.ok && res.status !== 404) throw new Error(`control plane status POST \u2192 HTTP ${res.status}`);
|
|
24103
24320
|
}
|
|
24104
24321
|
var defaultCloneRepo = async (cloneUrl, ref, destDir) => {
|
|
24105
|
-
const [{ default: git }, httpMod,
|
|
24322
|
+
const [{ default: git }, httpMod, fs42] = await Promise.all([
|
|
24106
24323
|
import("isomorphic-git"),
|
|
24107
24324
|
import("isomorphic-git/http/node"),
|
|
24108
24325
|
import("fs")
|
|
@@ -24113,7 +24330,7 @@ var defaultCloneRepo = async (cloneUrl, ref, destDir) => {
|
|
|
24113
24330
|
const username = parsed.password ? parsed.username : "x-access-token";
|
|
24114
24331
|
const cleanUrl = `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
|
|
24115
24332
|
const clone = git.clone({
|
|
24116
|
-
fs:
|
|
24333
|
+
fs: fs42,
|
|
24117
24334
|
http,
|
|
24118
24335
|
dir: destDir,
|
|
24119
24336
|
url: cleanUrl,
|
|
@@ -24144,7 +24361,7 @@ async function syncOneRepo(r, input) {
|
|
|
24144
24361
|
const tmpRoot = input.tmpRoot ?? import_node_os5.default.tmpdir();
|
|
24145
24362
|
let dir;
|
|
24146
24363
|
try {
|
|
24147
|
-
dir = await (0, import_promises2.mkdtemp)(
|
|
24364
|
+
dir = await (0, import_promises2.mkdtemp)(import_node_path77.default.join(tmpRoot, "neat-repo-"));
|
|
24148
24365
|
await cpPostStatus(deps, r.owner, r.name, { syncStatus: "syncing", detail: "cloning" }).catch(() => {
|
|
24149
24366
|
});
|
|
24150
24367
|
await cloneRepo(r.cloneUrl, r.defaultBranch, dir);
|
|
@@ -24281,9 +24498,9 @@ function makeK8sFetchImpl(transport) {
|
|
|
24281
24498
|
req2.end();
|
|
24282
24499
|
}));
|
|
24283
24500
|
}
|
|
24284
|
-
async function listResource(transport, namespace,
|
|
24501
|
+
async function listResource(transport, namespace, path82, opts = {}) {
|
|
24285
24502
|
const base = opts.apiUrl ?? transport.server;
|
|
24286
|
-
const url = `${base.replace(/\/$/, "")}${
|
|
24503
|
+
const url = `${base.replace(/\/$/, "")}${path82}`;
|
|
24287
24504
|
const fetchImpl = opts.fetchImpl ?? makeK8sFetchImpl(transport);
|
|
24288
24505
|
const res = await junctionFetch(
|
|
24289
24506
|
url,
|
|
@@ -24293,7 +24510,7 @@ async function listResource(transport, namespace, path81, opts = {}) {
|
|
|
24293
24510
|
{ provider: "kubernetes", accountKey: `${safeHost(transport.server)}/${namespace}`, fetchImpl }
|
|
24294
24511
|
);
|
|
24295
24512
|
if (!res.ok) {
|
|
24296
|
-
throw new Error(`kubernetes ${
|
|
24513
|
+
throw new Error(`kubernetes ${path82} failed: ${res.status} ${res.statusText}`);
|
|
24297
24514
|
}
|
|
24298
24515
|
const json = await res.json();
|
|
24299
24516
|
return Array.isArray(json.items) ? json.items : [];
|
|
@@ -24314,14 +24531,14 @@ async function fetchPods(transport, namespace, opts = {}) {
|
|
|
24314
24531
|
|
|
24315
24532
|
// src/connectors/kubernetes/kubeconfig.ts
|
|
24316
24533
|
init_cjs_shims();
|
|
24317
|
-
var
|
|
24534
|
+
var import_node_fs40 = require("fs");
|
|
24318
24535
|
var import_yaml4 = require("yaml");
|
|
24319
24536
|
function pemFrom(dataField, pathField) {
|
|
24320
24537
|
if (typeof dataField === "string" && dataField.length > 0) {
|
|
24321
24538
|
return Buffer.from(dataField, "base64").toString("utf8");
|
|
24322
24539
|
}
|
|
24323
24540
|
if (typeof pathField === "string" && pathField.length > 0) {
|
|
24324
|
-
return (0,
|
|
24541
|
+
return (0, import_node_fs40.readFileSync)(pathField, "utf8");
|
|
24325
24542
|
}
|
|
24326
24543
|
return void 0;
|
|
24327
24544
|
}
|
|
@@ -24332,7 +24549,7 @@ function named(list, name) {
|
|
|
24332
24549
|
}
|
|
24333
24550
|
function parseKubeconfig(kubeconfig) {
|
|
24334
24551
|
const looksInline = /\n/.test(kubeconfig) || /(^|\s)clusters\s*:/.test(kubeconfig);
|
|
24335
|
-
const text = looksInline ? kubeconfig : (0,
|
|
24552
|
+
const text = looksInline ? kubeconfig : (0, import_node_fs40.readFileSync)(kubeconfig, "utf8");
|
|
24336
24553
|
let doc;
|
|
24337
24554
|
try {
|
|
24338
24555
|
doc = (0, import_yaml4.parse)(text);
|
|
@@ -24597,14 +24814,14 @@ function createK8sResolveTarget(graph) {
|
|
|
24597
24814
|
init_cjs_shims();
|
|
24598
24815
|
var import_promises3 = require("fs/promises");
|
|
24599
24816
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
24600
|
-
var
|
|
24817
|
+
var import_node_path78 = __toESM(require("path"), 1);
|
|
24601
24818
|
function defaultHome() {
|
|
24602
24819
|
const override = process.env.NEAT_HOME;
|
|
24603
|
-
if (override && override.length > 0) return
|
|
24604
|
-
return
|
|
24820
|
+
if (override && override.length > 0) return import_node_path78.default.resolve(override);
|
|
24821
|
+
return import_node_path78.default.join(import_node_os6.default.homedir(), ".neat");
|
|
24605
24822
|
}
|
|
24606
24823
|
function k8sSubstrateConfigPath(home = defaultHome()) {
|
|
24607
|
-
return
|
|
24824
|
+
return import_node_path78.default.join(home, "k8s.json");
|
|
24608
24825
|
}
|
|
24609
24826
|
async function readK8sSubstrateConfig(home = defaultHome()) {
|
|
24610
24827
|
let raw;
|
|
@@ -24703,8 +24920,8 @@ init_auth();
|
|
|
24703
24920
|
|
|
24704
24921
|
// src/unrouted.ts
|
|
24705
24922
|
init_cjs_shims();
|
|
24706
|
-
var
|
|
24707
|
-
var
|
|
24923
|
+
var import_node_fs41 = require("fs");
|
|
24924
|
+
var import_node_path79 = __toESM(require("path"), 1);
|
|
24708
24925
|
function buildUnroutedSpanRecord(serviceName, traceId, now = /* @__PURE__ */ new Date()) {
|
|
24709
24926
|
return {
|
|
24710
24927
|
timestamp: now.toISOString(),
|
|
@@ -24714,34 +24931,34 @@ function buildUnroutedSpanRecord(serviceName, traceId, now = /* @__PURE__ */ new
|
|
|
24714
24931
|
};
|
|
24715
24932
|
}
|
|
24716
24933
|
async function appendUnroutedSpan(neatHome4, record) {
|
|
24717
|
-
const target =
|
|
24718
|
-
await
|
|
24719
|
-
await
|
|
24934
|
+
const target = import_node_path79.default.join(neatHome4, "errors.ndjson");
|
|
24935
|
+
await import_node_fs41.promises.mkdir(neatHome4, { recursive: true });
|
|
24936
|
+
await import_node_fs41.promises.appendFile(target, JSON.stringify(record) + "\n", "utf8");
|
|
24720
24937
|
}
|
|
24721
24938
|
function unroutedErrorsPath(neatHome4) {
|
|
24722
|
-
return
|
|
24939
|
+
return import_node_path79.default.join(neatHome4, "errors.ndjson");
|
|
24723
24940
|
}
|
|
24724
24941
|
|
|
24725
24942
|
// src/daemon.ts
|
|
24726
24943
|
var import_types107 = require("@neat.is/types");
|
|
24727
24944
|
function daemonJsonPath(scanPath) {
|
|
24728
|
-
return
|
|
24945
|
+
return import_node_path80.default.join(scanPath, "neat-out", "daemon.json");
|
|
24729
24946
|
}
|
|
24730
24947
|
function daemonsDiscoveryDir(home) {
|
|
24731
24948
|
const base = home && home.length > 0 ? home : neatHomeFromEnv();
|
|
24732
|
-
return
|
|
24949
|
+
return import_node_path80.default.join(base, "daemons");
|
|
24733
24950
|
}
|
|
24734
24951
|
function daemonDiscoveryPath(project, home) {
|
|
24735
|
-
return
|
|
24952
|
+
return import_node_path80.default.join(daemonsDiscoveryDir(home), `${sanitizeDiscoveryName(project)}.json`);
|
|
24736
24953
|
}
|
|
24737
24954
|
function sanitizeDiscoveryName(project) {
|
|
24738
24955
|
return project.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
24739
24956
|
}
|
|
24740
24957
|
function neatHomeFromEnv() {
|
|
24741
24958
|
const env = process.env.NEAT_HOME;
|
|
24742
|
-
if (env && env.length > 0) return
|
|
24959
|
+
if (env && env.length > 0) return import_node_path80.default.resolve(env);
|
|
24743
24960
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
24744
|
-
return
|
|
24961
|
+
return import_node_path80.default.join(home, ".neat");
|
|
24745
24962
|
}
|
|
24746
24963
|
function resolveNeatVersion() {
|
|
24747
24964
|
if (process.env.NEAT_LOCAL_VERSION && process.env.NEAT_LOCAL_VERSION.length > 0) {
|
|
@@ -24773,7 +24990,7 @@ async function clearDaemonRecord(record, home) {
|
|
|
24773
24990
|
} catch {
|
|
24774
24991
|
}
|
|
24775
24992
|
try {
|
|
24776
|
-
await
|
|
24993
|
+
await import_node_fs42.promises.unlink(daemonDiscoveryPath(record.project, home));
|
|
24777
24994
|
} catch {
|
|
24778
24995
|
}
|
|
24779
24996
|
}
|
|
@@ -24782,12 +24999,12 @@ function reconcileDaemonRecordSync(record, home) {
|
|
|
24782
24999
|
const stopped = { ...record, status: "stopped" };
|
|
24783
25000
|
const target = daemonJsonPath(record.projectPath);
|
|
24784
25001
|
const tmp = `${target}.${process.pid}.tmp`;
|
|
24785
|
-
(0,
|
|
24786
|
-
(0,
|
|
25002
|
+
(0, import_node_fs42.writeFileSync)(tmp, JSON.stringify(stopped, null, 2) + "\n");
|
|
25003
|
+
(0, import_node_fs42.renameSync)(tmp, target);
|
|
24787
25004
|
} catch {
|
|
24788
25005
|
}
|
|
24789
25006
|
try {
|
|
24790
|
-
(0,
|
|
25007
|
+
(0, import_node_fs42.unlinkSync)(daemonDiscoveryPath(record.project, home));
|
|
24791
25008
|
} catch {
|
|
24792
25009
|
}
|
|
24793
25010
|
}
|
|
@@ -24822,11 +25039,11 @@ function teardownSlot(slot) {
|
|
|
24822
25039
|
}
|
|
24823
25040
|
}
|
|
24824
25041
|
function neatHomeFor(opts) {
|
|
24825
|
-
if (opts.neatHome && opts.neatHome.length > 0) return
|
|
25042
|
+
if (opts.neatHome && opts.neatHome.length > 0) return import_node_path80.default.resolve(opts.neatHome);
|
|
24826
25043
|
const env = process.env.NEAT_HOME;
|
|
24827
|
-
if (env && env.length > 0) return
|
|
25044
|
+
if (env && env.length > 0) return import_node_path80.default.resolve(env);
|
|
24828
25045
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
24829
|
-
return
|
|
25046
|
+
return import_node_path80.default.join(home, ".neat");
|
|
24830
25047
|
}
|
|
24831
25048
|
function routeSpanToProject(serviceName, projects) {
|
|
24832
25049
|
if (!serviceName) return DEFAULT_PROJECT;
|
|
@@ -24878,9 +25095,9 @@ function spanBelongsToSingleProject(graph, project, serviceName) {
|
|
|
24878
25095
|
);
|
|
24879
25096
|
}
|
|
24880
25097
|
async function bootstrapProject(entry2, connectors = [], neatHome4) {
|
|
24881
|
-
const paths = pathsForProject(entry2.name,
|
|
25098
|
+
const paths = pathsForProject(entry2.name, import_node_path80.default.join(entry2.path, "neat-out"));
|
|
24882
25099
|
try {
|
|
24883
|
-
const stat = await
|
|
25100
|
+
const stat = await import_node_fs42.promises.stat(entry2.path);
|
|
24884
25101
|
if (!stat.isDirectory()) {
|
|
24885
25102
|
throw new Error(`registered path ${entry2.path} is not a directory`);
|
|
24886
25103
|
}
|
|
@@ -25032,7 +25249,7 @@ async function startDaemon(opts = {}) {
|
|
|
25032
25249
|
const projectArg = typeof opts.project === "string" && opts.project.length > 0 ? opts.project : process.env.NEAT_PROJECT && process.env.NEAT_PROJECT.length > 0 ? process.env.NEAT_PROJECT : null;
|
|
25033
25250
|
const projectPathArg = opts.projectPath && opts.projectPath.length > 0 ? opts.projectPath : process.env.NEAT_PROJECT_PATH && process.env.NEAT_PROJECT_PATH.length > 0 ? process.env.NEAT_PROJECT_PATH : null;
|
|
25034
25251
|
const singleProject = projectArg;
|
|
25035
|
-
const singleProjectPath = singleProject && projectPathArg ?
|
|
25252
|
+
const singleProjectPath = singleProject && projectPathArg ? import_node_path80.default.resolve(projectPathArg) : null;
|
|
25036
25253
|
if (singleProject && !singleProjectPath) {
|
|
25037
25254
|
throw new Error(
|
|
25038
25255
|
`neatd: project "${singleProject}" given without a projectPath; pass NEAT_PROJECT_PATH alongside NEAT_PROJECT.`
|
|
@@ -25040,14 +25257,14 @@ async function startDaemon(opts = {}) {
|
|
|
25040
25257
|
}
|
|
25041
25258
|
if (!singleProject) {
|
|
25042
25259
|
try {
|
|
25043
|
-
await
|
|
25260
|
+
await import_node_fs42.promises.access(regPath);
|
|
25044
25261
|
} catch {
|
|
25045
25262
|
throw new Error(
|
|
25046
25263
|
`neatd: registry not found at ${regPath}. Run \`neat init <path>\` to register a project before starting the daemon.`
|
|
25047
25264
|
);
|
|
25048
25265
|
}
|
|
25049
25266
|
}
|
|
25050
|
-
const pidPath =
|
|
25267
|
+
const pidPath = import_node_path80.default.join(home, "neatd.pid");
|
|
25051
25268
|
await writeAtomically(pidPath, `${process.pid}
|
|
25052
25269
|
`);
|
|
25053
25270
|
const slots = /* @__PURE__ */ new Map();
|
|
@@ -25259,7 +25476,7 @@ async function startDaemon(opts = {}) {
|
|
|
25259
25476
|
}
|
|
25260
25477
|
if (restApp) await restApp.close().catch(() => {
|
|
25261
25478
|
});
|
|
25262
|
-
await
|
|
25479
|
+
await import_node_fs42.promises.unlink(pidPath).catch(() => {
|
|
25263
25480
|
});
|
|
25264
25481
|
throw new Error(
|
|
25265
25482
|
`neatd: failed to bind REST on port ${restPort} \u2014 ${err.message}`
|
|
@@ -25437,7 +25654,7 @@ async function startDaemon(opts = {}) {
|
|
|
25437
25654
|
});
|
|
25438
25655
|
if (otlpApp) await otlpApp.close().catch(() => {
|
|
25439
25656
|
});
|
|
25440
|
-
await
|
|
25657
|
+
await import_node_fs42.promises.unlink(pidPath).catch(() => {
|
|
25441
25658
|
});
|
|
25442
25659
|
throw new Error(
|
|
25443
25660
|
`neatd: failed to bind OTLP on port ${otlpPort} \u2014 ${err.message}`
|
|
@@ -25472,7 +25689,7 @@ async function startDaemon(opts = {}) {
|
|
|
25472
25689
|
});
|
|
25473
25690
|
if (otlpApp) await otlpApp.close().catch(() => {
|
|
25474
25691
|
});
|
|
25475
|
-
await
|
|
25692
|
+
await import_node_fs42.promises.unlink(pidPath).catch(() => {
|
|
25476
25693
|
});
|
|
25477
25694
|
throw new Error(
|
|
25478
25695
|
`neatd: failed to write daemon.json for "${singleProject}" \u2014 ${err.message}`
|
|
@@ -25519,9 +25736,9 @@ async function startDaemon(opts = {}) {
|
|
|
25519
25736
|
let registryWatcher = null;
|
|
25520
25737
|
let reloadTimer = null;
|
|
25521
25738
|
if (!singleProject) try {
|
|
25522
|
-
const regDir =
|
|
25523
|
-
const regBase =
|
|
25524
|
-
registryWatcher = (0,
|
|
25739
|
+
const regDir = import_node_path80.default.dirname(regPath);
|
|
25740
|
+
const regBase = import_node_path80.default.basename(regPath);
|
|
25741
|
+
registryWatcher = (0, import_node_fs42.watch)(regDir, (_eventType, filename) => {
|
|
25525
25742
|
if (filename !== null && filename !== regBase) return;
|
|
25526
25743
|
if (reloadTimer) clearTimeout(reloadTimer);
|
|
25527
25744
|
reloadTimer = setTimeout(() => {
|
|
@@ -25570,7 +25787,7 @@ async function startDaemon(opts = {}) {
|
|
|
25570
25787
|
if (daemonRecord) {
|
|
25571
25788
|
await clearDaemonRecord(daemonRecord, home);
|
|
25572
25789
|
}
|
|
25573
|
-
await
|
|
25790
|
+
await import_node_fs42.promises.unlink(pidPath).catch(() => {
|
|
25574
25791
|
});
|
|
25575
25792
|
};
|
|
25576
25793
|
return {
|
|
@@ -25593,9 +25810,9 @@ init_auth();
|
|
|
25593
25810
|
// src/web-spawn.ts
|
|
25594
25811
|
init_cjs_shims();
|
|
25595
25812
|
var import_node_child_process2 = require("child_process");
|
|
25596
|
-
var
|
|
25813
|
+
var import_node_fs43 = require("fs");
|
|
25597
25814
|
var import_node_net = __toESM(require("net"), 1);
|
|
25598
|
-
var
|
|
25815
|
+
var import_node_path81 = __toESM(require("path"), 1);
|
|
25599
25816
|
var DEFAULT_WEB_PORT = 6328;
|
|
25600
25817
|
var DEFAULT_REST_PORT = 8080;
|
|
25601
25818
|
function asValidPort(value) {
|
|
@@ -25604,11 +25821,11 @@ function asValidPort(value) {
|
|
|
25604
25821
|
}
|
|
25605
25822
|
function projectRoot() {
|
|
25606
25823
|
const fromEnv = process.env.NEAT_SCAN_PATH;
|
|
25607
|
-
return
|
|
25824
|
+
return import_node_path81.default.resolve(fromEnv && fromEnv.length > 0 ? fromEnv : process.cwd());
|
|
25608
25825
|
}
|
|
25609
25826
|
async function readDaemonPorts(root) {
|
|
25610
25827
|
try {
|
|
25611
|
-
const raw = await
|
|
25828
|
+
const raw = await import_node_fs43.promises.readFile(import_node_path81.default.join(root, "neat-out", "daemon.json"), "utf8");
|
|
25612
25829
|
const parsed = JSON.parse(raw);
|
|
25613
25830
|
const ports = parsed?.ports ?? {};
|
|
25614
25831
|
return { web: asValidPort(ports.web), rest: asValidPort(ports.rest) };
|
|
@@ -25653,10 +25870,10 @@ function resolveWebPackageDir() {
|
|
|
25653
25870
|
eval("require")
|
|
25654
25871
|
);
|
|
25655
25872
|
const pkgJsonPath = req.resolve("@neat.is/web/package.json");
|
|
25656
|
-
return
|
|
25873
|
+
return import_node_path81.default.dirname(pkgJsonPath);
|
|
25657
25874
|
}
|
|
25658
25875
|
function resolveStandaloneServerEntry(webDir) {
|
|
25659
|
-
return
|
|
25876
|
+
return import_node_path81.default.join(webDir, ".next/standalone/packages/web/server.js");
|
|
25660
25877
|
}
|
|
25661
25878
|
async function pickInternalPort() {
|
|
25662
25879
|
return new Promise((resolve, reject) => {
|
|
@@ -25709,7 +25926,7 @@ async function spawnWebUI(restPort, opts = {}) {
|
|
|
25709
25926
|
NEAT_API_URL: apiUrl
|
|
25710
25927
|
};
|
|
25711
25928
|
child = (0, import_node_child_process2.spawn)(process.execPath, [serverEntry], {
|
|
25712
|
-
cwd:
|
|
25929
|
+
cwd: import_node_path81.default.dirname(serverEntry),
|
|
25713
25930
|
env,
|
|
25714
25931
|
stdio: ["ignore", "inherit", "inherit"],
|
|
25715
25932
|
detached: false
|
|
@@ -25885,14 +26102,14 @@ function localVersion() {
|
|
|
25885
26102
|
}
|
|
25886
26103
|
function neatHome3() {
|
|
25887
26104
|
if (process.env.NEAT_HOME && process.env.NEAT_HOME.length > 0) {
|
|
25888
|
-
return
|
|
26105
|
+
return import_node_path82.default.resolve(process.env.NEAT_HOME);
|
|
25889
26106
|
}
|
|
25890
26107
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
25891
|
-
return
|
|
26108
|
+
return import_node_path82.default.join(home, ".neat");
|
|
25892
26109
|
}
|
|
25893
26110
|
async function readPid() {
|
|
25894
26111
|
try {
|
|
25895
|
-
const raw = await
|
|
26112
|
+
const raw = await import_node_fs44.promises.readFile(import_node_path82.default.join(neatHome3(), "neatd.pid"), "utf8");
|
|
25896
26113
|
const n = Number.parseInt(raw.trim(), 10);
|
|
25897
26114
|
return Number.isFinite(n) ? n : null;
|
|
25898
26115
|
} catch {
|