@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/server.cjs
CHANGED
|
@@ -59,8 +59,8 @@ function mountBearerAuth(app, opts) {
|
|
|
59
59
|
]);
|
|
60
60
|
const publicRead = opts.publicRead === true;
|
|
61
61
|
app.addHook("preHandler", (req, reply, done) => {
|
|
62
|
-
const
|
|
63
|
-
if (exactUnauthPaths.has(
|
|
62
|
+
const path78 = (req.url.split("?")[0] ?? "").replace(/\/+$/, "");
|
|
63
|
+
if (exactUnauthPaths.has(path78) || PROJECT_SCOPED_UNAUTH_PATTERN.test(path78)) {
|
|
64
64
|
done();
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
@@ -192,8 +192,8 @@ function reshapeGrpcRequest(req) {
|
|
|
192
192
|
};
|
|
193
193
|
}
|
|
194
194
|
function resolveProtoRoot() {
|
|
195
|
-
const here =
|
|
196
|
-
return
|
|
195
|
+
const here = import_node_path56.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
196
|
+
return import_node_path56.default.resolve(here, "..", "proto");
|
|
197
197
|
}
|
|
198
198
|
function loadTraceService() {
|
|
199
199
|
const protoRoot = resolveProtoRoot();
|
|
@@ -261,13 +261,13 @@ async function startOtelGrpcReceiver(opts) {
|
|
|
261
261
|
})
|
|
262
262
|
};
|
|
263
263
|
}
|
|
264
|
-
var import_node_url,
|
|
264
|
+
var import_node_url, import_node_path56, import_node_crypto2, grpc, protoLoader;
|
|
265
265
|
var init_otel_grpc = __esm({
|
|
266
266
|
"src/otel-grpc.ts"() {
|
|
267
267
|
"use strict";
|
|
268
268
|
init_cjs_shims();
|
|
269
269
|
import_node_url = require("url");
|
|
270
|
-
|
|
270
|
+
import_node_path56 = __toESM(require("path"), 1);
|
|
271
271
|
import_node_crypto2 = require("crypto");
|
|
272
272
|
grpc = __toESM(require("@grpc/grpc-js"), 1);
|
|
273
273
|
protoLoader = __toESM(require("@grpc/proto-loader"), 1);
|
|
@@ -413,8 +413,8 @@ function websocketChannelPathOf(attrs) {
|
|
|
413
413
|
const v = attrs[key];
|
|
414
414
|
if (typeof v === "string" && v.length > 0) {
|
|
415
415
|
const q = v.indexOf("?");
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
416
|
+
const path78 = q === -1 ? v : v.slice(0, q);
|
|
417
|
+
if (path78.length > 0) return path78;
|
|
418
418
|
}
|
|
419
419
|
}
|
|
420
420
|
return void 0;
|
|
@@ -476,10 +476,10 @@ function parseOtlpRequest(body) {
|
|
|
476
476
|
return out;
|
|
477
477
|
}
|
|
478
478
|
function loadProtoRoot() {
|
|
479
|
-
const here =
|
|
480
|
-
const protoRoot =
|
|
479
|
+
const here = import_node_path57.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
480
|
+
const protoRoot = import_node_path57.default.resolve(here, "..", "proto");
|
|
481
481
|
const root = new import_protobufjs.default.Root();
|
|
482
|
-
root.resolvePath = (_origin, target) =>
|
|
482
|
+
root.resolvePath = (_origin, target) => import_node_path57.default.resolve(protoRoot, target);
|
|
483
483
|
root.loadSync(
|
|
484
484
|
"opentelemetry/proto/collector/trace/v1/trace_service.proto",
|
|
485
485
|
{ keepCase: true }
|
|
@@ -741,12 +741,12 @@ async function buildOtelReceiver(opts) {
|
|
|
741
741
|
};
|
|
742
742
|
return decorated;
|
|
743
743
|
}
|
|
744
|
-
var
|
|
744
|
+
var import_node_path57, import_node_url2, import_node_zlib, import_fastify, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody;
|
|
745
745
|
var init_otel = __esm({
|
|
746
746
|
"src/otel.ts"() {
|
|
747
747
|
"use strict";
|
|
748
748
|
init_cjs_shims();
|
|
749
|
-
|
|
749
|
+
import_node_path57 = __toESM(require("path"), 1);
|
|
750
750
|
import_node_url2 = require("url");
|
|
751
751
|
import_node_zlib = __toESM(require("zlib"), 1);
|
|
752
752
|
import_fastify = __toESM(require("fastify"), 1);
|
|
@@ -763,7 +763,7 @@ var init_otel = __esm({
|
|
|
763
763
|
|
|
764
764
|
// src/server.ts
|
|
765
765
|
init_cjs_shims();
|
|
766
|
-
var
|
|
766
|
+
var import_node_path77 = __toESM(require("path"), 1);
|
|
767
767
|
|
|
768
768
|
// src/graph.ts
|
|
769
769
|
init_cjs_shims();
|
|
@@ -1505,8 +1505,8 @@ init_cjs_shims();
|
|
|
1505
1505
|
|
|
1506
1506
|
// src/ingest.ts
|
|
1507
1507
|
init_cjs_shims();
|
|
1508
|
-
var
|
|
1509
|
-
var
|
|
1508
|
+
var import_node_fs10 = require("fs");
|
|
1509
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
1510
1510
|
var sourceMapJs = __toESM(require("source-map-js"), 1);
|
|
1511
1511
|
|
|
1512
1512
|
// src/policy.ts
|
|
@@ -2032,7 +2032,7 @@ var import_types7 = require("@neat.is/types");
|
|
|
2032
2032
|
|
|
2033
2033
|
// src/extract/routes.ts
|
|
2034
2034
|
init_cjs_shims();
|
|
2035
|
-
var
|
|
2035
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
2036
2036
|
var import_tree_sitter2 = __toESM(require("tree-sitter"), 1);
|
|
2037
2037
|
var import_tree_sitter_javascript2 = __toESM(require("tree-sitter-javascript"), 1);
|
|
2038
2038
|
var import_tree_sitter_python2 = __toESM(require("tree-sitter-python"), 1);
|
|
@@ -2058,6 +2058,17 @@ var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
|
2058
2058
|
"dist",
|
|
2059
2059
|
"build",
|
|
2060
2060
|
".next",
|
|
2061
|
+
// `_next` is the *emitted* half of the pair above — `next build`'s output as
|
|
2062
|
+
// it is served or exported. `.next` was listed and `_next` wasn't, so an
|
|
2063
|
+
// exported bundle walked in as first-party source: minified chunks, one file
|
|
2064
|
+
// per line, hundreds of KB each (#1254).
|
|
2065
|
+
"_next",
|
|
2066
|
+
// Agent scratch space. `.claude/worktrees/` holds a full checkout per agent
|
|
2067
|
+
// session, so walking it re-extracts the whole repo once per worktree — and
|
|
2068
|
+
// pulls in whatever build output those checkouts happen to carry. It is
|
|
2069
|
+
// gitignored in practice, but the file walk doesn't read .gitignore, so the
|
|
2070
|
+
// name has to be listed here.
|
|
2071
|
+
".claude",
|
|
2061
2072
|
// Python virtualenv shapes (issue #344). Walking into a venv pulls in the
|
|
2062
2073
|
// entire CPython stdlib + every installed package as if it were first-party
|
|
2063
2074
|
// service code — 20k+ files, none of which the user wrote. The shape names
|
|
@@ -2289,6 +2300,15 @@ function noteExtractedDropped(edge) {
|
|
|
2289
2300
|
function drainDroppedExtracted() {
|
|
2290
2301
|
return droppedSink.splice(0, droppedSink.length);
|
|
2291
2302
|
}
|
|
2303
|
+
var skippedSink = /* @__PURE__ */ new Map();
|
|
2304
|
+
function noteSkippedFile(file) {
|
|
2305
|
+
if (!skippedSink.has(file.path)) skippedSink.set(file.path, file);
|
|
2306
|
+
}
|
|
2307
|
+
function drainSkippedFiles() {
|
|
2308
|
+
const out = [...skippedSink.values()];
|
|
2309
|
+
skippedSink.clear();
|
|
2310
|
+
return out;
|
|
2311
|
+
}
|
|
2292
2312
|
function isRejectedLogEnabled() {
|
|
2293
2313
|
const raw = process.env.NEAT_EXTRACTED_REJECTED_LOG;
|
|
2294
2314
|
return raw === "1" || raw === "true";
|
|
@@ -2302,14 +2322,91 @@ async function writeRejectedExtracted(drops, rejectedPath) {
|
|
|
2302
2322
|
|
|
2303
2323
|
// src/extract/calls/shared.ts
|
|
2304
2324
|
init_cjs_shims();
|
|
2325
|
+
var import_node_fs8 = require("fs");
|
|
2326
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
2327
|
+
var import_types4 = require("@neat.is/types");
|
|
2328
|
+
|
|
2329
|
+
// src/extract/gitignore.ts
|
|
2330
|
+
init_cjs_shims();
|
|
2305
2331
|
var import_node_fs7 = require("fs");
|
|
2306
2332
|
var import_node_path7 = __toESM(require("path"), 1);
|
|
2307
|
-
var
|
|
2333
|
+
var import_ignore = __toESM(require("ignore"), 1);
|
|
2334
|
+
var LAYER_CACHE = /* @__PURE__ */ new Map();
|
|
2335
|
+
async function layerFor(dir) {
|
|
2336
|
+
const cached = LAYER_CACHE.get(dir);
|
|
2337
|
+
if (cached !== void 0) return cached;
|
|
2338
|
+
let layer = null;
|
|
2339
|
+
try {
|
|
2340
|
+
const raw = await import_node_fs7.promises.readFile(import_node_path7.default.join(dir, ".gitignore"), "utf8");
|
|
2341
|
+
layer = { dir, ig: (0, import_ignore.default)().add(raw) };
|
|
2342
|
+
} catch {
|
|
2343
|
+
layer = null;
|
|
2344
|
+
}
|
|
2345
|
+
LAYER_CACHE.set(dir, layer);
|
|
2346
|
+
return layer;
|
|
2347
|
+
}
|
|
2348
|
+
async function isRepoRoot(dir) {
|
|
2349
|
+
try {
|
|
2350
|
+
await import_node_fs7.promises.stat(import_node_path7.default.join(dir, ".git"));
|
|
2351
|
+
return true;
|
|
2352
|
+
} catch {
|
|
2353
|
+
return false;
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
async function loadIgnoreChain(startDir) {
|
|
2357
|
+
const dirs = [];
|
|
2358
|
+
let current = import_node_path7.default.resolve(startDir);
|
|
2359
|
+
for (; ; ) {
|
|
2360
|
+
dirs.push(current);
|
|
2361
|
+
if (await isRepoRoot(current)) break;
|
|
2362
|
+
const parent = import_node_path7.default.dirname(current);
|
|
2363
|
+
if (parent === current) break;
|
|
2364
|
+
current = parent;
|
|
2365
|
+
}
|
|
2366
|
+
dirs.reverse();
|
|
2367
|
+
const layers = [];
|
|
2368
|
+
for (const dir of dirs) {
|
|
2369
|
+
const layer = await layerFor(dir);
|
|
2370
|
+
if (layer) layers.push(layer);
|
|
2371
|
+
}
|
|
2372
|
+
return layers;
|
|
2373
|
+
}
|
|
2374
|
+
async function extendIgnoreChain(chain, dir) {
|
|
2375
|
+
const layer = await layerFor(import_node_path7.default.resolve(dir));
|
|
2376
|
+
return layer ? [...chain, layer] : chain;
|
|
2377
|
+
}
|
|
2378
|
+
function isIgnored(chain, fullPath, isDir) {
|
|
2379
|
+
return decide(chain, fullPath, isDir).ignored;
|
|
2380
|
+
}
|
|
2381
|
+
function decide(chain, fullPath, isDir) {
|
|
2382
|
+
if (chain.length === 0) return { ignored: false, subtree: chain };
|
|
2383
|
+
const abs = import_node_path7.default.resolve(fullPath);
|
|
2384
|
+
let ignored = false;
|
|
2385
|
+
let unignoredAt = -1;
|
|
2386
|
+
for (let i = 0; i < chain.length; i++) {
|
|
2387
|
+
const layer = chain[i];
|
|
2388
|
+
const rel = import_node_path7.default.relative(layer.dir, abs);
|
|
2389
|
+
if (!rel || rel.startsWith("..") || import_node_path7.default.isAbsolute(rel)) continue;
|
|
2390
|
+
const candidate = rel.split(import_node_path7.default.sep).join("/") + (isDir ? "/" : "");
|
|
2391
|
+
const result = layer.ig.test(candidate);
|
|
2392
|
+
if (result.ignored) ignored = true;
|
|
2393
|
+
else if (result.unignored) {
|
|
2394
|
+
ignored = false;
|
|
2395
|
+
unignoredAt = i;
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
return {
|
|
2399
|
+
ignored,
|
|
2400
|
+
subtree: unignoredAt >= 0 ? chain.slice(unignoredAt) : chain
|
|
2401
|
+
};
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
// src/extract/calls/shared.ts
|
|
2308
2405
|
function buildServiceHostIndex(services) {
|
|
2309
2406
|
const knownHosts = /* @__PURE__ */ new Set();
|
|
2310
2407
|
const hostToNodeId = /* @__PURE__ */ new Map();
|
|
2311
2408
|
for (const service of services) {
|
|
2312
|
-
const base =
|
|
2409
|
+
const base = import_node_path8.default.basename(service.dir);
|
|
2313
2410
|
knownHosts.add(base);
|
|
2314
2411
|
knownHosts.add(service.pkg.name);
|
|
2315
2412
|
hostToNodeId.set(base, service.node.id);
|
|
@@ -2318,33 +2415,62 @@ function buildServiceHostIndex(services) {
|
|
|
2318
2415
|
return { knownHosts, hostToNodeId };
|
|
2319
2416
|
}
|
|
2320
2417
|
async function walkSourceFiles(dir, excludeDirs = []) {
|
|
2321
|
-
const excluded = new Set(excludeDirs.map((d) =>
|
|
2418
|
+
const excluded = new Set(excludeDirs.map((d) => import_node_path8.default.resolve(d)));
|
|
2322
2419
|
const out = [];
|
|
2323
|
-
|
|
2324
|
-
|
|
2420
|
+
const rootChain = await loadIgnoreChain(dir);
|
|
2421
|
+
async function walk11(current, inherited) {
|
|
2422
|
+
const entries = await import_node_fs8.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
2423
|
+
const chain = entries.some((e) => e.isFile() && e.name === ".gitignore") ? await extendIgnoreChain(inherited, current) : inherited;
|
|
2325
2424
|
for (const entry of entries) {
|
|
2326
|
-
const full =
|
|
2425
|
+
const full = import_node_path8.default.join(current, entry.name);
|
|
2327
2426
|
if (entry.isDirectory()) {
|
|
2328
2427
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
2329
|
-
if (excluded.has(
|
|
2428
|
+
if (excluded.has(import_node_path8.default.resolve(full))) continue;
|
|
2429
|
+
const verdict = decide(chain, full, true);
|
|
2430
|
+
if (verdict.ignored) continue;
|
|
2330
2431
|
if (await isPythonVenvDir(full)) continue;
|
|
2331
|
-
await walk11(full);
|
|
2332
|
-
} else if (entry.isFile() && SERVICE_FILE_EXTENSIONS.has(
|
|
2432
|
+
await walk11(full, verdict.subtree);
|
|
2433
|
+
} else if (entry.isFile() && SERVICE_FILE_EXTENSIONS.has(import_node_path8.default.extname(entry.name)) && // Skip NEAT's own generated `otel-init.*` bootstrap — extracting it
|
|
2333
2434
|
// would attribute our instrumentation imports to the user's service.
|
|
2334
|
-
!isNeatAuthoredSourceFile(entry.name)) {
|
|
2435
|
+
!isNeatAuthoredSourceFile(entry.name) && !isIgnored(chain, full, false)) {
|
|
2335
2436
|
out.push(full);
|
|
2336
2437
|
}
|
|
2337
2438
|
}
|
|
2338
2439
|
}
|
|
2339
|
-
await walk11(dir);
|
|
2440
|
+
await walk11(dir, rootChain.filter((l) => import_node_path8.default.resolve(l.dir) !== import_node_path8.default.resolve(dir)));
|
|
2340
2441
|
return out;
|
|
2341
2442
|
}
|
|
2443
|
+
var MINIFIED_LINE_CHARS = 5e3;
|
|
2444
|
+
function hasMinifiedName(filePath) {
|
|
2445
|
+
return /\.min\.(js|mjs|cjs|jsx|ts|tsx)$/i.test(filePath);
|
|
2446
|
+
}
|
|
2447
|
+
function isMinifiedSource(filePath, content) {
|
|
2448
|
+
if (hasMinifiedName(filePath)) return { minified: true, detail: "named *.min.js" };
|
|
2449
|
+
let longest = 0;
|
|
2450
|
+
let start = 0;
|
|
2451
|
+
for (; ; ) {
|
|
2452
|
+
const nl = content.indexOf("\n", start);
|
|
2453
|
+
const len = (nl === -1 ? content.length : nl) - start;
|
|
2454
|
+
if (len > longest) longest = len;
|
|
2455
|
+
if (nl === -1) break;
|
|
2456
|
+
start = nl + 1;
|
|
2457
|
+
}
|
|
2458
|
+
if (longest > MINIFIED_LINE_CHARS) {
|
|
2459
|
+
return { minified: true, detail: `longest line ${longest} chars` };
|
|
2460
|
+
}
|
|
2461
|
+
return { minified: false, detail: "" };
|
|
2462
|
+
}
|
|
2342
2463
|
async function loadSourceFiles(dir, excludeDirs = []) {
|
|
2343
2464
|
const paths = await walkSourceFiles(dir, excludeDirs);
|
|
2344
2465
|
const out = [];
|
|
2345
2466
|
for (const p of paths) {
|
|
2346
2467
|
try {
|
|
2347
|
-
const content = await
|
|
2468
|
+
const content = await import_node_fs8.promises.readFile(p, "utf8");
|
|
2469
|
+
const verdict = isMinifiedSource(p, content);
|
|
2470
|
+
if (verdict.minified) {
|
|
2471
|
+
noteSkippedFile({ path: p, reason: "minified", detail: verdict.detail });
|
|
2472
|
+
continue;
|
|
2473
|
+
}
|
|
2348
2474
|
out.push({ path: p, content });
|
|
2349
2475
|
} catch {
|
|
2350
2476
|
}
|
|
@@ -2356,15 +2482,18 @@ function lineOf(text, needle) {
|
|
|
2356
2482
|
if (idx < 0) return 1;
|
|
2357
2483
|
return text.slice(0, idx).split("\n").length;
|
|
2358
2484
|
}
|
|
2485
|
+
var SNIPPET_MAX_CHARS = 120;
|
|
2359
2486
|
function snippet(text, line) {
|
|
2360
2487
|
const lines = text.split("\n");
|
|
2361
|
-
|
|
2488
|
+
const raw = (lines[line - 1] ?? "").trim();
|
|
2489
|
+
if (raw.length <= SNIPPET_MAX_CHARS) return raw;
|
|
2490
|
+
return `${raw.slice(0, SNIPPET_MAX_CHARS)}\u2026 (+${raw.length - SNIPPET_MAX_CHARS} chars)`;
|
|
2362
2491
|
}
|
|
2363
2492
|
function toPosix(p) {
|
|
2364
2493
|
return p.split("\\").join("/");
|
|
2365
2494
|
}
|
|
2366
2495
|
function languageForPath(relPath) {
|
|
2367
|
-
switch (
|
|
2496
|
+
switch (import_node_path8.default.extname(relPath).toLowerCase()) {
|
|
2368
2497
|
case ".py":
|
|
2369
2498
|
return "python";
|
|
2370
2499
|
case ".go":
|
|
@@ -2438,8 +2567,8 @@ function ensureFileNode(graph, serviceName, serviceNodeId, relPath) {
|
|
|
2438
2567
|
|
|
2439
2568
|
// src/extract/imports.ts
|
|
2440
2569
|
init_cjs_shims();
|
|
2441
|
-
var
|
|
2442
|
-
var
|
|
2570
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
2571
|
+
var import_node_fs9 = require("fs");
|
|
2443
2572
|
var import_tree_sitter = __toESM(require("tree-sitter"), 1);
|
|
2444
2573
|
var import_tree_sitter_javascript = __toESM(require("tree-sitter-javascript"), 1);
|
|
2445
2574
|
var import_tree_sitter_python = __toESM(require("tree-sitter-python"), 1);
|
|
@@ -2584,15 +2713,15 @@ function collectPyImports(node, out) {
|
|
|
2584
2713
|
}
|
|
2585
2714
|
async function fileExists2(p) {
|
|
2586
2715
|
try {
|
|
2587
|
-
await
|
|
2716
|
+
await import_node_fs9.promises.access(p);
|
|
2588
2717
|
return true;
|
|
2589
2718
|
} catch {
|
|
2590
2719
|
return false;
|
|
2591
2720
|
}
|
|
2592
2721
|
}
|
|
2593
2722
|
function isWithinServiceDir(candidate, serviceDir) {
|
|
2594
|
-
const rel =
|
|
2595
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
2723
|
+
const rel = import_node_path9.default.relative(serviceDir, candidate);
|
|
2724
|
+
return rel !== "" && !rel.startsWith("..") && !import_node_path9.default.isAbsolute(rel);
|
|
2596
2725
|
}
|
|
2597
2726
|
var JS_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
2598
2727
|
var JS_INDEX_FILES = JS_EXTENSIONS.map((ext) => `index${ext}`);
|
|
@@ -2600,22 +2729,22 @@ async function firstExistingCandidate(base, serviceDir) {
|
|
|
2600
2729
|
for (const ext of JS_EXTENSIONS) {
|
|
2601
2730
|
const candidate = base + ext;
|
|
2602
2731
|
if (isWithinServiceDir(candidate, serviceDir) && await fileExists2(candidate)) {
|
|
2603
|
-
return toPosix(
|
|
2732
|
+
return toPosix(import_node_path9.default.relative(serviceDir, candidate));
|
|
2604
2733
|
}
|
|
2605
2734
|
}
|
|
2606
2735
|
for (const indexFile of JS_INDEX_FILES) {
|
|
2607
|
-
const candidate =
|
|
2736
|
+
const candidate = import_node_path9.default.join(base, indexFile);
|
|
2608
2737
|
if (isWithinServiceDir(candidate, serviceDir) && await fileExists2(candidate)) {
|
|
2609
|
-
return toPosix(
|
|
2738
|
+
return toPosix(import_node_path9.default.relative(serviceDir, candidate));
|
|
2610
2739
|
}
|
|
2611
2740
|
}
|
|
2612
2741
|
return null;
|
|
2613
2742
|
}
|
|
2614
2743
|
async function loadTsPathConfig(serviceDir) {
|
|
2615
|
-
const tsconfigPath =
|
|
2744
|
+
const tsconfigPath = import_node_path9.default.join(serviceDir, "tsconfig.json");
|
|
2616
2745
|
let raw;
|
|
2617
2746
|
try {
|
|
2618
|
-
raw = await
|
|
2747
|
+
raw = await import_node_fs9.promises.readFile(tsconfigPath, "utf8");
|
|
2619
2748
|
} catch {
|
|
2620
2749
|
return null;
|
|
2621
2750
|
}
|
|
@@ -2624,7 +2753,7 @@ async function loadTsPathConfig(serviceDir) {
|
|
|
2624
2753
|
const paths = parsed.compilerOptions?.paths;
|
|
2625
2754
|
if (!paths || Object.keys(paths).length === 0) return null;
|
|
2626
2755
|
const baseUrl = parsed.compilerOptions?.baseUrl;
|
|
2627
|
-
return { paths, baseDir: baseUrl ?
|
|
2756
|
+
return { paths, baseDir: baseUrl ? import_node_path9.default.resolve(serviceDir, baseUrl) : serviceDir };
|
|
2628
2757
|
} catch (err) {
|
|
2629
2758
|
recordExtractionError("import alias resolution", tsconfigPath, err);
|
|
2630
2759
|
return null;
|
|
@@ -2642,11 +2771,11 @@ async function resolveTsAlias(specifier, config, serviceDir) {
|
|
|
2642
2771
|
if (suffix === null) continue;
|
|
2643
2772
|
for (const target of targets) {
|
|
2644
2773
|
const targetBase = target.endsWith("/*") ? target.slice(0, -2) : target.replace(/\*$/, "");
|
|
2645
|
-
const resolvedBase =
|
|
2774
|
+
const resolvedBase = import_node_path9.default.resolve(config.baseDir, targetBase, suffix);
|
|
2646
2775
|
const hit = await firstExistingCandidate(resolvedBase, serviceDir);
|
|
2647
2776
|
if (hit) return hit;
|
|
2648
2777
|
if (isWithinServiceDir(resolvedBase, serviceDir) && await fileExists2(resolvedBase)) {
|
|
2649
|
-
return toPosix(
|
|
2778
|
+
return toPosix(import_node_path9.default.relative(serviceDir, resolvedBase));
|
|
2650
2779
|
}
|
|
2651
2780
|
}
|
|
2652
2781
|
}
|
|
@@ -2655,18 +2784,18 @@ async function resolveTsAlias(specifier, config, serviceDir) {
|
|
|
2655
2784
|
async function resolveJsImport(specifier, importerDir, serviceDir, tsPaths) {
|
|
2656
2785
|
if (!specifier) return null;
|
|
2657
2786
|
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
2658
|
-
const base =
|
|
2659
|
-
const ext =
|
|
2787
|
+
const base = import_node_path9.default.resolve(importerDir, specifier);
|
|
2788
|
+
const ext = import_node_path9.default.extname(specifier);
|
|
2660
2789
|
if (ext) {
|
|
2661
2790
|
if (ext === ".js" || ext === ".jsx") {
|
|
2662
2791
|
const tsExt = ext === ".jsx" ? ".tsx" : ".ts";
|
|
2663
2792
|
const tsSibling = base.slice(0, -ext.length) + tsExt;
|
|
2664
2793
|
if (isWithinServiceDir(tsSibling, serviceDir) && await fileExists2(tsSibling)) {
|
|
2665
|
-
return toPosix(
|
|
2794
|
+
return toPosix(import_node_path9.default.relative(serviceDir, tsSibling));
|
|
2666
2795
|
}
|
|
2667
2796
|
}
|
|
2668
2797
|
if (isWithinServiceDir(base, serviceDir) && await fileExists2(base)) {
|
|
2669
|
-
return toPosix(
|
|
2798
|
+
return toPosix(import_node_path9.default.relative(serviceDir, base));
|
|
2670
2799
|
}
|
|
2671
2800
|
if (!JS_EXTENSIONS.includes(ext)) {
|
|
2672
2801
|
return firstExistingCandidate(base, serviceDir);
|
|
@@ -2681,30 +2810,30 @@ async function resolveJsImport(specifier, importerDir, serviceDir, tsPaths) {
|
|
|
2681
2810
|
async function resolvePyImport(imp, importerPath, serviceDir) {
|
|
2682
2811
|
let baseDir;
|
|
2683
2812
|
if (imp.level > 0) {
|
|
2684
|
-
baseDir =
|
|
2685
|
-
for (let i = 1; i < imp.level; i++) baseDir =
|
|
2813
|
+
baseDir = import_node_path9.default.dirname(importerPath);
|
|
2814
|
+
for (let i = 1; i < imp.level; i++) baseDir = import_node_path9.default.dirname(baseDir);
|
|
2686
2815
|
} else {
|
|
2687
2816
|
baseDir = serviceDir;
|
|
2688
2817
|
}
|
|
2689
|
-
const moduleBase = imp.modulePath ?
|
|
2818
|
+
const moduleBase = imp.modulePath ? import_node_path9.default.join(baseDir, imp.modulePath.split(".").join("/")) : baseDir;
|
|
2690
2819
|
const resolved = /* @__PURE__ */ new Set();
|
|
2691
2820
|
let needModuleFile = imp.names.length === 0;
|
|
2692
2821
|
for (const name of imp.names) {
|
|
2693
|
-
const submoduleFile =
|
|
2694
|
-
const subpackageInit =
|
|
2822
|
+
const submoduleFile = import_node_path9.default.join(moduleBase, `${name}.py`);
|
|
2823
|
+
const subpackageInit = import_node_path9.default.join(moduleBase, name, "__init__.py");
|
|
2695
2824
|
if (isWithinServiceDir(submoduleFile, serviceDir) && await fileExists2(submoduleFile)) {
|
|
2696
|
-
resolved.add(toPosix(
|
|
2825
|
+
resolved.add(toPosix(import_node_path9.default.relative(serviceDir, submoduleFile)));
|
|
2697
2826
|
} else if (isWithinServiceDir(subpackageInit, serviceDir) && await fileExists2(subpackageInit)) {
|
|
2698
|
-
resolved.add(toPosix(
|
|
2827
|
+
resolved.add(toPosix(import_node_path9.default.relative(serviceDir, subpackageInit)));
|
|
2699
2828
|
} else {
|
|
2700
2829
|
needModuleFile = true;
|
|
2701
2830
|
}
|
|
2702
2831
|
}
|
|
2703
2832
|
if (needModuleFile) {
|
|
2704
|
-
const moduleFileCandidates = imp.modulePath ? [`${moduleBase}.py`,
|
|
2833
|
+
const moduleFileCandidates = imp.modulePath ? [`${moduleBase}.py`, import_node_path9.default.join(moduleBase, "__init__.py")] : [import_node_path9.default.join(moduleBase, "__init__.py")];
|
|
2705
2834
|
for (const candidate of moduleFileCandidates) {
|
|
2706
2835
|
if (isWithinServiceDir(candidate, serviceDir) && await fileExists2(candidate)) {
|
|
2707
|
-
resolved.add(toPosix(
|
|
2836
|
+
resolved.add(toPosix(import_node_path9.default.relative(serviceDir, candidate)));
|
|
2708
2837
|
break;
|
|
2709
2838
|
}
|
|
2710
2839
|
}
|
|
@@ -2714,11 +2843,11 @@ async function resolvePyImport(imp, importerPath, serviceDir) {
|
|
|
2714
2843
|
async function resolveGoImport(specifier, modulePath, serviceDir) {
|
|
2715
2844
|
if (specifier !== modulePath && !specifier.startsWith(`${modulePath}/`)) return null;
|
|
2716
2845
|
const suffix = specifier === modulePath ? "" : specifier.slice(modulePath.length + 1);
|
|
2717
|
-
const dir =
|
|
2718
|
-
const entries = await
|
|
2719
|
-
const candidates = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".go") && !entry.name.endsWith("_test.go")).map((entry) =>
|
|
2846
|
+
const dir = import_node_path9.default.join(serviceDir, suffix);
|
|
2847
|
+
const entries = await import_node_fs9.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
2848
|
+
const candidates = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".go") && !entry.name.endsWith("_test.go")).map((entry) => import_node_path9.default.join(dir, entry.name));
|
|
2720
2849
|
if (candidates.length !== 1) return null;
|
|
2721
|
-
return toPosix(
|
|
2850
|
+
return toPosix(import_node_path9.default.relative(serviceDir, candidates[0]));
|
|
2722
2851
|
}
|
|
2723
2852
|
function emitImportEdge(graph, serviceName, importerFileId, importerRelPath, importeeRelPath, line, snippet2) {
|
|
2724
2853
|
const importeeFileId = (0, import_types5.fileId)(serviceName, importeeRelPath);
|
|
@@ -2748,12 +2877,12 @@ async function addImports(graph, services) {
|
|
|
2748
2877
|
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
2749
2878
|
for (const file of files) {
|
|
2750
2879
|
if (isTestPath(file.path)) continue;
|
|
2751
|
-
const relFile = toPosix(
|
|
2880
|
+
const relFile = toPosix(import_node_path9.default.relative(service.dir, file.path));
|
|
2752
2881
|
const importerFileId = (0, import_types5.fileId)(service.pkg.name, relFile);
|
|
2753
|
-
const isPython =
|
|
2754
|
-
const isGo =
|
|
2755
|
-
if (
|
|
2756
|
-
if (
|
|
2882
|
+
const isPython = import_node_path9.default.extname(file.path) === ".py";
|
|
2883
|
+
const isGo = import_node_path9.default.extname(file.path) === ".go";
|
|
2884
|
+
if (import_node_path9.default.extname(file.path) === ".rb") continue;
|
|
2885
|
+
if (import_node_path9.default.extname(file.path) === ".php") continue;
|
|
2757
2886
|
if (isGo) {
|
|
2758
2887
|
let goImports = [];
|
|
2759
2888
|
try {
|
|
@@ -2763,7 +2892,7 @@ async function addImports(graph, services) {
|
|
|
2763
2892
|
recordExtractionError("import extraction", file.path, err);
|
|
2764
2893
|
continue;
|
|
2765
2894
|
}
|
|
2766
|
-
const goMod = await
|
|
2895
|
+
const goMod = await import_node_fs9.promises.readFile(import_node_path9.default.join(service.dir, "go.mod"), "utf8").catch(() => "");
|
|
2767
2896
|
const modulePath = goMod.match(/^\s*module\s+(\S+)\s*$/m)?.[1];
|
|
2768
2897
|
if (!modulePath) continue;
|
|
2769
2898
|
for (const imp of goImports) {
|
|
@@ -2807,7 +2936,7 @@ async function addImports(graph, services) {
|
|
|
2807
2936
|
continue;
|
|
2808
2937
|
}
|
|
2809
2938
|
for (const imp of jsImports) {
|
|
2810
|
-
const resolved = await resolveJsImport(imp.specifier,
|
|
2939
|
+
const resolved = await resolveJsImport(imp.specifier, import_node_path9.default.dirname(file.path), service.dir, tsPaths);
|
|
2811
2940
|
if (!resolved) continue;
|
|
2812
2941
|
edgesAdded += emitImportEdge(
|
|
2813
2942
|
graph,
|
|
@@ -2932,8 +3061,8 @@ function chiRoutesFromSource(source, parser) {
|
|
|
2932
3061
|
chiWalk(tree.rootNode, "", out);
|
|
2933
3062
|
return out;
|
|
2934
3063
|
}
|
|
2935
|
-
function stripChiRegex(
|
|
2936
|
-
return
|
|
3064
|
+
function stripChiRegex(path78) {
|
|
3065
|
+
return path78.replace(/\{([^{}:]+):[^{}]*\}/g, "{$1}");
|
|
2937
3066
|
}
|
|
2938
3067
|
function chiWalk(node, prefix, out) {
|
|
2939
3068
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
@@ -3273,7 +3402,7 @@ function isNextPagesApiFile(relFile) {
|
|
|
3273
3402
|
if (pagesIdx === -1 || segs[pagesIdx + 1] !== "api") return false;
|
|
3274
3403
|
const base = segs[segs.length - 1] ?? "";
|
|
3275
3404
|
if (/^_(app|document|middleware)\./.test(base)) return false;
|
|
3276
|
-
return JS_ROUTE_EXTENSIONS.has(
|
|
3405
|
+
return JS_ROUTE_EXTENSIONS.has(import_node_path10.default.extname(base));
|
|
3277
3406
|
}
|
|
3278
3407
|
function nextSegment(seg) {
|
|
3279
3408
|
if (seg.startsWith("(") && seg.endsWith(")")) return null;
|
|
@@ -3605,9 +3734,9 @@ function rubyRocketRoute(args) {
|
|
|
3605
3734
|
if (!pair || pair.type !== "pair") continue;
|
|
3606
3735
|
const k = pair.childForFieldName("key");
|
|
3607
3736
|
if (k?.type !== "string") continue;
|
|
3608
|
-
const
|
|
3609
|
-
if (
|
|
3610
|
-
return { path:
|
|
3737
|
+
const path78 = rubyLiteral(k);
|
|
3738
|
+
if (path78 === null) continue;
|
|
3739
|
+
return { path: path78, target: rubyLiteral(pair.childForFieldName("value")) };
|
|
3611
3740
|
}
|
|
3612
3741
|
return null;
|
|
3613
3742
|
}
|
|
@@ -4455,12 +4584,12 @@ async function expressMountPrefixes(files, serviceDir, tsPaths) {
|
|
|
4455
4584
|
const jsParser = makeJsParser2();
|
|
4456
4585
|
const fileInfo = /* @__PURE__ */ new Map();
|
|
4457
4586
|
for (const f of files) {
|
|
4458
|
-
if (!JS_ROUTE_EXTENSIONS.has(
|
|
4587
|
+
if (!JS_ROUTE_EXTENSIONS.has(import_node_path10.default.extname(f.path))) continue;
|
|
4459
4588
|
if (isTestPath(f.path)) continue;
|
|
4460
|
-
const rel = toPosix(
|
|
4589
|
+
const rel = toPosix(import_node_path10.default.relative(serviceDir, f.path));
|
|
4461
4590
|
try {
|
|
4462
4591
|
const tree = parseSource2(jsParser, f.content);
|
|
4463
|
-
fileInfo.set(rel, analyzeExpressFile(tree.rootNode,
|
|
4592
|
+
fileInfo.set(rel, analyzeExpressFile(tree.rootNode, import_node_path10.default.dirname(f.path)));
|
|
4464
4593
|
} catch {
|
|
4465
4594
|
}
|
|
4466
4595
|
}
|
|
@@ -4559,14 +4688,14 @@ async function addRoutes(graph, services) {
|
|
|
4559
4688
|
const mountPrefixes = hasExpress ? await expressMountPrefixes(files, service.dir, await loadTsPathConfig(service.dir)) : /* @__PURE__ */ new Map();
|
|
4560
4689
|
for (const file of files) {
|
|
4561
4690
|
if (isTestPath(file.path)) continue;
|
|
4562
|
-
const ext =
|
|
4691
|
+
const ext = import_node_path10.default.extname(file.path);
|
|
4563
4692
|
const isPy = ext === ".py";
|
|
4564
4693
|
const isGo = ext === ".go";
|
|
4565
4694
|
const isRb = ext === ".rb";
|
|
4566
4695
|
const isPhp = ext === ".php";
|
|
4567
4696
|
const isRs = ext === ".rs";
|
|
4568
4697
|
if (!JS_ROUTE_EXTENSIONS.has(ext) && !isPy && !isGo && !isRb && !isPhp && !isRs) continue;
|
|
4569
|
-
const relFile = toPosix(
|
|
4698
|
+
const relFile = toPosix(import_node_path10.default.relative(service.dir, file.path));
|
|
4570
4699
|
let routes;
|
|
4571
4700
|
try {
|
|
4572
4701
|
if (isPhp) {
|
|
@@ -5023,7 +5152,7 @@ function languageForExt(relPath) {
|
|
|
5023
5152
|
function relPathForRuntimeFile(filepath, serviceNode, scanPath) {
|
|
5024
5153
|
let p = toPosix2(filepath).replace(/^file:\/\//, "");
|
|
5025
5154
|
if (scanPath && scanPath.length > 0) {
|
|
5026
|
-
const absRoot = toPosix2(
|
|
5155
|
+
const absRoot = toPosix2(import_node_path11.default.resolve(scanPath, serviceNode?.repoPath ?? ""));
|
|
5027
5156
|
const anchor = absRoot.endsWith("/") ? absRoot : `${absRoot}/`;
|
|
5028
5157
|
if (p.startsWith(anchor)) return p.slice(anchor.length);
|
|
5029
5158
|
}
|
|
@@ -5051,10 +5180,10 @@ function resolveDistToSrc(absFilepath, line) {
|
|
|
5051
5180
|
entry = null;
|
|
5052
5181
|
const mapPath = `${absFilepath}.map`;
|
|
5053
5182
|
try {
|
|
5054
|
-
if ((0,
|
|
5055
|
-
const raw = JSON.parse((0,
|
|
5183
|
+
if ((0, import_node_fs10.existsSync)(mapPath)) {
|
|
5184
|
+
const raw = JSON.parse((0, import_node_fs10.readFileSync)(mapPath, "utf8"));
|
|
5056
5185
|
const consumer = new sourceMapJs.SourceMapConsumer(raw);
|
|
5057
|
-
entry = { consumer, dir:
|
|
5186
|
+
entry = { consumer, dir: import_node_path11.default.dirname(mapPath) };
|
|
5058
5187
|
}
|
|
5059
5188
|
} catch {
|
|
5060
5189
|
entry = null;
|
|
@@ -5074,7 +5203,7 @@ function resolveDistToSrc(absFilepath, line) {
|
|
|
5074
5203
|
}
|
|
5075
5204
|
if (!pos || !pos.source) return null;
|
|
5076
5205
|
const root = entry.consumer.sourceRoot ?? "";
|
|
5077
|
-
const resolved =
|
|
5206
|
+
const resolved = import_node_path11.default.resolve(entry.dir, root, pos.source);
|
|
5078
5207
|
return { filepath: resolved, ...pos.line ? { line: pos.line } : {} };
|
|
5079
5208
|
} catch {
|
|
5080
5209
|
return null;
|
|
@@ -5618,8 +5747,8 @@ function emitIncidentEvent(project, ev) {
|
|
|
5618
5747
|
});
|
|
5619
5748
|
}
|
|
5620
5749
|
async function appendErrorEvent(ctx, ev) {
|
|
5621
|
-
await
|
|
5622
|
-
await
|
|
5750
|
+
await import_node_fs10.promises.mkdir(import_node_path11.default.dirname(ctx.errorsPath), { recursive: true });
|
|
5751
|
+
await import_node_fs10.promises.appendFile(ctx.errorsPath, JSON.stringify(ev) + "\n", "utf8");
|
|
5623
5752
|
emitIncidentEvent(ctx.project ?? DEFAULT_PROJECT, ev);
|
|
5624
5753
|
}
|
|
5625
5754
|
async function appendConnectorIncident(errorsPath, input, project) {
|
|
@@ -5634,8 +5763,8 @@ async function appendConnectorIncident(errorsPath, input, project) {
|
|
|
5634
5763
|
...input.attributes && Object.keys(input.attributes).length > 0 ? { attributes: input.attributes } : {},
|
|
5635
5764
|
affectedNode: input.affectedNode
|
|
5636
5765
|
};
|
|
5637
|
-
await
|
|
5638
|
-
await
|
|
5766
|
+
await import_node_fs10.promises.mkdir(import_node_path11.default.dirname(errorsPath), { recursive: true });
|
|
5767
|
+
await import_node_fs10.promises.appendFile(errorsPath, JSON.stringify(ev) + "\n", "utf8");
|
|
5639
5768
|
if (project) emitIncidentEvent(project, ev);
|
|
5640
5769
|
}
|
|
5641
5770
|
function landIncidentCallSite(span, callSite, trusted, graph) {
|
|
@@ -6226,13 +6355,13 @@ async function markStaleEdges(graph, options = {}) {
|
|
|
6226
6355
|
return { count: events.length, events };
|
|
6227
6356
|
}
|
|
6228
6357
|
async function appendStaleEvents(staleEventsPath, events) {
|
|
6229
|
-
await
|
|
6358
|
+
await import_node_fs10.promises.mkdir(import_node_path11.default.dirname(staleEventsPath), { recursive: true });
|
|
6230
6359
|
const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
6231
|
-
await
|
|
6360
|
+
await import_node_fs10.promises.appendFile(staleEventsPath, lines, "utf8");
|
|
6232
6361
|
}
|
|
6233
6362
|
async function readStaleEvents(staleEventsPath) {
|
|
6234
6363
|
try {
|
|
6235
|
-
const raw = await
|
|
6364
|
+
const raw = await import_node_fs10.promises.readFile(staleEventsPath, "utf8");
|
|
6236
6365
|
return raw.split("\n").filter((line) => line.length > 0).map((line) => JSON.parse(line));
|
|
6237
6366
|
} catch (err) {
|
|
6238
6367
|
if (err.code === "ENOENT") return [];
|
|
@@ -6268,7 +6397,7 @@ function startStalenessLoop(graph, options = {}) {
|
|
|
6268
6397
|
var INCIDENT_READ_MAX_BYTES = 32 * 1024 * 1024;
|
|
6269
6398
|
var INCIDENT_READ_MAX_EVENTS = 5e3;
|
|
6270
6399
|
async function readErrorFileTail(errorsPath, maxBytes) {
|
|
6271
|
-
const handle = await
|
|
6400
|
+
const handle = await import_node_fs10.promises.open(errorsPath, "r");
|
|
6272
6401
|
try {
|
|
6273
6402
|
const { size } = await handle.stat();
|
|
6274
6403
|
if (size <= maxBytes) {
|
|
@@ -6511,19 +6640,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
6511
6640
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
6512
6641
|
let best = { path: [start], edges: [] };
|
|
6513
6642
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
6514
|
-
function step(node,
|
|
6515
|
-
if (
|
|
6516
|
-
best = { path: [...
|
|
6643
|
+
function step(node, path78, edges) {
|
|
6644
|
+
if (path78.length > best.path.length) {
|
|
6645
|
+
best = { path: [...path78], edges: [...edges] };
|
|
6517
6646
|
}
|
|
6518
|
-
if (
|
|
6647
|
+
if (path78.length - 1 >= maxDepth) return;
|
|
6519
6648
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
6520
6649
|
for (const [srcId, edge] of incoming) {
|
|
6521
6650
|
if (visited.has(srcId)) continue;
|
|
6522
6651
|
visited.add(srcId);
|
|
6523
|
-
|
|
6652
|
+
path78.push(srcId);
|
|
6524
6653
|
edges.push(edge);
|
|
6525
|
-
step(srcId,
|
|
6526
|
-
|
|
6654
|
+
step(srcId, path78, edges);
|
|
6655
|
+
path78.pop();
|
|
6527
6656
|
edges.pop();
|
|
6528
6657
|
visited.delete(srcId);
|
|
6529
6658
|
}
|
|
@@ -6738,20 +6867,20 @@ function dominantFailingCall(graph, serviceId17, visited) {
|
|
|
6738
6867
|
return best;
|
|
6739
6868
|
}
|
|
6740
6869
|
function followFailingCallChain(graph, originServiceId, maxDepth) {
|
|
6741
|
-
const
|
|
6870
|
+
const path78 = [originServiceId];
|
|
6742
6871
|
const edges = [];
|
|
6743
6872
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
6744
6873
|
let current = originServiceId;
|
|
6745
6874
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
6746
6875
|
const hop = dominantFailingCall(graph, current, visited);
|
|
6747
6876
|
if (!hop) break;
|
|
6748
|
-
|
|
6877
|
+
path78.push(hop.nextService);
|
|
6749
6878
|
edges.push(hop.edge);
|
|
6750
6879
|
visited.add(hop.nextService);
|
|
6751
6880
|
current = hop.nextService;
|
|
6752
6881
|
}
|
|
6753
6882
|
if (edges.length === 0) return null;
|
|
6754
|
-
return { path:
|
|
6883
|
+
return { path: path78, edges, culprit: current };
|
|
6755
6884
|
}
|
|
6756
6885
|
function isStaleCallEdge(e) {
|
|
6757
6886
|
return e.type === import_types8.EdgeType.CALLS && e.provenance === import_types8.Provenance.STALE;
|
|
@@ -6787,26 +6916,26 @@ function dominantStaleCall(graph, serviceId17, visited) {
|
|
|
6787
6916
|
return best;
|
|
6788
6917
|
}
|
|
6789
6918
|
function followStaleCallChain(graph, originServiceId, maxDepth) {
|
|
6790
|
-
const
|
|
6919
|
+
const path78 = [originServiceId];
|
|
6791
6920
|
const edges = [];
|
|
6792
6921
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
6793
6922
|
let current = originServiceId;
|
|
6794
6923
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
6795
6924
|
const hop = dominantStaleCall(graph, current, visited);
|
|
6796
6925
|
if (!hop) break;
|
|
6797
|
-
|
|
6926
|
+
path78.push(hop.nextService);
|
|
6798
6927
|
edges.push(hop.edge);
|
|
6799
6928
|
visited.add(hop.nextService);
|
|
6800
6929
|
current = hop.nextService;
|
|
6801
6930
|
}
|
|
6802
6931
|
if (edges.length === 0) return null;
|
|
6803
|
-
return { path:
|
|
6932
|
+
return { path: path78, edges, culprit: current };
|
|
6804
6933
|
}
|
|
6805
6934
|
function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
6806
6935
|
const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
|
|
6807
6936
|
if (!chain) return null;
|
|
6808
6937
|
const culprit = chain.culprit;
|
|
6809
|
-
const
|
|
6938
|
+
const path78 = [...chain.path];
|
|
6810
6939
|
const edgeProvenances = chain.edges.map((e) => e.provenance);
|
|
6811
6940
|
const baseConfidence = confidenceFromMix(chain.edges);
|
|
6812
6941
|
const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
|
|
@@ -6814,14 +6943,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
6814
6943
|
if (loc) {
|
|
6815
6944
|
let rootCauseNode = culprit;
|
|
6816
6945
|
if (loc.fileNode) {
|
|
6817
|
-
|
|
6946
|
+
path78.push(loc.fileNode);
|
|
6818
6947
|
edgeProvenances.push(import_types8.Provenance.OBSERVED);
|
|
6819
6948
|
rootCauseNode = loc.fileNode;
|
|
6820
6949
|
}
|
|
6821
6950
|
return import_types8.RootCauseResultSchema.parse({
|
|
6822
6951
|
rootCauseNode,
|
|
6823
6952
|
rootCauseReason: loc.rootCauseReason,
|
|
6824
|
-
traversalPath:
|
|
6953
|
+
traversalPath: path78,
|
|
6825
6954
|
edgeProvenances,
|
|
6826
6955
|
confidence,
|
|
6827
6956
|
...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
|
|
@@ -6833,7 +6962,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
6833
6962
|
return import_types8.RootCauseResultSchema.parse({
|
|
6834
6963
|
rootCauseNode: culprit,
|
|
6835
6964
|
rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
|
|
6836
|
-
traversalPath:
|
|
6965
|
+
traversalPath: path78,
|
|
6837
6966
|
edgeProvenances,
|
|
6838
6967
|
confidence,
|
|
6839
6968
|
fixRecommendation: `Inspect ${culpritName}'s failing handler`
|
|
@@ -7486,10 +7615,10 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
|
|
|
7486
7615
|
traversalPath = staleChain.path;
|
|
7487
7616
|
edgeProvenances = staleChain.edges.map((e) => e.provenance);
|
|
7488
7617
|
} else if (top.node !== seedNode) {
|
|
7489
|
-
const
|
|
7490
|
-
if (
|
|
7491
|
-
traversalPath =
|
|
7492
|
-
edgeProvenances =
|
|
7618
|
+
const path78 = findPath(graph, errorNodeId, top.node, "up", ROOT_CAUSE_MAX_DEPTH);
|
|
7619
|
+
if (path78) {
|
|
7620
|
+
traversalPath = path78.nodes;
|
|
7621
|
+
edgeProvenances = path78.edges.map((e) => e.provenance);
|
|
7493
7622
|
} else {
|
|
7494
7623
|
traversalPath = [errorNodeId, top.node];
|
|
7495
7624
|
edgeProvenances = [top.provenance ?? import_types8.Provenance.OBSERVED];
|
|
@@ -8251,16 +8380,16 @@ init_cjs_shims();
|
|
|
8251
8380
|
|
|
8252
8381
|
// src/extract/services.ts
|
|
8253
8382
|
init_cjs_shims();
|
|
8254
|
-
var
|
|
8255
|
-
var
|
|
8256
|
-
var
|
|
8383
|
+
var import_node_fs21 = require("fs");
|
|
8384
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
8385
|
+
var import_ignore2 = __toESM(require("ignore"), 1);
|
|
8257
8386
|
var import_minimatch2 = require("minimatch");
|
|
8258
8387
|
var import_types19 = require("@neat.is/types");
|
|
8259
8388
|
|
|
8260
8389
|
// src/extract/python.ts
|
|
8261
8390
|
init_cjs_shims();
|
|
8262
|
-
var
|
|
8263
|
-
var
|
|
8391
|
+
var import_node_fs11 = require("fs");
|
|
8392
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
8264
8393
|
var import_smol_toml = require("smol-toml");
|
|
8265
8394
|
var REQUIREMENT_LINE = /^\s*([A-Za-z0-9_.-]+)(?:\[[^\]]*\])?\s*(?:(==)\s*([A-Za-z0-9_.+-]+))?/;
|
|
8266
8395
|
function parseRequirementsTxt(content) {
|
|
@@ -8293,25 +8422,25 @@ function depsFromPyProject(pyproject) {
|
|
|
8293
8422
|
return out;
|
|
8294
8423
|
}
|
|
8295
8424
|
async function discoverPythonService(serviceDir) {
|
|
8296
|
-
const pyprojectPath =
|
|
8297
|
-
const requirementsPath =
|
|
8298
|
-
const setupPath =
|
|
8425
|
+
const pyprojectPath = import_node_path12.default.join(serviceDir, "pyproject.toml");
|
|
8426
|
+
const requirementsPath = import_node_path12.default.join(serviceDir, "requirements.txt");
|
|
8427
|
+
const setupPath = import_node_path12.default.join(serviceDir, "setup.py");
|
|
8299
8428
|
const hasPyproject = await exists2(pyprojectPath);
|
|
8300
8429
|
const hasRequirements = await exists2(requirementsPath);
|
|
8301
8430
|
const hasSetup = await exists2(setupPath);
|
|
8302
8431
|
if (!hasPyproject && !hasRequirements && !hasSetup) return null;
|
|
8303
|
-
let name =
|
|
8432
|
+
let name = import_node_path12.default.basename(serviceDir);
|
|
8304
8433
|
let version;
|
|
8305
8434
|
const dependencies = {};
|
|
8306
8435
|
if (hasPyproject) {
|
|
8307
|
-
const raw = await
|
|
8436
|
+
const raw = await import_node_fs11.promises.readFile(pyprojectPath, "utf8");
|
|
8308
8437
|
const pyproject = (0, import_smol_toml.parse)(raw);
|
|
8309
8438
|
name = pyproject.project?.name ?? pyproject.tool?.poetry?.name ?? name;
|
|
8310
8439
|
version = pyproject.project?.version ?? pyproject.tool?.poetry?.version ?? void 0;
|
|
8311
8440
|
Object.assign(dependencies, depsFromPyProject(pyproject));
|
|
8312
8441
|
}
|
|
8313
8442
|
if (hasRequirements) {
|
|
8314
|
-
const raw = await
|
|
8443
|
+
const raw = await import_node_fs11.promises.readFile(requirementsPath, "utf8");
|
|
8315
8444
|
Object.assign(dependencies, parseRequirementsTxt(raw));
|
|
8316
8445
|
}
|
|
8317
8446
|
return { name, version, dependencies };
|
|
@@ -8326,8 +8455,8 @@ function pythonToPackage(service) {
|
|
|
8326
8455
|
|
|
8327
8456
|
// src/extract/go.ts
|
|
8328
8457
|
init_cjs_shims();
|
|
8329
|
-
var
|
|
8330
|
-
var
|
|
8458
|
+
var import_node_fs12 = require("fs");
|
|
8459
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
8331
8460
|
var import_types10 = require("@neat.is/types");
|
|
8332
8461
|
function parseGoMod(source) {
|
|
8333
8462
|
const module2 = source.match(/^\s*module\s+(\S+)\s*$/m)?.[1];
|
|
@@ -8354,7 +8483,7 @@ function goFramework(deps) {
|
|
|
8354
8483
|
async function discoverGoService(scanPath, dir) {
|
|
8355
8484
|
let raw;
|
|
8356
8485
|
try {
|
|
8357
|
-
raw = await
|
|
8486
|
+
raw = await import_node_fs12.promises.readFile(import_node_path13.default.join(dir, "go.mod"), "utf8");
|
|
8358
8487
|
} catch {
|
|
8359
8488
|
return null;
|
|
8360
8489
|
}
|
|
@@ -8369,7 +8498,7 @@ async function discoverGoService(scanPath, dir) {
|
|
|
8369
8498
|
name,
|
|
8370
8499
|
language: "go",
|
|
8371
8500
|
dependencies: mod.dependencies,
|
|
8372
|
-
repoPath:
|
|
8501
|
+
repoPath: import_node_path13.default.relative(scanPath, dir),
|
|
8373
8502
|
...framework ? { framework } : {}
|
|
8374
8503
|
};
|
|
8375
8504
|
return { pkg, dir, node };
|
|
@@ -8377,8 +8506,8 @@ async function discoverGoService(scanPath, dir) {
|
|
|
8377
8506
|
|
|
8378
8507
|
// src/extract/ruby.ts
|
|
8379
8508
|
init_cjs_shims();
|
|
8380
|
-
var
|
|
8381
|
-
var
|
|
8509
|
+
var import_node_fs13 = require("fs");
|
|
8510
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
8382
8511
|
var import_types11 = require("@neat.is/types");
|
|
8383
8512
|
function parseGemfile(source) {
|
|
8384
8513
|
const dependencies = {};
|
|
@@ -8395,12 +8524,12 @@ function parseGemfile(source) {
|
|
|
8395
8524
|
async function discoverRubyService(scanPath, dir) {
|
|
8396
8525
|
let raw;
|
|
8397
8526
|
try {
|
|
8398
|
-
raw = await
|
|
8527
|
+
raw = await import_node_fs13.promises.readFile(import_node_path14.default.join(dir, "Gemfile"), "utf8");
|
|
8399
8528
|
} catch {
|
|
8400
8529
|
return null;
|
|
8401
8530
|
}
|
|
8402
8531
|
const gemfile = parseGemfile(raw);
|
|
8403
|
-
const name =
|
|
8532
|
+
const name = import_node_path14.default.basename(dir);
|
|
8404
8533
|
const pkg = { name, dependencies: gemfile.dependencies };
|
|
8405
8534
|
const node = {
|
|
8406
8535
|
id: (0, import_types11.serviceId)(name),
|
|
@@ -8408,7 +8537,7 @@ async function discoverRubyService(scanPath, dir) {
|
|
|
8408
8537
|
name,
|
|
8409
8538
|
language: "ruby",
|
|
8410
8539
|
dependencies: gemfile.dependencies,
|
|
8411
|
-
repoPath:
|
|
8540
|
+
repoPath: import_node_path14.default.relative(scanPath, dir),
|
|
8412
8541
|
...gemfile.dependencies["rails"] !== void 0 ? { framework: "rails" } : {}
|
|
8413
8542
|
};
|
|
8414
8543
|
return { pkg, dir, node };
|
|
@@ -8416,7 +8545,7 @@ async function discoverRubyService(scanPath, dir) {
|
|
|
8416
8545
|
|
|
8417
8546
|
// src/extract/php.ts
|
|
8418
8547
|
init_cjs_shims();
|
|
8419
|
-
var
|
|
8548
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
8420
8549
|
var import_types12 = require("@neat.is/types");
|
|
8421
8550
|
function parseComposerJson(composer) {
|
|
8422
8551
|
return {
|
|
@@ -8429,12 +8558,12 @@ function parseComposerJson(composer) {
|
|
|
8429
8558
|
async function discoverPhpService(scanPath, dir) {
|
|
8430
8559
|
let composer;
|
|
8431
8560
|
try {
|
|
8432
|
-
composer = await readJson(
|
|
8561
|
+
composer = await readJson(import_node_path15.default.join(dir, "composer.json"));
|
|
8433
8562
|
} catch {
|
|
8434
8563
|
return null;
|
|
8435
8564
|
}
|
|
8436
8565
|
const { dependencies } = parseComposerJson(composer);
|
|
8437
|
-
const name =
|
|
8566
|
+
const name = import_node_path15.default.basename(dir);
|
|
8438
8567
|
const pkg = { name, dependencies };
|
|
8439
8568
|
const node = {
|
|
8440
8569
|
id: (0, import_types12.serviceId)(name),
|
|
@@ -8442,7 +8571,7 @@ async function discoverPhpService(scanPath, dir) {
|
|
|
8442
8571
|
name,
|
|
8443
8572
|
language: "php",
|
|
8444
8573
|
dependencies,
|
|
8445
|
-
repoPath:
|
|
8574
|
+
repoPath: import_node_path15.default.relative(scanPath, dir),
|
|
8446
8575
|
...dependencies["laravel/framework"] !== void 0 ? { framework: "laravel" } : {}
|
|
8447
8576
|
};
|
|
8448
8577
|
return { pkg, dir, node };
|
|
@@ -8450,23 +8579,23 @@ async function discoverPhpService(scanPath, dir) {
|
|
|
8450
8579
|
|
|
8451
8580
|
// src/extract/csharp.ts
|
|
8452
8581
|
init_cjs_shims();
|
|
8453
|
-
var
|
|
8454
|
-
var
|
|
8582
|
+
var import_node_fs14 = require("fs");
|
|
8583
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
8455
8584
|
var import_types13 = require("@neat.is/types");
|
|
8456
8585
|
var CSHARP_PROJECT_EXTS = /* @__PURE__ */ new Set([".csproj", ".sln"]);
|
|
8457
8586
|
async function projectFiles(dir) {
|
|
8458
|
-
const entries = await
|
|
8587
|
+
const entries = await import_node_fs14.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
8459
8588
|
const out = [];
|
|
8460
8589
|
for (const entry of entries) {
|
|
8461
8590
|
if (!entry.isFile()) continue;
|
|
8462
|
-
if (CSHARP_PROJECT_EXTS.has(
|
|
8591
|
+
if (CSHARP_PROJECT_EXTS.has(import_node_path16.default.extname(entry.name).toLowerCase())) out.push(entry.name);
|
|
8463
8592
|
}
|
|
8464
8593
|
return out.sort();
|
|
8465
8594
|
}
|
|
8466
8595
|
var NESTED_PROJECT_DIR = "src";
|
|
8467
8596
|
async function resolveProjectDir(dir) {
|
|
8468
8597
|
if ((await projectFiles(dir)).length > 0) return dir;
|
|
8469
|
-
const nested =
|
|
8598
|
+
const nested = import_node_path16.default.join(dir, NESTED_PROJECT_DIR);
|
|
8470
8599
|
if ((await projectFiles(nested)).length > 0) return nested;
|
|
8471
8600
|
return null;
|
|
8472
8601
|
}
|
|
@@ -8491,10 +8620,10 @@ async function discoverCsharpService(scanPath, dir) {
|
|
|
8491
8620
|
if (projectDir === null) return null;
|
|
8492
8621
|
const projects = await projectFiles(projectDir);
|
|
8493
8622
|
const csproj = projects.find((p) => p.toLowerCase().endsWith(".csproj"));
|
|
8494
|
-
const name = csproj ?
|
|
8623
|
+
const name = csproj ? import_node_path16.default.basename(csproj, import_node_path16.default.extname(csproj)) : import_node_path16.default.basename(dir);
|
|
8495
8624
|
let dependencies = {};
|
|
8496
8625
|
if (csproj) {
|
|
8497
|
-
const raw = await
|
|
8626
|
+
const raw = await import_node_fs14.promises.readFile(import_node_path16.default.join(projectDir, csproj), "utf8").catch(() => "");
|
|
8498
8627
|
dependencies = parseCsproj(raw).dependencies;
|
|
8499
8628
|
}
|
|
8500
8629
|
const pkg = { name, dependencies };
|
|
@@ -8506,20 +8635,20 @@ async function discoverCsharpService(scanPath, dir) {
|
|
|
8506
8635
|
dependencies,
|
|
8507
8636
|
// Anchor on the directory that holds the project and its `.cs` files, so file
|
|
8508
8637
|
// attribution reaches the source whether it sits at the root or under `src/`.
|
|
8509
|
-
repoPath:
|
|
8638
|
+
repoPath: import_node_path16.default.relative(scanPath, projectDir)
|
|
8510
8639
|
};
|
|
8511
8640
|
return { pkg, dir: projectDir, node };
|
|
8512
8641
|
}
|
|
8513
8642
|
|
|
8514
8643
|
// src/extract/java.ts
|
|
8515
8644
|
init_cjs_shims();
|
|
8516
|
-
var
|
|
8517
|
-
var
|
|
8645
|
+
var import_node_fs15 = require("fs");
|
|
8646
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
8518
8647
|
var import_types14 = require("@neat.is/types");
|
|
8519
8648
|
var JAVA_MANIFESTS = ["pom.xml", "build.gradle", "build.gradle.kts"];
|
|
8520
8649
|
async function hasJavaManifest(dir) {
|
|
8521
8650
|
for (const manifest of JAVA_MANIFESTS) {
|
|
8522
|
-
if (await exists2(
|
|
8651
|
+
if (await exists2(import_node_path17.default.join(dir, manifest))) return true;
|
|
8523
8652
|
}
|
|
8524
8653
|
return false;
|
|
8525
8654
|
}
|
|
@@ -8554,19 +8683,19 @@ function parseGradle(source) {
|
|
|
8554
8683
|
return { dependencies };
|
|
8555
8684
|
}
|
|
8556
8685
|
async function discoverJavaService(scanPath, dir) {
|
|
8557
|
-
const pomPath =
|
|
8558
|
-
const gradlePath =
|
|
8559
|
-
const gradleKtsPath =
|
|
8686
|
+
const pomPath = import_node_path17.default.join(dir, "pom.xml");
|
|
8687
|
+
const gradlePath = import_node_path17.default.join(dir, "build.gradle");
|
|
8688
|
+
const gradleKtsPath = import_node_path17.default.join(dir, "build.gradle.kts");
|
|
8560
8689
|
let manifest = null;
|
|
8561
8690
|
if (await exists2(pomPath)) {
|
|
8562
|
-
manifest = parsePomXml(await
|
|
8691
|
+
manifest = parsePomXml(await import_node_fs15.promises.readFile(pomPath, "utf8").catch(() => ""));
|
|
8563
8692
|
} else if (await exists2(gradlePath)) {
|
|
8564
|
-
manifest = parseGradle(await
|
|
8693
|
+
manifest = parseGradle(await import_node_fs15.promises.readFile(gradlePath, "utf8").catch(() => ""));
|
|
8565
8694
|
} else if (await exists2(gradleKtsPath)) {
|
|
8566
|
-
manifest = parseGradle(await
|
|
8695
|
+
manifest = parseGradle(await import_node_fs15.promises.readFile(gradleKtsPath, "utf8").catch(() => ""));
|
|
8567
8696
|
}
|
|
8568
8697
|
if (!manifest) return null;
|
|
8569
|
-
const name = manifest.name?.trim() ||
|
|
8698
|
+
const name = manifest.name?.trim() || import_node_path17.default.basename(dir);
|
|
8570
8699
|
const dependencies = manifest.dependencies;
|
|
8571
8700
|
const pkg = { name, dependencies };
|
|
8572
8701
|
const node = {
|
|
@@ -8575,15 +8704,15 @@ async function discoverJavaService(scanPath, dir) {
|
|
|
8575
8704
|
name,
|
|
8576
8705
|
language: "java",
|
|
8577
8706
|
dependencies,
|
|
8578
|
-
repoPath:
|
|
8707
|
+
repoPath: import_node_path17.default.relative(scanPath, dir)
|
|
8579
8708
|
};
|
|
8580
8709
|
return { pkg, dir, node };
|
|
8581
8710
|
}
|
|
8582
8711
|
|
|
8583
8712
|
// src/extract/kotlin.ts
|
|
8584
8713
|
init_cjs_shims();
|
|
8585
|
-
var
|
|
8586
|
-
var
|
|
8714
|
+
var import_node_fs16 = require("fs");
|
|
8715
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
8587
8716
|
var import_types15 = require("@neat.is/types");
|
|
8588
8717
|
var KOTLIN_SOURCE_EXT = ".kt";
|
|
8589
8718
|
var JAVA_SOURCE_EXT = ".java";
|
|
@@ -8593,15 +8722,15 @@ async function dominantJvmSourceLanguage(dir) {
|
|
|
8593
8722
|
let java = 0;
|
|
8594
8723
|
async function recurse(current, depth) {
|
|
8595
8724
|
if (depth > SOURCE_PROBE_MAX_DEPTH) return;
|
|
8596
|
-
const entries = await
|
|
8725
|
+
const entries = await import_node_fs16.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
8597
8726
|
for (const entry of entries) {
|
|
8598
8727
|
if (entry.isDirectory()) {
|
|
8599
8728
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
8600
|
-
await recurse(
|
|
8729
|
+
await recurse(import_node_path18.default.join(current, entry.name), depth + 1);
|
|
8601
8730
|
continue;
|
|
8602
8731
|
}
|
|
8603
8732
|
if (!entry.isFile()) continue;
|
|
8604
|
-
const ext =
|
|
8733
|
+
const ext = import_node_path18.default.extname(entry.name).toLowerCase();
|
|
8605
8734
|
if (ext === KOTLIN_SOURCE_EXT) kt++;
|
|
8606
8735
|
else if (ext === JAVA_SOURCE_EXT) java++;
|
|
8607
8736
|
}
|
|
@@ -8612,17 +8741,17 @@ async function dominantJvmSourceLanguage(dir) {
|
|
|
8612
8741
|
return void 0;
|
|
8613
8742
|
}
|
|
8614
8743
|
async function readJvmManifest(dir) {
|
|
8615
|
-
const pomPath =
|
|
8616
|
-
const gradlePath =
|
|
8617
|
-
const gradleKtsPath =
|
|
8744
|
+
const pomPath = import_node_path18.default.join(dir, JAVA_MANIFESTS[0]);
|
|
8745
|
+
const gradlePath = import_node_path18.default.join(dir, JAVA_MANIFESTS[1]);
|
|
8746
|
+
const gradleKtsPath = import_node_path18.default.join(dir, JAVA_MANIFESTS[2]);
|
|
8618
8747
|
if (await exists2(pomPath)) {
|
|
8619
|
-
return parsePomXml(await
|
|
8748
|
+
return parsePomXml(await import_node_fs16.promises.readFile(pomPath, "utf8").catch(() => ""));
|
|
8620
8749
|
}
|
|
8621
8750
|
if (await exists2(gradlePath)) {
|
|
8622
|
-
return parseGradle(await
|
|
8751
|
+
return parseGradle(await import_node_fs16.promises.readFile(gradlePath, "utf8").catch(() => ""));
|
|
8623
8752
|
}
|
|
8624
8753
|
if (await exists2(gradleKtsPath)) {
|
|
8625
|
-
return parseGradle(await
|
|
8754
|
+
return parseGradle(await import_node_fs16.promises.readFile(gradleKtsPath, "utf8").catch(() => ""));
|
|
8626
8755
|
}
|
|
8627
8756
|
return null;
|
|
8628
8757
|
}
|
|
@@ -8631,7 +8760,7 @@ async function discoverKotlinService(scanPath, dir) {
|
|
|
8631
8760
|
if (await dominantJvmSourceLanguage(dir) !== "kotlin") return null;
|
|
8632
8761
|
const manifest = await readJvmManifest(dir);
|
|
8633
8762
|
if (!manifest) return null;
|
|
8634
|
-
const name = manifest.name?.trim() ||
|
|
8763
|
+
const name = manifest.name?.trim() || import_node_path18.default.basename(dir);
|
|
8635
8764
|
const dependencies = manifest.dependencies;
|
|
8636
8765
|
const pkg = { name, dependencies };
|
|
8637
8766
|
const node = {
|
|
@@ -8640,20 +8769,20 @@ async function discoverKotlinService(scanPath, dir) {
|
|
|
8640
8769
|
name,
|
|
8641
8770
|
language: "kotlin",
|
|
8642
8771
|
dependencies,
|
|
8643
|
-
repoPath:
|
|
8772
|
+
repoPath: import_node_path18.default.relative(scanPath, dir)
|
|
8644
8773
|
};
|
|
8645
8774
|
return { pkg, dir, node };
|
|
8646
8775
|
}
|
|
8647
8776
|
|
|
8648
8777
|
// src/extract/rust.ts
|
|
8649
8778
|
init_cjs_shims();
|
|
8650
|
-
var
|
|
8651
|
-
var
|
|
8779
|
+
var import_node_fs17 = require("fs");
|
|
8780
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
8652
8781
|
var import_smol_toml2 = require("smol-toml");
|
|
8653
8782
|
var import_types16 = require("@neat.is/types");
|
|
8654
8783
|
var CARGO_MANIFEST = "Cargo.toml";
|
|
8655
8784
|
async function hasRustManifest(dir) {
|
|
8656
|
-
return exists2(
|
|
8785
|
+
return exists2(import_node_path19.default.join(dir, CARGO_MANIFEST));
|
|
8657
8786
|
}
|
|
8658
8787
|
function parseCargoToml(source) {
|
|
8659
8788
|
const dependencies = {};
|
|
@@ -8678,10 +8807,10 @@ function parseCargoToml(source) {
|
|
|
8678
8807
|
return { name, dependencies };
|
|
8679
8808
|
}
|
|
8680
8809
|
async function discoverRustService(scanPath, dir) {
|
|
8681
|
-
const cargoPath =
|
|
8810
|
+
const cargoPath = import_node_path19.default.join(dir, CARGO_MANIFEST);
|
|
8682
8811
|
if (!await exists2(cargoPath)) return null;
|
|
8683
|
-
const manifest = parseCargoToml(await
|
|
8684
|
-
const name = manifest.name?.trim() ||
|
|
8812
|
+
const manifest = parseCargoToml(await import_node_fs17.promises.readFile(cargoPath, "utf8").catch(() => ""));
|
|
8813
|
+
const name = manifest.name?.trim() || import_node_path19.default.basename(dir);
|
|
8685
8814
|
const dependencies = manifest.dependencies;
|
|
8686
8815
|
const pkg = { name, dependencies };
|
|
8687
8816
|
const node = {
|
|
@@ -8690,19 +8819,19 @@ async function discoverRustService(scanPath, dir) {
|
|
|
8690
8819
|
name,
|
|
8691
8820
|
language: "rust",
|
|
8692
8821
|
dependencies,
|
|
8693
|
-
repoPath:
|
|
8822
|
+
repoPath: import_node_path19.default.relative(scanPath, dir)
|
|
8694
8823
|
};
|
|
8695
8824
|
return { pkg, dir, node };
|
|
8696
8825
|
}
|
|
8697
8826
|
|
|
8698
8827
|
// src/extract/cpp.ts
|
|
8699
8828
|
init_cjs_shims();
|
|
8700
|
-
var
|
|
8701
|
-
var
|
|
8829
|
+
var import_node_fs18 = require("fs");
|
|
8830
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
8702
8831
|
var import_types17 = require("@neat.is/types");
|
|
8703
8832
|
var CMAKE_MANIFEST = "CMakeLists.txt";
|
|
8704
8833
|
async function hasCppManifest(dir) {
|
|
8705
|
-
return exists2(
|
|
8834
|
+
return exists2(import_node_path20.default.join(dir, CMAKE_MANIFEST));
|
|
8706
8835
|
}
|
|
8707
8836
|
function parseCMakeProjectName(source) {
|
|
8708
8837
|
const withoutComments = source.replace(/#.*$/gm, "");
|
|
@@ -8710,10 +8839,10 @@ function parseCMakeProjectName(source) {
|
|
|
8710
8839
|
return m?.[1];
|
|
8711
8840
|
}
|
|
8712
8841
|
async function discoverCppService(scanPath, dir) {
|
|
8713
|
-
const cmakePath =
|
|
8842
|
+
const cmakePath = import_node_path20.default.join(dir, CMAKE_MANIFEST);
|
|
8714
8843
|
if (!await exists2(cmakePath)) return null;
|
|
8715
|
-
const source = await
|
|
8716
|
-
const name = parseCMakeProjectName(source)?.trim() ||
|
|
8844
|
+
const source = await import_node_fs18.promises.readFile(cmakePath, "utf8").catch(() => "");
|
|
8845
|
+
const name = parseCMakeProjectName(source)?.trim() || import_node_path20.default.basename(dir);
|
|
8717
8846
|
const dependencies = {};
|
|
8718
8847
|
const pkg = { name, dependencies };
|
|
8719
8848
|
const node = {
|
|
@@ -8722,15 +8851,15 @@ async function discoverCppService(scanPath, dir) {
|
|
|
8722
8851
|
name,
|
|
8723
8852
|
language: "cpp",
|
|
8724
8853
|
dependencies,
|
|
8725
|
-
repoPath:
|
|
8854
|
+
repoPath: import_node_path20.default.relative(scanPath, dir)
|
|
8726
8855
|
};
|
|
8727
8856
|
return { pkg, dir, node };
|
|
8728
8857
|
}
|
|
8729
8858
|
|
|
8730
8859
|
// src/extract/dockerfile-service.ts
|
|
8731
8860
|
init_cjs_shims();
|
|
8732
|
-
var
|
|
8733
|
-
var
|
|
8861
|
+
var import_node_fs19 = require("fs");
|
|
8862
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
8734
8863
|
var import_types18 = require("@neat.is/types");
|
|
8735
8864
|
function languageForSourceExt(ext) {
|
|
8736
8865
|
switch (ext) {
|
|
@@ -8772,12 +8901,12 @@ function languageForSourceExt(ext) {
|
|
|
8772
8901
|
}
|
|
8773
8902
|
var LANGUAGE_PRECEDENCE = ["typescript", "javascript", "python", "go", "ruby", "php", "csharp", "java", "kotlin", "rust", "cpp"];
|
|
8774
8903
|
async function inferServiceLanguage(dir) {
|
|
8775
|
-
const entries = await
|
|
8904
|
+
const entries = await import_node_fs19.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
8776
8905
|
const counts = /* @__PURE__ */ new Map();
|
|
8777
8906
|
for (const entry of entries) {
|
|
8778
8907
|
if (!entry.isFile()) continue;
|
|
8779
8908
|
if (isNeatAuthoredSourceFile(entry.name)) continue;
|
|
8780
|
-
const ext =
|
|
8909
|
+
const ext = import_node_path21.default.extname(entry.name).toLowerCase();
|
|
8781
8910
|
if (!SERVICE_FILE_EXTENSIONS.has(ext)) continue;
|
|
8782
8911
|
const lang = languageForSourceExt(ext);
|
|
8783
8912
|
if (!lang) continue;
|
|
@@ -8796,7 +8925,7 @@ async function inferServiceLanguage(dir) {
|
|
|
8796
8925
|
return best;
|
|
8797
8926
|
}
|
|
8798
8927
|
async function hasLanguageManifest(dir) {
|
|
8799
|
-
return await exists2(
|
|
8928
|
+
return await exists2(import_node_path21.default.join(dir, "package.json")) || await exists2(import_node_path21.default.join(dir, "pyproject.toml")) || await exists2(import_node_path21.default.join(dir, "requirements.txt")) || await exists2(import_node_path21.default.join(dir, "setup.py")) || await exists2(import_node_path21.default.join(dir, "go.mod")) || await exists2(import_node_path21.default.join(dir, "Gemfile")) || await exists2(import_node_path21.default.join(dir, "composer.json")) || // C#'s marker is a glob (`*.csproj` / `*.sln`), so it reads the directory
|
|
8800
8929
|
// rather than probing a fixed filename (ADR-196).
|
|
8801
8930
|
await hasCsharpProject(dir) || // Java (and its JVM sibling Kotlin, ADR-199) key on the same Maven / Gradle
|
|
8802
8931
|
// build manifest (ADR-197), so this one check stands the Dockerfile fallback
|
|
@@ -8806,15 +8935,15 @@ async function hasLanguageManifest(dir) {
|
|
|
8806
8935
|
await hasCppManifest(dir);
|
|
8807
8936
|
}
|
|
8808
8937
|
async function hasDockerfileDeclaredService(dir) {
|
|
8809
|
-
if (!await exists2(
|
|
8938
|
+
if (!await exists2(import_node_path21.default.join(dir, "Dockerfile"))) return false;
|
|
8810
8939
|
return await inferServiceLanguage(dir) !== null;
|
|
8811
8940
|
}
|
|
8812
8941
|
async function discoverDockerfileService(scanPath, dir) {
|
|
8813
|
-
if (!await exists2(
|
|
8942
|
+
if (!await exists2(import_node_path21.default.join(dir, "Dockerfile"))) return null;
|
|
8814
8943
|
if (await hasLanguageManifest(dir)) return null;
|
|
8815
8944
|
const language = await inferServiceLanguage(dir);
|
|
8816
8945
|
if (!language) return null;
|
|
8817
|
-
const name =
|
|
8946
|
+
const name = import_node_path21.default.basename(dir);
|
|
8818
8947
|
const pkg = { name, dependencies: {} };
|
|
8819
8948
|
const node = {
|
|
8820
8949
|
id: (0, import_types18.serviceId)(name),
|
|
@@ -8822,24 +8951,24 @@ async function discoverDockerfileService(scanPath, dir) {
|
|
|
8822
8951
|
name,
|
|
8823
8952
|
language,
|
|
8824
8953
|
dependencies: {},
|
|
8825
|
-
repoPath:
|
|
8954
|
+
repoPath: import_node_path21.default.relative(scanPath, dir)
|
|
8826
8955
|
};
|
|
8827
8956
|
return { pkg, dir, node };
|
|
8828
8957
|
}
|
|
8829
8958
|
|
|
8830
8959
|
// src/extract/owners.ts
|
|
8831
8960
|
init_cjs_shims();
|
|
8832
|
-
var
|
|
8833
|
-
var
|
|
8961
|
+
var import_node_fs20 = require("fs");
|
|
8962
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
8834
8963
|
var import_minimatch = require("minimatch");
|
|
8835
8964
|
async function loadCodeowners(scanPath) {
|
|
8836
8965
|
const candidates = [
|
|
8837
|
-
|
|
8838
|
-
|
|
8966
|
+
import_node_path22.default.join(scanPath, "CODEOWNERS"),
|
|
8967
|
+
import_node_path22.default.join(scanPath, ".github", "CODEOWNERS")
|
|
8839
8968
|
];
|
|
8840
8969
|
for (const file of candidates) {
|
|
8841
8970
|
if (await exists2(file)) {
|
|
8842
|
-
const raw = await
|
|
8971
|
+
const raw = await import_node_fs20.promises.readFile(file, "utf8");
|
|
8843
8972
|
return parseCodeowners(raw);
|
|
8844
8973
|
}
|
|
8845
8974
|
}
|
|
@@ -8857,7 +8986,7 @@ function parseCodeowners(raw) {
|
|
|
8857
8986
|
return { rules };
|
|
8858
8987
|
}
|
|
8859
8988
|
function matchOwner(file, repoPath) {
|
|
8860
|
-
const normalized = repoPath.split(
|
|
8989
|
+
const normalized = repoPath.split(import_node_path22.default.sep).join("/");
|
|
8861
8990
|
for (const rule of file.rules) {
|
|
8862
8991
|
if (matchesPattern(rule.pattern, normalized)) return rule.owners;
|
|
8863
8992
|
}
|
|
@@ -8873,7 +9002,7 @@ function matchesPattern(rawPattern, repoPath) {
|
|
|
8873
9002
|
return false;
|
|
8874
9003
|
}
|
|
8875
9004
|
async function readPackageJsonAuthor(serviceDir) {
|
|
8876
|
-
const pkgPath =
|
|
9005
|
+
const pkgPath = import_node_path22.default.join(serviceDir, "package.json");
|
|
8877
9006
|
if (!await exists2(pkgPath)) return null;
|
|
8878
9007
|
try {
|
|
8879
9008
|
const pkg = await readJson(pkgPath);
|
|
@@ -8910,36 +9039,36 @@ function workspaceGlobs(pkg) {
|
|
|
8910
9039
|
return null;
|
|
8911
9040
|
}
|
|
8912
9041
|
async function hasPythonManifest(dir) {
|
|
8913
|
-
return await exists2(
|
|
9042
|
+
return await exists2(import_node_path23.default.join(dir, "pyproject.toml")) || await exists2(import_node_path23.default.join(dir, "requirements.txt")) || await exists2(import_node_path23.default.join(dir, "setup.py"));
|
|
8914
9043
|
}
|
|
8915
9044
|
async function hasGoManifest(dir) {
|
|
8916
|
-
return exists2(
|
|
9045
|
+
return exists2(import_node_path23.default.join(dir, "go.mod"));
|
|
8917
9046
|
}
|
|
8918
9047
|
async function hasRubyManifest(dir) {
|
|
8919
|
-
return exists2(
|
|
9048
|
+
return exists2(import_node_path23.default.join(dir, "Gemfile"));
|
|
8920
9049
|
}
|
|
8921
9050
|
async function hasPhpManifest(dir) {
|
|
8922
|
-
return exists2(
|
|
9051
|
+
return exists2(import_node_path23.default.join(dir, "composer.json"));
|
|
8923
9052
|
}
|
|
8924
9053
|
async function hasCsharpManifest(dir) {
|
|
8925
9054
|
return hasCsharpProject(dir);
|
|
8926
9055
|
}
|
|
8927
9056
|
async function loadGitignore(scanPath) {
|
|
8928
|
-
const gitignorePath =
|
|
9057
|
+
const gitignorePath = import_node_path23.default.join(scanPath, ".gitignore");
|
|
8929
9058
|
if (!await exists2(gitignorePath)) return null;
|
|
8930
|
-
const raw = await
|
|
8931
|
-
return (0,
|
|
9059
|
+
const raw = await import_node_fs21.promises.readFile(gitignorePath, "utf8");
|
|
9060
|
+
return (0, import_ignore2.default)().add(raw);
|
|
8932
9061
|
}
|
|
8933
9062
|
async function walkDirs(start, scanPath, options, visit) {
|
|
8934
9063
|
async function recurse(current, depth) {
|
|
8935
9064
|
if (depth > options.maxDepth) return;
|
|
8936
|
-
const entries = await
|
|
9065
|
+
const entries = await import_node_fs21.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
8937
9066
|
for (const entry of entries) {
|
|
8938
9067
|
if (!entry.isDirectory()) continue;
|
|
8939
9068
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
8940
|
-
const child =
|
|
9069
|
+
const child = import_node_path23.default.join(current, entry.name);
|
|
8941
9070
|
if (options.ig) {
|
|
8942
|
-
const rel =
|
|
9071
|
+
const rel = import_node_path23.default.relative(scanPath, child).split(import_node_path23.default.sep).join("/");
|
|
8943
9072
|
if (rel && options.ig.ignores(rel + "/")) continue;
|
|
8944
9073
|
}
|
|
8945
9074
|
if (await isPythonVenvDir(child)) continue;
|
|
@@ -8955,8 +9084,8 @@ async function expandWorkspaceGlobs(scanPath, globs) {
|
|
|
8955
9084
|
for (const raw of globs) {
|
|
8956
9085
|
const pattern = raw.replace(/^\.\//, "");
|
|
8957
9086
|
if (!pattern.includes("*")) {
|
|
8958
|
-
const candidate =
|
|
8959
|
-
if (await exists2(
|
|
9087
|
+
const candidate = import_node_path23.default.join(scanPath, pattern);
|
|
9088
|
+
if (await exists2(import_node_path23.default.join(candidate, "package.json"))) found.add(candidate);
|
|
8960
9089
|
continue;
|
|
8961
9090
|
}
|
|
8962
9091
|
const segments = pattern.split("/");
|
|
@@ -8965,13 +9094,13 @@ async function expandWorkspaceGlobs(scanPath, globs) {
|
|
|
8965
9094
|
if (seg.includes("*")) break;
|
|
8966
9095
|
staticSegments.push(seg);
|
|
8967
9096
|
}
|
|
8968
|
-
const start =
|
|
9097
|
+
const start = import_node_path23.default.join(scanPath, ...staticSegments);
|
|
8969
9098
|
if (!await exists2(start)) continue;
|
|
8970
9099
|
const hasDoubleStar = pattern.includes("**");
|
|
8971
9100
|
const walkDepth = hasDoubleStar ? scanDepth : Math.max(0, segments.length - staticSegments.length - 1);
|
|
8972
9101
|
await walkDirs(start, scanPath, { maxDepth: walkDepth, ig: null }, async (dir) => {
|
|
8973
|
-
const rel =
|
|
8974
|
-
if ((0, import_minimatch2.minimatch)(rel, pattern) && await exists2(
|
|
9102
|
+
const rel = import_node_path23.default.relative(scanPath, dir).split(import_node_path23.default.sep).join("/");
|
|
9103
|
+
if ((0, import_minimatch2.minimatch)(rel, pattern) && await exists2(import_node_path23.default.join(dir, "package.json"))) {
|
|
8975
9104
|
found.add(dir);
|
|
8976
9105
|
}
|
|
8977
9106
|
});
|
|
@@ -8994,18 +9123,18 @@ function detectJsFramework(pkg) {
|
|
|
8994
9123
|
async function detectJsServiceLanguage(dir, pkg) {
|
|
8995
9124
|
const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
8996
9125
|
if (deps["typescript"] !== void 0) return "typescript";
|
|
8997
|
-
const entries = await
|
|
9126
|
+
const entries = await import_node_fs21.promises.readdir(dir).catch(() => []);
|
|
8998
9127
|
if (entries.some((name) => /^tsconfig(\..+)?\.json$/.test(name))) return "typescript";
|
|
8999
9128
|
return "javascript";
|
|
9000
9129
|
}
|
|
9001
9130
|
async function discoverNodeService(scanPath, dir) {
|
|
9002
|
-
const pkgPath =
|
|
9131
|
+
const pkgPath = import_node_path23.default.join(dir, "package.json");
|
|
9003
9132
|
if (!await exists2(pkgPath)) return null;
|
|
9004
9133
|
let pkg;
|
|
9005
9134
|
try {
|
|
9006
9135
|
pkg = await readJson(pkgPath);
|
|
9007
9136
|
} catch (err) {
|
|
9008
|
-
recordExtractionError("services",
|
|
9137
|
+
recordExtractionError("services", import_node_path23.default.relative(scanPath, pkgPath), err);
|
|
9009
9138
|
return null;
|
|
9010
9139
|
}
|
|
9011
9140
|
if (!pkg.name) return null;
|
|
@@ -9018,7 +9147,7 @@ async function discoverNodeService(scanPath, dir) {
|
|
|
9018
9147
|
language,
|
|
9019
9148
|
version: pkg.version,
|
|
9020
9149
|
dependencies: pkg.dependencies ?? {},
|
|
9021
|
-
repoPath:
|
|
9150
|
+
repoPath: import_node_path23.default.relative(scanPath, dir),
|
|
9022
9151
|
...pkg.engines?.node ? { nodeEngine: pkg.engines.node } : {},
|
|
9023
9152
|
...framework ? { framework } : {}
|
|
9024
9153
|
};
|
|
@@ -9035,12 +9164,12 @@ async function discoverPyService(scanPath, dir) {
|
|
|
9035
9164
|
language: "python",
|
|
9036
9165
|
version: py.version,
|
|
9037
9166
|
dependencies: py.dependencies,
|
|
9038
|
-
repoPath:
|
|
9167
|
+
repoPath: import_node_path23.default.relative(scanPath, dir)
|
|
9039
9168
|
};
|
|
9040
9169
|
return { pkg, dir, node };
|
|
9041
9170
|
}
|
|
9042
9171
|
async function discoverServices(scanPath) {
|
|
9043
|
-
const rootPkgPath =
|
|
9172
|
+
const rootPkgPath = import_node_path23.default.join(scanPath, "package.json");
|
|
9044
9173
|
let rootPkg = null;
|
|
9045
9174
|
if (await exists2(rootPkgPath)) {
|
|
9046
9175
|
try {
|
|
@@ -9048,7 +9177,7 @@ async function discoverServices(scanPath) {
|
|
|
9048
9177
|
} catch (err) {
|
|
9049
9178
|
recordExtractionError(
|
|
9050
9179
|
"services workspaces",
|
|
9051
|
-
|
|
9180
|
+
import_node_path23.default.relative(scanPath, rootPkgPath),
|
|
9052
9181
|
err
|
|
9053
9182
|
);
|
|
9054
9183
|
}
|
|
@@ -9069,7 +9198,7 @@ async function discoverServices(scanPath) {
|
|
|
9069
9198
|
scanPath,
|
|
9070
9199
|
{ maxDepth: parseScanDepth(), ig },
|
|
9071
9200
|
async (dir) => {
|
|
9072
|
-
if (await exists2(
|
|
9201
|
+
if (await exists2(import_node_path23.default.join(dir, "package.json"))) {
|
|
9073
9202
|
candidateDirs.push(dir);
|
|
9074
9203
|
} 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)) {
|
|
9075
9204
|
candidateDirs.push(dir);
|
|
@@ -9097,8 +9226,8 @@ async function discoverServices(scanPath) {
|
|
|
9097
9226
|
seenDirs.add(service.dir);
|
|
9098
9227
|
const existingDir = seen.get(service.node.name);
|
|
9099
9228
|
if (existingDir !== void 0) {
|
|
9100
|
-
const a =
|
|
9101
|
-
const b =
|
|
9229
|
+
const a = import_node_path23.default.relative(scanPath, existingDir) || ".";
|
|
9230
|
+
const b = import_node_path23.default.relative(scanPath, dir) || ".";
|
|
9102
9231
|
console.warn(
|
|
9103
9232
|
`[neat] duplicate package name "${service.node.name}" \u2014 keeping ${a}, ignoring ${b}`
|
|
9104
9233
|
);
|
|
@@ -9112,14 +9241,14 @@ async function discoverServices(scanPath) {
|
|
|
9112
9241
|
const owner = await computeServiceOwner(codeowners, service.node.repoPath, service.dir);
|
|
9113
9242
|
if (owner !== void 0) service.node.owner = owner;
|
|
9114
9243
|
}
|
|
9115
|
-
const resolvedDirs = out.map((s) =>
|
|
9244
|
+
const resolvedDirs = out.map((s) => import_node_path23.default.resolve(s.dir));
|
|
9116
9245
|
for (let i = 0; i < out.length; i++) {
|
|
9117
9246
|
const self = resolvedDirs[i];
|
|
9118
9247
|
const nested = [];
|
|
9119
9248
|
for (let j = 0; j < out.length; j++) {
|
|
9120
9249
|
if (i === j) continue;
|
|
9121
9250
|
const other = resolvedDirs[j];
|
|
9122
|
-
if (other.startsWith(self +
|
|
9251
|
+
if (other.startsWith(self + import_node_path23.default.sep)) nested.push(other);
|
|
9123
9252
|
}
|
|
9124
9253
|
out[i].excludeDirs = nested;
|
|
9125
9254
|
}
|
|
@@ -9146,8 +9275,8 @@ function addServiceNodes(graph, services) {
|
|
|
9146
9275
|
|
|
9147
9276
|
// src/extract/aliases.ts
|
|
9148
9277
|
init_cjs_shims();
|
|
9149
|
-
var
|
|
9150
|
-
var
|
|
9278
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
9279
|
+
var import_node_fs22 = require("fs");
|
|
9151
9280
|
var import_yaml2 = require("yaml");
|
|
9152
9281
|
var import_types20 = require("@neat.is/types");
|
|
9153
9282
|
var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
@@ -9174,14 +9303,14 @@ function indexServicesByName(services) {
|
|
|
9174
9303
|
const map = /* @__PURE__ */ new Map();
|
|
9175
9304
|
for (const s of services) {
|
|
9176
9305
|
map.set(s.node.name, s.node.id);
|
|
9177
|
-
map.set(
|
|
9306
|
+
map.set(import_node_path24.default.basename(s.dir), s.node.id);
|
|
9178
9307
|
}
|
|
9179
9308
|
return map;
|
|
9180
9309
|
}
|
|
9181
9310
|
async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
9182
9311
|
let composePath = null;
|
|
9183
9312
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
9184
|
-
const abs =
|
|
9313
|
+
const abs = import_node_path24.default.join(scanPath, name);
|
|
9185
9314
|
if (await exists2(abs)) {
|
|
9186
9315
|
composePath = abs;
|
|
9187
9316
|
break;
|
|
@@ -9194,7 +9323,7 @@ async function collectComposeAliases(graph, scanPath, serviceIndex) {
|
|
|
9194
9323
|
} catch (err) {
|
|
9195
9324
|
recordExtractionError(
|
|
9196
9325
|
"aliases compose",
|
|
9197
|
-
|
|
9326
|
+
import_node_path24.default.relative(scanPath, composePath),
|
|
9198
9327
|
err
|
|
9199
9328
|
);
|
|
9200
9329
|
return;
|
|
@@ -9237,11 +9366,11 @@ function parseDockerfileLabels(content) {
|
|
|
9237
9366
|
}
|
|
9238
9367
|
async function collectDockerfileAliases(graph, services) {
|
|
9239
9368
|
for (const service of services) {
|
|
9240
|
-
const dockerfilePath =
|
|
9369
|
+
const dockerfilePath = import_node_path24.default.join(service.dir, "Dockerfile");
|
|
9241
9370
|
if (!await exists2(dockerfilePath)) continue;
|
|
9242
9371
|
let content;
|
|
9243
9372
|
try {
|
|
9244
|
-
content = await
|
|
9373
|
+
content = await import_node_fs22.promises.readFile(dockerfilePath, "utf8");
|
|
9245
9374
|
} catch (err) {
|
|
9246
9375
|
recordExtractionError("aliases dockerfile", dockerfilePath, err);
|
|
9247
9376
|
continue;
|
|
@@ -9253,15 +9382,15 @@ async function collectDockerfileAliases(graph, services) {
|
|
|
9253
9382
|
async function walkYamlFiles(start, depth = 0, max = 5) {
|
|
9254
9383
|
if (depth > max) return [];
|
|
9255
9384
|
const out = [];
|
|
9256
|
-
const entries = await
|
|
9385
|
+
const entries = await import_node_fs22.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
9257
9386
|
for (const entry of entries) {
|
|
9258
9387
|
if (entry.isDirectory()) {
|
|
9259
9388
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
9260
|
-
const child =
|
|
9389
|
+
const child = import_node_path24.default.join(start, entry.name);
|
|
9261
9390
|
if (await isPythonVenvDir(child)) continue;
|
|
9262
9391
|
out.push(...await walkYamlFiles(child, depth + 1, max));
|
|
9263
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
9264
|
-
out.push(
|
|
9392
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path24.default.extname(entry.name))) {
|
|
9393
|
+
out.push(import_node_path24.default.join(start, entry.name));
|
|
9265
9394
|
}
|
|
9266
9395
|
}
|
|
9267
9396
|
return out;
|
|
@@ -9288,7 +9417,7 @@ function k8sServiceTarget(doc, byName) {
|
|
|
9288
9417
|
async function collectK8sAliases(graph, scanPath, serviceIndex) {
|
|
9289
9418
|
const files = await walkYamlFiles(scanPath);
|
|
9290
9419
|
for (const file of files) {
|
|
9291
|
-
const content = await
|
|
9420
|
+
const content = await import_node_fs22.promises.readFile(file, "utf8");
|
|
9292
9421
|
let docs;
|
|
9293
9422
|
try {
|
|
9294
9423
|
docs = (0, import_yaml2.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
@@ -9313,14 +9442,14 @@ async function addServiceAliases(graph, scanPath, services) {
|
|
|
9313
9442
|
|
|
9314
9443
|
// src/extract/files.ts
|
|
9315
9444
|
init_cjs_shims();
|
|
9316
|
-
var
|
|
9445
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
9317
9446
|
async function addFiles(graph, services) {
|
|
9318
9447
|
let nodesAdded = 0;
|
|
9319
9448
|
let edgesAdded = 0;
|
|
9320
9449
|
for (const service of services) {
|
|
9321
9450
|
const filePaths = await walkSourceFiles(service.dir, service.excludeDirs);
|
|
9322
9451
|
for (const filePath of filePaths) {
|
|
9323
|
-
const relPath = toPosix(
|
|
9452
|
+
const relPath = toPosix(import_node_path25.default.relative(service.dir, filePath));
|
|
9324
9453
|
const { nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
9325
9454
|
graph,
|
|
9326
9455
|
service.pkg.name,
|
|
@@ -9336,7 +9465,7 @@ async function addFiles(graph, services) {
|
|
|
9336
9465
|
|
|
9337
9466
|
// src/extract/symbols.ts
|
|
9338
9467
|
init_cjs_shims();
|
|
9339
|
-
var
|
|
9468
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
9340
9469
|
var import_tree_sitter3 = __toESM(require("tree-sitter"), 1);
|
|
9341
9470
|
var import_tree_sitter_javascript3 = __toESM(require("tree-sitter-javascript"), 1);
|
|
9342
9471
|
var import_tree_sitter_typescript = __toESM(require("tree-sitter-typescript"), 1);
|
|
@@ -10088,10 +10217,10 @@ async function addSymbols(graph, services) {
|
|
|
10088
10217
|
for (const service of services) {
|
|
10089
10218
|
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
10090
10219
|
for (const file of files) {
|
|
10091
|
-
const ext =
|
|
10220
|
+
const ext = import_node_path26.default.extname(file.path);
|
|
10092
10221
|
const parser = parserForExt5(ext);
|
|
10093
10222
|
if (!parser) continue;
|
|
10094
|
-
const relPath = toPosix(
|
|
10223
|
+
const relPath = toPosix(import_node_path26.default.relative(service.dir, file.path));
|
|
10095
10224
|
let defs;
|
|
10096
10225
|
try {
|
|
10097
10226
|
const tree = parseSource3(parser, file.content);
|
|
@@ -10151,7 +10280,7 @@ async function addSymbols(graph, services) {
|
|
|
10151
10280
|
|
|
10152
10281
|
// src/extract/symbol-edges.ts
|
|
10153
10282
|
init_cjs_shims();
|
|
10154
|
-
var
|
|
10283
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
10155
10284
|
var import_tree_sitter4 = __toESM(require("tree-sitter"), 1);
|
|
10156
10285
|
var import_types22 = require("@neat.is/types");
|
|
10157
10286
|
function extendsInfo(classHeritage) {
|
|
@@ -10258,10 +10387,10 @@ async function addSymbolEdges(graph, services) {
|
|
|
10258
10387
|
const tsPaths = await loadTsPathConfig(service.dir);
|
|
10259
10388
|
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
10260
10389
|
for (const file of files) {
|
|
10261
|
-
const parser = parserForExt5(
|
|
10390
|
+
const parser = parserForExt5(import_node_path27.default.extname(file.path));
|
|
10262
10391
|
if (!parser) continue;
|
|
10263
|
-
const relPath = toPosix(
|
|
10264
|
-
const fileDir =
|
|
10392
|
+
const relPath = toPosix(import_node_path27.default.relative(service.dir, file.path));
|
|
10393
|
+
const fileDir = import_node_path27.default.dirname(file.path);
|
|
10265
10394
|
let root;
|
|
10266
10395
|
try {
|
|
10267
10396
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -10396,7 +10525,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
10396
10525
|
|
|
10397
10526
|
// src/extract/actions.ts
|
|
10398
10527
|
init_cjs_shims();
|
|
10399
|
-
var
|
|
10528
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
10400
10529
|
var import_tree_sitter5 = __toESM(require("tree-sitter"), 1);
|
|
10401
10530
|
var import_types23 = require("@neat.is/types");
|
|
10402
10531
|
function stringLiteralText2(node) {
|
|
@@ -10543,9 +10672,9 @@ async function addServerActions(graph, services) {
|
|
|
10543
10672
|
const files = await loadSourceFiles(service.dir, service.excludeDirs);
|
|
10544
10673
|
for (const file of files) {
|
|
10545
10674
|
if (isTestPath(file.path)) continue;
|
|
10546
|
-
const parser = parserForExt5(
|
|
10675
|
+
const parser = parserForExt5(import_node_path28.default.extname(file.path));
|
|
10547
10676
|
if (!parser) continue;
|
|
10548
|
-
const relPath = toPosix(
|
|
10677
|
+
const relPath = toPosix(import_node_path28.default.relative(service.dir, file.path));
|
|
10549
10678
|
let root;
|
|
10550
10679
|
try {
|
|
10551
10680
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -10606,10 +10735,10 @@ async function addServerActions(graph, services) {
|
|
|
10606
10735
|
}
|
|
10607
10736
|
for (const file of files) {
|
|
10608
10737
|
if (isTestPath(file.path)) continue;
|
|
10609
|
-
const parser = parserForExt5(
|
|
10738
|
+
const parser = parserForExt5(import_node_path28.default.extname(file.path));
|
|
10610
10739
|
if (!parser) continue;
|
|
10611
|
-
const relPath = toPosix(
|
|
10612
|
-
const fileDir =
|
|
10740
|
+
const relPath = toPosix(import_node_path28.default.relative(service.dir, file.path));
|
|
10741
|
+
const fileDir = import_node_path28.default.dirname(file.path);
|
|
10613
10742
|
let root;
|
|
10614
10743
|
try {
|
|
10615
10744
|
root = parseSource3(parser, file.content).rootNode;
|
|
@@ -10662,14 +10791,14 @@ async function addServerActions(graph, services) {
|
|
|
10662
10791
|
|
|
10663
10792
|
// src/extract/databases/index.ts
|
|
10664
10793
|
init_cjs_shims();
|
|
10665
|
-
var
|
|
10794
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
10666
10795
|
var import_types24 = require("@neat.is/types");
|
|
10667
10796
|
|
|
10668
10797
|
// src/extract/databases/db-config-yaml.ts
|
|
10669
10798
|
init_cjs_shims();
|
|
10670
|
-
var
|
|
10799
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
10671
10800
|
async function parse(serviceDir) {
|
|
10672
|
-
const yamlPath =
|
|
10801
|
+
const yamlPath = import_node_path29.default.join(serviceDir, "db-config.yaml");
|
|
10673
10802
|
if (!await exists2(yamlPath)) return [];
|
|
10674
10803
|
const raw = await readYaml(yamlPath);
|
|
10675
10804
|
return [
|
|
@@ -10687,13 +10816,13 @@ var dbConfigYamlParser = { name: "db-config.yaml", parse };
|
|
|
10687
10816
|
|
|
10688
10817
|
// src/extract/databases/dotenv.ts
|
|
10689
10818
|
init_cjs_shims();
|
|
10690
|
-
var
|
|
10691
|
-
var
|
|
10819
|
+
var import_node_fs24 = require("fs");
|
|
10820
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
10692
10821
|
|
|
10693
10822
|
// src/extract/databases/shared.ts
|
|
10694
10823
|
init_cjs_shims();
|
|
10695
|
-
var
|
|
10696
|
-
var
|
|
10824
|
+
var import_node_fs23 = require("fs");
|
|
10825
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
10697
10826
|
function schemeToEngine(scheme) {
|
|
10698
10827
|
const s = scheme.toLowerCase().split("+")[0];
|
|
10699
10828
|
switch (s) {
|
|
@@ -10732,18 +10861,18 @@ function parseConnectionString(url) {
|
|
|
10732
10861
|
}
|
|
10733
10862
|
async function readIfExists(filePath) {
|
|
10734
10863
|
try {
|
|
10735
|
-
return await
|
|
10864
|
+
return await import_node_fs23.promises.readFile(filePath, "utf8");
|
|
10736
10865
|
} catch {
|
|
10737
10866
|
return null;
|
|
10738
10867
|
}
|
|
10739
10868
|
}
|
|
10740
10869
|
async function resolveEnvVar(serviceDir, name) {
|
|
10741
|
-
const entries = await
|
|
10870
|
+
const entries = await import_node_fs23.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
10742
10871
|
const envNames = entries.filter((e) => e.isFile() && (e.name === ".env" || e.name.startsWith(".env."))).map((e) => e.name);
|
|
10743
10872
|
const rank = (n) => n === ".env.local" ? 0 : n === ".env" ? 1 : 2;
|
|
10744
10873
|
envNames.sort((a, b) => rank(a) - rank(b) || a.localeCompare(b));
|
|
10745
10874
|
for (const fileName of envNames) {
|
|
10746
|
-
const content = await readIfExists(
|
|
10875
|
+
const content = await readIfExists(import_node_path30.default.join(serviceDir, fileName));
|
|
10747
10876
|
if (!content) continue;
|
|
10748
10877
|
for (const line of content.split("\n")) {
|
|
10749
10878
|
const trimmed = line.trim();
|
|
@@ -10762,7 +10891,7 @@ async function resolveEnvVar(serviceDir, name) {
|
|
|
10762
10891
|
}
|
|
10763
10892
|
async function findFirst(serviceDir, candidates) {
|
|
10764
10893
|
for (const rel of candidates) {
|
|
10765
|
-
const abs =
|
|
10894
|
+
const abs = import_node_path30.default.join(serviceDir, rel);
|
|
10766
10895
|
const content = await readIfExists(abs);
|
|
10767
10896
|
if (content !== null) return abs;
|
|
10768
10897
|
}
|
|
@@ -10820,15 +10949,15 @@ function parseDotenvLine(line) {
|
|
|
10820
10949
|
return { key, value };
|
|
10821
10950
|
}
|
|
10822
10951
|
async function parse2(serviceDir) {
|
|
10823
|
-
const entries = await
|
|
10952
|
+
const entries = await import_node_fs24.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
10824
10953
|
const configs = [];
|
|
10825
10954
|
const seen = /* @__PURE__ */ new Set();
|
|
10826
10955
|
for (const entry of entries) {
|
|
10827
10956
|
if (!entry.isFile()) continue;
|
|
10828
10957
|
const match = isConfigFile(entry.name);
|
|
10829
10958
|
if (!match.match || match.fileType !== "env") continue;
|
|
10830
|
-
const filePath =
|
|
10831
|
-
const content = await
|
|
10959
|
+
const filePath = import_node_path31.default.join(serviceDir, entry.name);
|
|
10960
|
+
const content = await import_node_fs24.promises.readFile(filePath, "utf8");
|
|
10832
10961
|
for (const line of content.split("\n")) {
|
|
10833
10962
|
const parsed = parseDotenvLine(line);
|
|
10834
10963
|
if (!parsed) continue;
|
|
@@ -10847,9 +10976,9 @@ var dotenvParser = { name: ".env", parse: parse2 };
|
|
|
10847
10976
|
|
|
10848
10977
|
// src/extract/databases/prisma.ts
|
|
10849
10978
|
init_cjs_shims();
|
|
10850
|
-
var
|
|
10979
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
10851
10980
|
async function parse3(serviceDir) {
|
|
10852
|
-
const schemaPath =
|
|
10981
|
+
const schemaPath = import_node_path32.default.join(serviceDir, "prisma", "schema.prisma");
|
|
10853
10982
|
const content = await readIfExists(schemaPath);
|
|
10854
10983
|
if (!content) return [];
|
|
10855
10984
|
const block = content.match(/datasource\s+\w+\s*\{([^}]*)\}/s);
|
|
@@ -11007,10 +11136,10 @@ var knexParser = { name: "knex", parse: parse5 };
|
|
|
11007
11136
|
|
|
11008
11137
|
// src/extract/databases/ormconfig.ts
|
|
11009
11138
|
init_cjs_shims();
|
|
11010
|
-
var
|
|
11139
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
11011
11140
|
async function parse6(serviceDir) {
|
|
11012
11141
|
for (const candidate of ["ormconfig.json", "ormconfig.yaml", "ormconfig.yml"]) {
|
|
11013
|
-
const abs =
|
|
11142
|
+
const abs = import_node_path33.default.join(serviceDir, candidate);
|
|
11014
11143
|
if (!await exists2(abs)) continue;
|
|
11015
11144
|
const raw = candidate.endsWith(".json") ? await readJson(abs) : await readYaml(abs);
|
|
11016
11145
|
const entries = Array.isArray(raw) ? raw : [raw];
|
|
@@ -11070,9 +11199,9 @@ var typeormParser = { name: "typeorm", parse: parse7 };
|
|
|
11070
11199
|
|
|
11071
11200
|
// src/extract/databases/sequelize.ts
|
|
11072
11201
|
init_cjs_shims();
|
|
11073
|
-
var
|
|
11202
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
11074
11203
|
async function parse8(serviceDir) {
|
|
11075
|
-
const configPath =
|
|
11204
|
+
const configPath = import_node_path34.default.join(serviceDir, "config", "config.json");
|
|
11076
11205
|
if (!await exists2(configPath)) return [];
|
|
11077
11206
|
const raw = await readJson(configPath);
|
|
11078
11207
|
const out = [];
|
|
@@ -11099,8 +11228,8 @@ var sequelizeParser = { name: "sequelize", parse: parse8 };
|
|
|
11099
11228
|
|
|
11100
11229
|
// src/extract/databases/csharp.ts
|
|
11101
11230
|
init_cjs_shims();
|
|
11102
|
-
var
|
|
11103
|
-
var
|
|
11231
|
+
var import_node_fs25 = require("fs");
|
|
11232
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
11104
11233
|
var CS_EXT = ".cs";
|
|
11105
11234
|
var NPGSQL_GATE = /\bUseNpgsql\b|\bNpgsql\b/;
|
|
11106
11235
|
var REDIS_GATE = /\bConnectionMultiplexer\b|\bStackExchange\.Redis\b|\bConfigurationOptions\.Parse\b|\bAddStackExchangeRedisCache\b/;
|
|
@@ -11147,12 +11276,12 @@ function parseRedisEndpoint(raw) {
|
|
|
11147
11276
|
return { host, port, database: "", engine: "redis", engineVersion: "unknown" };
|
|
11148
11277
|
}
|
|
11149
11278
|
async function resolveEnvUpTree(startDir, name) {
|
|
11150
|
-
let dir =
|
|
11279
|
+
let dir = import_node_path35.default.resolve(startDir);
|
|
11151
11280
|
for (let depth = 0; depth < 12; depth++) {
|
|
11152
11281
|
const value = await resolveEnvVar(dir, name);
|
|
11153
11282
|
if (value !== null) return value;
|
|
11154
|
-
const atRepoRoot = await
|
|
11155
|
-
const parent =
|
|
11283
|
+
const atRepoRoot = await import_node_fs25.promises.access(import_node_path35.default.join(dir, ".git")).then(() => true).catch(() => false);
|
|
11284
|
+
const parent = import_node_path35.default.dirname(dir);
|
|
11156
11285
|
if (atRepoRoot || parent === dir) break;
|
|
11157
11286
|
dir = parent;
|
|
11158
11287
|
}
|
|
@@ -11207,12 +11336,12 @@ async function resolveConfigs(literals, keys, serviceDir, looksLike, parse11) {
|
|
|
11207
11336
|
}
|
|
11208
11337
|
async function parse9(serviceDir) {
|
|
11209
11338
|
const files = (await walkSourceFiles(serviceDir).catch(() => [])).filter(
|
|
11210
|
-
(f) =>
|
|
11339
|
+
(f) => import_node_path35.default.extname(f) === CS_EXT
|
|
11211
11340
|
);
|
|
11212
11341
|
if (files.length === 0) return [];
|
|
11213
11342
|
const sources = [];
|
|
11214
11343
|
for (const file of files) {
|
|
11215
|
-
const content = await
|
|
11344
|
+
const content = await import_node_fs25.promises.readFile(file, "utf8").catch(() => null);
|
|
11216
11345
|
if (content !== null) sources.push({ file, content });
|
|
11217
11346
|
}
|
|
11218
11347
|
let pgGateFile = null;
|
|
@@ -11253,7 +11382,7 @@ var csharpParser = { name: "csharp", parse: parse9 };
|
|
|
11253
11382
|
|
|
11254
11383
|
// src/extract/databases/docker-compose.ts
|
|
11255
11384
|
init_cjs_shims();
|
|
11256
|
-
var
|
|
11385
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
11257
11386
|
function portFromService(svc) {
|
|
11258
11387
|
for (const raw of svc.ports ?? []) {
|
|
11259
11388
|
const str = String(raw);
|
|
@@ -11280,7 +11409,7 @@ function databaseFromEnv(svc) {
|
|
|
11280
11409
|
}
|
|
11281
11410
|
async function parse10(serviceDir) {
|
|
11282
11411
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
11283
|
-
const abs =
|
|
11412
|
+
const abs = import_node_path36.default.join(serviceDir, name);
|
|
11284
11413
|
if (!await exists2(abs)) continue;
|
|
11285
11414
|
const raw = await readYaml(abs);
|
|
11286
11415
|
if (!raw?.services) return [];
|
|
@@ -11453,7 +11582,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
11453
11582
|
discoveredVia: mergedDiscoveredVia
|
|
11454
11583
|
});
|
|
11455
11584
|
}
|
|
11456
|
-
const relConfigFile = toPosix(
|
|
11585
|
+
const relConfigFile = toPosix(import_node_path37.default.relative(service.dir, config.sourceFile));
|
|
11457
11586
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
11458
11587
|
graph,
|
|
11459
11588
|
service.pkg.name,
|
|
@@ -11462,7 +11591,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
11462
11591
|
);
|
|
11463
11592
|
nodesAdded += fn;
|
|
11464
11593
|
edgesAdded += fe;
|
|
11465
|
-
const evidenceFile = toPosix(
|
|
11594
|
+
const evidenceFile = toPosix(import_node_path37.default.relative(scanPath, config.sourceFile));
|
|
11466
11595
|
const edge = {
|
|
11467
11596
|
id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id, import_types24.EdgeType.CONNECTS_TO),
|
|
11468
11597
|
source: fileNodeId,
|
|
@@ -11483,15 +11612,15 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
11483
11612
|
if (allConfigs.length === 1) {
|
|
11484
11613
|
const primary = allConfigs[0];
|
|
11485
11614
|
service.node.dbConnectionTarget = primary.port ? `${primary.host}:${primary.port}` : primary.host;
|
|
11486
|
-
const relPath =
|
|
11615
|
+
const relPath = import_node_path37.default.relative(scanPath, primary.sourceFile);
|
|
11487
11616
|
const cfgId = (0, import_types24.configId)(relPath);
|
|
11488
11617
|
if (!graph.hasNode(cfgId)) {
|
|
11489
11618
|
const cfgNode = {
|
|
11490
11619
|
id: cfgId,
|
|
11491
11620
|
type: import_types24.NodeType.ConfigNode,
|
|
11492
|
-
name:
|
|
11621
|
+
name: import_node_path37.default.basename(primary.sourceFile),
|
|
11493
11622
|
path: relPath,
|
|
11494
|
-
fileType: isConfigFile(
|
|
11623
|
+
fileType: isConfigFile(import_node_path37.default.basename(primary.sourceFile)).fileType || "config"
|
|
11495
11624
|
};
|
|
11496
11625
|
graph.addNode(cfgId, cfgNode);
|
|
11497
11626
|
nodesAdded++;
|
|
@@ -11532,19 +11661,19 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
11532
11661
|
|
|
11533
11662
|
// src/extract/configs.ts
|
|
11534
11663
|
init_cjs_shims();
|
|
11535
|
-
var
|
|
11536
|
-
var
|
|
11664
|
+
var import_node_fs26 = require("fs");
|
|
11665
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
11537
11666
|
var import_types25 = require("@neat.is/types");
|
|
11538
11667
|
async function walkConfigFiles(dir, excludeDirs = []) {
|
|
11539
|
-
const excluded = new Set(excludeDirs.map((d) =>
|
|
11668
|
+
const excluded = new Set(excludeDirs.map((d) => import_node_path38.default.resolve(d)));
|
|
11540
11669
|
const out = [];
|
|
11541
11670
|
async function walk11(current) {
|
|
11542
|
-
const entries = await
|
|
11671
|
+
const entries = await import_node_fs26.promises.readdir(current, { withFileTypes: true });
|
|
11543
11672
|
for (const entry of entries) {
|
|
11544
|
-
const full =
|
|
11673
|
+
const full = import_node_path38.default.join(current, entry.name);
|
|
11545
11674
|
if (entry.isDirectory()) {
|
|
11546
11675
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
11547
|
-
if (excluded.has(
|
|
11676
|
+
if (excluded.has(import_node_path38.default.resolve(full))) continue;
|
|
11548
11677
|
if (await isPythonVenvDir(full)) continue;
|
|
11549
11678
|
await walk11(full);
|
|
11550
11679
|
} else if (entry.isFile() && isConfigFile(entry.name).match) {
|
|
@@ -11561,19 +11690,19 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
11561
11690
|
for (const service of services) {
|
|
11562
11691
|
const configFiles = await walkConfigFiles(service.dir, service.excludeDirs);
|
|
11563
11692
|
for (const file of configFiles) {
|
|
11564
|
-
const relPath =
|
|
11693
|
+
const relPath = import_node_path38.default.relative(scanPath, file);
|
|
11565
11694
|
const node = {
|
|
11566
11695
|
id: (0, import_types25.configId)(relPath),
|
|
11567
11696
|
type: import_types25.NodeType.ConfigNode,
|
|
11568
|
-
name:
|
|
11697
|
+
name: import_node_path38.default.basename(file),
|
|
11569
11698
|
path: relPath,
|
|
11570
|
-
fileType: isConfigFile(
|
|
11699
|
+
fileType: isConfigFile(import_node_path38.default.basename(file)).fileType
|
|
11571
11700
|
};
|
|
11572
11701
|
if (!graph.hasNode(node.id)) {
|
|
11573
11702
|
graph.addNode(node.id, node);
|
|
11574
11703
|
nodesAdded++;
|
|
11575
11704
|
}
|
|
11576
|
-
const relToService = toPosix(
|
|
11705
|
+
const relToService = toPosix(import_node_path38.default.relative(service.dir, file));
|
|
11577
11706
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
11578
11707
|
graph,
|
|
11579
11708
|
service.pkg.name,
|
|
@@ -11589,7 +11718,7 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
11589
11718
|
type: import_types25.EdgeType.CONFIGURED_BY,
|
|
11590
11719
|
provenance: import_types25.Provenance.EXTRACTED,
|
|
11591
11720
|
confidence: (0, import_types25.confidenceForExtracted)("structural"),
|
|
11592
|
-
evidence: { file: relPath.split(
|
|
11721
|
+
evidence: { file: relPath.split(import_node_path38.default.sep).join("/") }
|
|
11593
11722
|
};
|
|
11594
11723
|
if (!graph.hasEdge(edge.id)) {
|
|
11595
11724
|
graph.addEdgeWithKey(edge.id, edge.source, edge.target, edge);
|
|
@@ -11602,8 +11731,8 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
11602
11731
|
|
|
11603
11732
|
// src/extract/proto.ts
|
|
11604
11733
|
init_cjs_shims();
|
|
11605
|
-
var
|
|
11606
|
-
var
|
|
11734
|
+
var import_node_fs27 = require("fs");
|
|
11735
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
11607
11736
|
var import_types26 = require("@neat.is/types");
|
|
11608
11737
|
var PROTO_EXTENSION = ".proto";
|
|
11609
11738
|
function packageOf(content) {
|
|
@@ -11641,18 +11770,18 @@ function grpcMethodsFromProto(content, fqPackage) {
|
|
|
11641
11770
|
return out;
|
|
11642
11771
|
}
|
|
11643
11772
|
async function walkProtoFiles(dir, excludeDirs = []) {
|
|
11644
|
-
const excluded = new Set(excludeDirs.map((d) =>
|
|
11773
|
+
const excluded = new Set(excludeDirs.map((d) => import_node_path39.default.resolve(d)));
|
|
11645
11774
|
const out = [];
|
|
11646
11775
|
async function walk11(current) {
|
|
11647
|
-
const entries = await
|
|
11776
|
+
const entries = await import_node_fs27.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
11648
11777
|
for (const entry of entries) {
|
|
11649
|
-
const full =
|
|
11778
|
+
const full = import_node_path39.default.join(current, entry.name);
|
|
11650
11779
|
if (entry.isDirectory()) {
|
|
11651
11780
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
11652
|
-
if (excluded.has(
|
|
11781
|
+
if (excluded.has(import_node_path39.default.resolve(full))) continue;
|
|
11653
11782
|
if (await isPythonVenvDir(full)) continue;
|
|
11654
11783
|
await walk11(full);
|
|
11655
|
-
} else if (entry.isFile() &&
|
|
11784
|
+
} else if (entry.isFile() && import_node_path39.default.extname(entry.name) === PROTO_EXTENSION) {
|
|
11656
11785
|
out.push(full);
|
|
11657
11786
|
}
|
|
11658
11787
|
}
|
|
@@ -11667,10 +11796,10 @@ async function addGrpcMethods(graph, services) {
|
|
|
11667
11796
|
const protoPaths = await walkProtoFiles(service.dir, service.excludeDirs);
|
|
11668
11797
|
for (const protoPath of protoPaths) {
|
|
11669
11798
|
if (isTestPath(protoPath)) continue;
|
|
11670
|
-
const relFile = toPosix(
|
|
11799
|
+
const relFile = toPosix(import_node_path39.default.relative(service.dir, protoPath));
|
|
11671
11800
|
let content;
|
|
11672
11801
|
try {
|
|
11673
|
-
content = await
|
|
11802
|
+
content = await import_node_fs27.promises.readFile(protoPath, "utf8");
|
|
11674
11803
|
} catch (err) {
|
|
11675
11804
|
recordExtractionError("proto extraction", protoPath, err);
|
|
11676
11805
|
continue;
|
|
@@ -11729,7 +11858,7 @@ var import_types46 = require("@neat.is/types");
|
|
|
11729
11858
|
|
|
11730
11859
|
// src/extract/calls/http.ts
|
|
11731
11860
|
init_cjs_shims();
|
|
11732
|
-
var
|
|
11861
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
11733
11862
|
var import_tree_sitter6 = __toESM(require("tree-sitter"), 1);
|
|
11734
11863
|
var import_tree_sitter_javascript4 = __toESM(require("tree-sitter-javascript"), 1);
|
|
11735
11864
|
var import_tree_sitter_typescript2 = __toESM(require("tree-sitter-typescript"), 1);
|
|
@@ -11812,7 +11941,7 @@ async function addHttpCallEdges(graph, services) {
|
|
|
11812
11941
|
const seen = /* @__PURE__ */ new Set();
|
|
11813
11942
|
for (const file of files) {
|
|
11814
11943
|
if (isTestPath(file.path)) continue;
|
|
11815
|
-
const parser = parserForExt(
|
|
11944
|
+
const parser = parserForExt(import_node_path40.default.extname(file.path), parserCache);
|
|
11816
11945
|
let sites;
|
|
11817
11946
|
try {
|
|
11818
11947
|
sites = callsFromSource(file.content, parser, knownHosts);
|
|
@@ -11821,7 +11950,7 @@ async function addHttpCallEdges(graph, services) {
|
|
|
11821
11950
|
continue;
|
|
11822
11951
|
}
|
|
11823
11952
|
if (sites.length === 0) continue;
|
|
11824
|
-
const relFile = toPosix(
|
|
11953
|
+
const relFile = toPosix(import_node_path40.default.relative(service.dir, file.path));
|
|
11825
11954
|
for (const site of sites) {
|
|
11826
11955
|
const targetId = hostToNodeId.get(site.host);
|
|
11827
11956
|
if (!targetId || targetId === service.node.id) continue;
|
|
@@ -11875,7 +12004,7 @@ async function addHttpCallEdges(graph, services) {
|
|
|
11875
12004
|
|
|
11876
12005
|
// src/extract/calls/route-match.ts
|
|
11877
12006
|
init_cjs_shims();
|
|
11878
|
-
var
|
|
12007
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
11879
12008
|
var import_tree_sitter7 = __toESM(require("tree-sitter"), 1);
|
|
11880
12009
|
var import_tree_sitter_javascript5 = __toESM(require("tree-sitter-javascript"), 1);
|
|
11881
12010
|
var import_types28 = require("@neat.is/types");
|
|
@@ -12153,7 +12282,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
12153
12282
|
const seen = /* @__PURE__ */ new Set();
|
|
12154
12283
|
for (const file of files) {
|
|
12155
12284
|
if (isTestPath(file.path)) continue;
|
|
12156
|
-
if (!JS_CLIENT_EXTENSIONS.has(
|
|
12285
|
+
if (!JS_CLIENT_EXTENSIONS.has(import_node_path41.default.extname(file.path))) continue;
|
|
12157
12286
|
let sites;
|
|
12158
12287
|
try {
|
|
12159
12288
|
sites = clientCallSitesFromSource(file.content, jsParser, knownHosts);
|
|
@@ -12162,7 +12291,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
12162
12291
|
continue;
|
|
12163
12292
|
}
|
|
12164
12293
|
if (sites.length === 0) continue;
|
|
12165
|
-
const relFile = toPosix(
|
|
12294
|
+
const relFile = toPosix(import_node_path41.default.relative(service.dir, file.path));
|
|
12166
12295
|
for (const site of sites) {
|
|
12167
12296
|
if (site.host === null) {
|
|
12168
12297
|
const dedupKey2 = `${relFile}|unresolved-host`;
|
|
@@ -12255,7 +12384,7 @@ async function addRouteCallEdges(graph, services) {
|
|
|
12255
12384
|
|
|
12256
12385
|
// src/extract/calls/kafka.ts
|
|
12257
12386
|
init_cjs_shims();
|
|
12258
|
-
var
|
|
12387
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
12259
12388
|
var import_types29 = require("@neat.is/types");
|
|
12260
12389
|
var PRODUCER_TOPIC_RE = /(?:producer|kafkaProducer)[\s\S]{0,40}?\.send\s*\(\s*\{[\s\S]{0,200}?topic\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
12261
12390
|
var CONSUMER_TOPIC_RE = /(?:consumer|kafkaConsumer)[\s\S]{0,40}?\.(?:subscribe|run)\s*\(\s*\{[\s\S]{0,200}?topic[s]?\s*:\s*(?:\[\s*)?['"`]([^'"`]+)['"`]/g;
|
|
@@ -12343,13 +12472,13 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
12343
12472
|
// call sites — verified-call-site tier (ADR-066).
|
|
12344
12473
|
confidenceKind: "verified-call-site",
|
|
12345
12474
|
evidence: {
|
|
12346
|
-
file:
|
|
12475
|
+
file: import_node_path42.default.relative(serviceDir, file.path),
|
|
12347
12476
|
line,
|
|
12348
12477
|
snippet: snippet(file.content, line)
|
|
12349
12478
|
}
|
|
12350
12479
|
});
|
|
12351
12480
|
};
|
|
12352
|
-
if (
|
|
12481
|
+
if (import_node_path42.default.extname(file.path) === ".go") {
|
|
12353
12482
|
goSaramaEndpoints(file.content, make);
|
|
12354
12483
|
} else {
|
|
12355
12484
|
for (const { topic } of findAll(PRODUCER_TOPIC_RE, file.content)) make(topic, "PUBLISHES_TO");
|
|
@@ -12360,7 +12489,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
12360
12489
|
|
|
12361
12490
|
// src/extract/calls/redis.ts
|
|
12362
12491
|
init_cjs_shims();
|
|
12363
|
-
var
|
|
12492
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
12364
12493
|
var import_types30 = require("@neat.is/types");
|
|
12365
12494
|
var REDIS_URL_RE = /redis(?:s)?:\/\/(?:[^@'"`\s]+@)?([^:/'"`\s]+)(?::(\d+))?/g;
|
|
12366
12495
|
function redisEndpointsFromFile(file, serviceDir) {
|
|
@@ -12383,7 +12512,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
12383
12512
|
// support tier (ADR-066).
|
|
12384
12513
|
confidenceKind: "url-with-structural-support",
|
|
12385
12514
|
evidence: {
|
|
12386
|
-
file:
|
|
12515
|
+
file: import_node_path43.default.relative(serviceDir, file.path),
|
|
12387
12516
|
line,
|
|
12388
12517
|
snippet: snippet(file.content, line)
|
|
12389
12518
|
}
|
|
@@ -12394,7 +12523,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
12394
12523
|
|
|
12395
12524
|
// src/extract/calls/aws.ts
|
|
12396
12525
|
init_cjs_shims();
|
|
12397
|
-
var
|
|
12526
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
12398
12527
|
var import_types31 = require("@neat.is/types");
|
|
12399
12528
|
var S3_BUCKET_RE = /Bucket\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
12400
12529
|
var DYNAMO_TABLE_RE = /TableName\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
@@ -12428,7 +12557,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
12428
12557
|
// (ADR-066).
|
|
12429
12558
|
confidenceKind: "verified-call-site",
|
|
12430
12559
|
evidence: {
|
|
12431
|
-
file:
|
|
12560
|
+
file: import_node_path44.default.relative(serviceDir, file.path),
|
|
12432
12561
|
line,
|
|
12433
12562
|
snippet: snippet(file.content, line)
|
|
12434
12563
|
}
|
|
@@ -12453,7 +12582,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
12453
12582
|
|
|
12454
12583
|
// src/extract/calls/grpc.ts
|
|
12455
12584
|
init_cjs_shims();
|
|
12456
|
-
var
|
|
12585
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
12457
12586
|
var import_types32 = require("@neat.is/types");
|
|
12458
12587
|
var GRPC_CLIENT_RE = /new\s+([A-Z][A-Za-z0-9_]*)Client\s*\(\s*['"`]?([^,'"`)]+)?/g;
|
|
12459
12588
|
var AWS_SDK_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@aws-sdk\/client-([a-z0-9-]+)['"`]/g;
|
|
@@ -12512,7 +12641,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
12512
12641
|
// tier (ADR-066).
|
|
12513
12642
|
confidenceKind: "verified-call-site",
|
|
12514
12643
|
evidence: {
|
|
12515
|
-
file:
|
|
12644
|
+
file: import_node_path45.default.relative(serviceDir, file.path),
|
|
12516
12645
|
line,
|
|
12517
12646
|
snippet: snippet(file.content, line)
|
|
12518
12647
|
}
|
|
@@ -12523,7 +12652,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
12523
12652
|
|
|
12524
12653
|
// src/extract/calls/supabase.ts
|
|
12525
12654
|
init_cjs_shims();
|
|
12526
|
-
var
|
|
12655
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
12527
12656
|
var import_types33 = require("@neat.is/types");
|
|
12528
12657
|
var SUPABASE_JS_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/supabase-js['"`]/;
|
|
12529
12658
|
var SUPABASE_SSR_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/ssr['"`]/;
|
|
@@ -12582,7 +12711,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
12582
12711
|
// tier (ADR-066), the same grade aws.ts / grpc.ts emit at.
|
|
12583
12712
|
confidenceKind: "verified-call-site",
|
|
12584
12713
|
evidence: {
|
|
12585
|
-
file:
|
|
12714
|
+
file: import_node_path46.default.relative(serviceDir, file.path),
|
|
12586
12715
|
line,
|
|
12587
12716
|
snippet: snippet(file.content, line)
|
|
12588
12717
|
}
|
|
@@ -12609,7 +12738,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
12609
12738
|
edgeType: "CALLS",
|
|
12610
12739
|
confidenceKind: "verified-call-site",
|
|
12611
12740
|
evidence: {
|
|
12612
|
-
file:
|
|
12741
|
+
file: import_node_path46.default.relative(serviceDir, file.path),
|
|
12613
12742
|
line,
|
|
12614
12743
|
snippet: snippet(file.content, line)
|
|
12615
12744
|
}
|
|
@@ -12621,7 +12750,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
12621
12750
|
|
|
12622
12751
|
// src/extract/calls/firestore.ts
|
|
12623
12752
|
init_cjs_shims();
|
|
12624
|
-
var
|
|
12753
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
12625
12754
|
var import_tree_sitter8 = __toESM(require("tree-sitter"), 1);
|
|
12626
12755
|
var import_tree_sitter_javascript6 = __toESM(require("tree-sitter-javascript"), 1);
|
|
12627
12756
|
var import_types34 = require("@neat.is/types");
|
|
@@ -12794,7 +12923,7 @@ function firestoreEndpointsFromFile(file, serviceDir, imported) {
|
|
|
12794
12923
|
if (!hasClient && !hasAdmin && importedNames.size === 0) return [];
|
|
12795
12924
|
const ownSdk = hasClient && !hasAdmin ? "client" : hasAdmin && !hasClient ? "admin" : null;
|
|
12796
12925
|
const fileSdk = !hasClient && !hasAdmin ? imported?.sdk ?? null : ownSdk;
|
|
12797
|
-
const tree = parseSource3(parserForExt2(
|
|
12926
|
+
const tree = parseSource3(parserForExt2(import_node_path47.default.extname(file.path)), file.content);
|
|
12798
12927
|
const clientVars = firestoreClientVars(tree.rootNode);
|
|
12799
12928
|
for (const n of importedNames) clientVars.add(n);
|
|
12800
12929
|
const collLine = /* @__PURE__ */ new Map();
|
|
@@ -12899,7 +13028,7 @@ function firestoreEndpointsFromFile(file, serviceDir, imported) {
|
|
|
12899
13028
|
...columnSet.size > 0 ? { columns: [...columnSet] } : {},
|
|
12900
13029
|
...sdkWrites ? { sdkWrites } : {},
|
|
12901
13030
|
evidence: {
|
|
12902
|
-
file:
|
|
13031
|
+
file: import_node_path47.default.relative(serviceDir, file.path),
|
|
12903
13032
|
line,
|
|
12904
13033
|
snippet: snippet(file.content, line)
|
|
12905
13034
|
}
|
|
@@ -12959,7 +13088,7 @@ function sdkOf(content) {
|
|
|
12959
13088
|
return hasClient && !hasAdmin ? "client" : hasAdmin && !hasClient ? "admin" : null;
|
|
12960
13089
|
}
|
|
12961
13090
|
function parseOrNull(file) {
|
|
12962
|
-
const ext =
|
|
13091
|
+
const ext = import_node_path47.default.extname(file.path);
|
|
12963
13092
|
if (!(ext in GRAMMAR_BY_EXT)) return null;
|
|
12964
13093
|
try {
|
|
12965
13094
|
return parseSource3(parserForExt2(ext), file.content).rootNode;
|
|
@@ -12975,7 +13104,7 @@ async function firestoreCrossFileEndpoints(files, serviceDir) {
|
|
|
12975
13104
|
if (!root) continue;
|
|
12976
13105
|
const names = exportedFirestoreClients(root);
|
|
12977
13106
|
if (names.size === 0) continue;
|
|
12978
|
-
registry.set(toPosix(
|
|
13107
|
+
registry.set(toPosix(import_node_path47.default.relative(serviceDir, f.path)), { names, sdk: sdkOf(f.content) });
|
|
12979
13108
|
}
|
|
12980
13109
|
if (registry.size === 0) return [];
|
|
12981
13110
|
const out = [];
|
|
@@ -12988,7 +13117,7 @@ async function firestoreCrossFileEndpoints(files, serviceDir) {
|
|
|
12988
13117
|
const names = /* @__PURE__ */ new Set();
|
|
12989
13118
|
let sdk = null;
|
|
12990
13119
|
for (const b of bindings) {
|
|
12991
|
-
const rel = await resolveJsImport(b.specifier,
|
|
13120
|
+
const rel = await resolveJsImport(b.specifier, import_node_path47.default.dirname(f.path), serviceDir, null);
|
|
12992
13121
|
if (!rel) continue;
|
|
12993
13122
|
const entry = registry.get(rel);
|
|
12994
13123
|
if (!entry || !entry.names.has(b.imported)) continue;
|
|
@@ -13003,7 +13132,7 @@ async function firestoreCrossFileEndpoints(files, serviceDir) {
|
|
|
13003
13132
|
|
|
13004
13133
|
// src/extract/calls/mongoose.ts
|
|
13005
13134
|
init_cjs_shims();
|
|
13006
|
-
var
|
|
13135
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
13007
13136
|
var import_types35 = require("@neat.is/types");
|
|
13008
13137
|
var MONGOOSE_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongoose['"`]/;
|
|
13009
13138
|
var MONGODB_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongodb['"`]/;
|
|
@@ -13154,7 +13283,7 @@ function endpoint(r, file, serviceDir, matchText) {
|
|
|
13154
13283
|
kind: r.kind,
|
|
13155
13284
|
edgeType: "CALLS",
|
|
13156
13285
|
confidenceKind: "verified-call-site",
|
|
13157
|
-
evidence: { file:
|
|
13286
|
+
evidence: { file: import_node_path48.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
13158
13287
|
};
|
|
13159
13288
|
}
|
|
13160
13289
|
function mongooseEndpointsFromFile(file, serviceDir) {
|
|
@@ -13244,7 +13373,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
13244
13373
|
const registry = /* @__PURE__ */ new Map();
|
|
13245
13374
|
for (const f of mongooseFiles) {
|
|
13246
13375
|
const fx = fileExportsOf(f.content, pluralizeOn);
|
|
13247
|
-
if (fx) registry.set(toPosix(
|
|
13376
|
+
if (fx) registry.set(toPosix(import_node_path48.default.relative(serviceDir, f.path)), fx);
|
|
13248
13377
|
}
|
|
13249
13378
|
if (registry.size === 0) return [];
|
|
13250
13379
|
const out = [];
|
|
@@ -13255,7 +13384,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
13255
13384
|
const directColl = /* @__PURE__ */ new Map();
|
|
13256
13385
|
const nsExports = /* @__PURE__ */ new Map();
|
|
13257
13386
|
for (const b of bindings) {
|
|
13258
|
-
const resolvedRel = await resolveJsImport(b.specifier,
|
|
13387
|
+
const resolvedRel = await resolveJsImport(b.specifier, import_node_path48.default.dirname(f.path), serviceDir, null);
|
|
13259
13388
|
if (!resolvedRel) continue;
|
|
13260
13389
|
const fx = registry.get(resolvedRel);
|
|
13261
13390
|
if (!fx) continue;
|
|
@@ -13299,7 +13428,7 @@ async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
|
13299
13428
|
|
|
13300
13429
|
// src/extract/calls/sqlalchemy.ts
|
|
13301
13430
|
init_cjs_shims();
|
|
13302
|
-
var
|
|
13431
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
13303
13432
|
var import_tree_sitter9 = __toESM(require("tree-sitter"), 1);
|
|
13304
13433
|
var import_tree_sitter_python5 = __toESM(require("tree-sitter-python"), 1);
|
|
13305
13434
|
var import_types36 = require("@neat.is/types");
|
|
@@ -13438,7 +13567,7 @@ function sqlalchemyForeignKeys(file, serviceDir) {
|
|
|
13438
13567
|
childTable,
|
|
13439
13568
|
parentTable,
|
|
13440
13569
|
evidence: {
|
|
13441
|
-
file:
|
|
13570
|
+
file: import_node_path49.default.relative(serviceDir, file.path),
|
|
13442
13571
|
line,
|
|
13443
13572
|
snippet: snippet(file.content, line)
|
|
13444
13573
|
}
|
|
@@ -13463,7 +13592,7 @@ function sqlalchemyEndpointsFromFile(file, serviceDir) {
|
|
|
13463
13592
|
confidenceKind: "verified-call-site",
|
|
13464
13593
|
...columns && columns.length > 0 ? { columns } : {},
|
|
13465
13594
|
evidence: {
|
|
13466
|
-
file:
|
|
13595
|
+
file: import_node_path49.default.relative(serviceDir, file.path),
|
|
13467
13596
|
line,
|
|
13468
13597
|
snippet: snippet(file.content, line)
|
|
13469
13598
|
}
|
|
@@ -13570,7 +13699,7 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
|
|
|
13570
13699
|
edgeType: "CALLS",
|
|
13571
13700
|
confidenceKind: "verified-call-site",
|
|
13572
13701
|
evidence: {
|
|
13573
|
-
file:
|
|
13702
|
+
file: import_node_path49.default.relative(serviceDir, file.path),
|
|
13574
13703
|
line,
|
|
13575
13704
|
snippet: snippet(file.content, line)
|
|
13576
13705
|
}
|
|
@@ -13582,7 +13711,7 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
|
|
|
13582
13711
|
|
|
13583
13712
|
// src/extract/calls/socket.ts
|
|
13584
13713
|
init_cjs_shims();
|
|
13585
|
-
var
|
|
13714
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
13586
13715
|
var import_tree_sitter10 = __toESM(require("tree-sitter"), 1);
|
|
13587
13716
|
var import_tree_sitter_python6 = __toESM(require("tree-sitter-python"), 1);
|
|
13588
13717
|
var import_types37 = require("@neat.is/types");
|
|
@@ -13658,7 +13787,7 @@ function socketEndpointsFromFile(file, serviceDir) {
|
|
|
13658
13787
|
// A verified `socket.socket(...)` + `.connect((host, port))` call site.
|
|
13659
13788
|
confidenceKind: "verified-call-site",
|
|
13660
13789
|
evidence: {
|
|
13661
|
-
file:
|
|
13790
|
+
file: import_node_path50.default.relative(serviceDir, file.path),
|
|
13662
13791
|
line,
|
|
13663
13792
|
snippet: snippet(file.content, line)
|
|
13664
13793
|
}
|
|
@@ -13669,7 +13798,7 @@ function socketEndpointsFromFile(file, serviceDir) {
|
|
|
13669
13798
|
|
|
13670
13799
|
// src/extract/calls/django-orm.ts
|
|
13671
13800
|
init_cjs_shims();
|
|
13672
|
-
var
|
|
13801
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
13673
13802
|
var import_tree_sitter11 = __toESM(require("tree-sitter"), 1);
|
|
13674
13803
|
var import_tree_sitter_python7 = __toESM(require("tree-sitter-python"), 1);
|
|
13675
13804
|
var import_types38 = require("@neat.is/types");
|
|
@@ -13739,7 +13868,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
13739
13868
|
const tree = parseSource8(makePyParser5(), file.content);
|
|
13740
13869
|
const out = [];
|
|
13741
13870
|
const seen = /* @__PURE__ */ new Set();
|
|
13742
|
-
const defaultAppLabel =
|
|
13871
|
+
const defaultAppLabel = import_node_path51.default.basename(import_node_path51.default.dirname(file.path));
|
|
13743
13872
|
walk5(tree.rootNode, (node) => {
|
|
13744
13873
|
if (node.type !== "class_definition") return;
|
|
13745
13874
|
if (!extendsDjangoModel(node)) return;
|
|
@@ -13757,7 +13886,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
13757
13886
|
kind: "sql-table",
|
|
13758
13887
|
edgeType: "CALLS",
|
|
13759
13888
|
confidenceKind: "verified-call-site",
|
|
13760
|
-
evidence: { file:
|
|
13889
|
+
evidence: { file: import_node_path51.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
13761
13890
|
});
|
|
13762
13891
|
});
|
|
13763
13892
|
return out;
|
|
@@ -13765,7 +13894,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
|
|
|
13765
13894
|
|
|
13766
13895
|
// src/extract/calls/drizzle.ts
|
|
13767
13896
|
init_cjs_shims();
|
|
13768
|
-
var
|
|
13897
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
13769
13898
|
var import_tree_sitter12 = __toESM(require("tree-sitter"), 1);
|
|
13770
13899
|
var import_tree_sitter_javascript7 = __toESM(require("tree-sitter-javascript"), 1);
|
|
13771
13900
|
var import_types39 = require("@neat.is/types");
|
|
@@ -13843,7 +13972,7 @@ function columnsFromObject(obj) {
|
|
|
13843
13972
|
}
|
|
13844
13973
|
function drizzleEndpointsFromFile(file, serviceDir) {
|
|
13845
13974
|
if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
|
|
13846
|
-
const tree = parseSource3(parserForExt3(
|
|
13975
|
+
const tree = parseSource3(parserForExt3(import_node_path52.default.extname(file.path)), file.content);
|
|
13847
13976
|
const out = [];
|
|
13848
13977
|
const seen = /* @__PURE__ */ new Set();
|
|
13849
13978
|
const walk11 = (node) => {
|
|
@@ -13866,7 +13995,7 @@ function drizzleEndpointsFromFile(file, serviceDir) {
|
|
|
13866
13995
|
confidenceKind: "structural",
|
|
13867
13996
|
columns,
|
|
13868
13997
|
evidence: {
|
|
13869
|
-
file:
|
|
13998
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
13870
13999
|
line,
|
|
13871
14000
|
snippet: snippet(file.content, line)
|
|
13872
14001
|
}
|
|
@@ -13932,7 +14061,7 @@ function referencesTargetVar(call) {
|
|
|
13932
14061
|
}
|
|
13933
14062
|
function drizzleForeignKeys(file, serviceDir) {
|
|
13934
14063
|
if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
|
|
13935
|
-
const tree = parseSource3(parserForExt3(
|
|
14064
|
+
const tree = parseSource3(parserForExt3(import_node_path52.default.extname(file.path)), file.content);
|
|
13936
14065
|
const { tables, varToTable } = collectDrizzleTables(tree.rootNode);
|
|
13937
14066
|
const out = [];
|
|
13938
14067
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -13951,7 +14080,7 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
13951
14080
|
childTable: table.tableName,
|
|
13952
14081
|
parentTable,
|
|
13953
14082
|
evidence: {
|
|
13954
|
-
file:
|
|
14083
|
+
file: import_node_path52.default.relative(serviceDir, file.path),
|
|
13955
14084
|
line,
|
|
13956
14085
|
snippet: snippet(file.content, line)
|
|
13957
14086
|
}
|
|
@@ -13968,7 +14097,7 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
13968
14097
|
|
|
13969
14098
|
// src/extract/calls/prisma.ts
|
|
13970
14099
|
init_cjs_shims();
|
|
13971
|
-
var
|
|
14100
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
13972
14101
|
var import_types40 = require("@neat.is/types");
|
|
13973
14102
|
var SCALAR_TYPES = /* @__PURE__ */ new Set([
|
|
13974
14103
|
"Int",
|
|
@@ -14024,7 +14153,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
|
|
|
14024
14153
|
confidenceKind: "structural",
|
|
14025
14154
|
columns: b.columns,
|
|
14026
14155
|
evidence: {
|
|
14027
|
-
file:
|
|
14156
|
+
file: import_node_path53.default.relative(serviceDir, file.path),
|
|
14028
14157
|
line: b.startLine,
|
|
14029
14158
|
snippet: snippet(content, b.startLine)
|
|
14030
14159
|
}
|
|
@@ -14085,7 +14214,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
|
|
|
14085
14214
|
}
|
|
14086
14215
|
async function prismaColumnEndpoints(serviceDir) {
|
|
14087
14216
|
const schemaPath = await findFirst(serviceDir, [
|
|
14088
|
-
|
|
14217
|
+
import_node_path53.default.join("prisma", "schema.prisma"),
|
|
14089
14218
|
"schema.prisma"
|
|
14090
14219
|
]);
|
|
14091
14220
|
if (!schemaPath) return [];
|
|
@@ -14160,7 +14289,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
|
|
|
14160
14289
|
childTable: current.table,
|
|
14161
14290
|
parentTable,
|
|
14162
14291
|
evidence: {
|
|
14163
|
-
file:
|
|
14292
|
+
file: import_node_path53.default.relative(serviceDir, file.path),
|
|
14164
14293
|
line: lineNo,
|
|
14165
14294
|
snippet: snippet(content, lineNo)
|
|
14166
14295
|
}
|
|
@@ -14175,7 +14304,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
|
|
|
14175
14304
|
}
|
|
14176
14305
|
async function prismaForeignKeys(serviceDir) {
|
|
14177
14306
|
const schemaPath = await findFirst(serviceDir, [
|
|
14178
|
-
|
|
14307
|
+
import_node_path53.default.join("prisma", "schema.prisma"),
|
|
14179
14308
|
"schema.prisma"
|
|
14180
14309
|
]);
|
|
14181
14310
|
if (!schemaPath) return [];
|
|
@@ -14186,7 +14315,7 @@ async function prismaForeignKeys(serviceDir) {
|
|
|
14186
14315
|
|
|
14187
14316
|
// src/extract/calls/activerecord.ts
|
|
14188
14317
|
init_cjs_shims();
|
|
14189
|
-
var
|
|
14318
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
14190
14319
|
var import_tree_sitter13 = __toESM(require("tree-sitter"), 1);
|
|
14191
14320
|
var import_tree_sitter_ruby3 = __toESM(require("tree-sitter-ruby"), 1);
|
|
14192
14321
|
var import_types41 = require("@neat.is/types");
|
|
@@ -14394,7 +14523,7 @@ function railsSchemaEndpointsFromFile(file, serviceDir) {
|
|
|
14394
14523
|
confidenceKind: "structural",
|
|
14395
14524
|
...table.columns.length > 0 ? { columns: table.columns } : {},
|
|
14396
14525
|
evidence: {
|
|
14397
|
-
file:
|
|
14526
|
+
file: import_node_path54.default.relative(serviceDir, file.path),
|
|
14398
14527
|
line: table.line,
|
|
14399
14528
|
snippet: snippet(file.content, table.line)
|
|
14400
14529
|
}
|
|
@@ -14416,7 +14545,7 @@ function railsSchemaForeignKeys(file, serviceDir) {
|
|
|
14416
14545
|
childTable,
|
|
14417
14546
|
parentTable,
|
|
14418
14547
|
evidence: {
|
|
14419
|
-
file:
|
|
14548
|
+
file: import_node_path54.default.relative(serviceDir, file.path),
|
|
14420
14549
|
line,
|
|
14421
14550
|
snippet: snippet(file.content, line)
|
|
14422
14551
|
}
|
|
@@ -14499,7 +14628,7 @@ function railsModelEndpointsFromFile(file, serviceDir) {
|
|
|
14499
14628
|
edgeType: "CALLS",
|
|
14500
14629
|
confidenceKind: "verified-call-site",
|
|
14501
14630
|
evidence: {
|
|
14502
|
-
file:
|
|
14631
|
+
file: import_node_path54.default.relative(serviceDir, file.path),
|
|
14503
14632
|
line,
|
|
14504
14633
|
snippet: snippet(file.content, line)
|
|
14505
14634
|
}
|
|
@@ -14536,7 +14665,7 @@ function railsModelForeignKeys(file, serviceDir) {
|
|
|
14536
14665
|
childTable,
|
|
14537
14666
|
parentTable,
|
|
14538
14667
|
evidence: {
|
|
14539
|
-
file:
|
|
14668
|
+
file: import_node_path54.default.relative(serviceDir, file.path),
|
|
14540
14669
|
line,
|
|
14541
14670
|
snippet: snippet(file.content, line)
|
|
14542
14671
|
}
|
|
@@ -14548,7 +14677,7 @@ function railsModelForeignKeys(file, serviceDir) {
|
|
|
14548
14677
|
|
|
14549
14678
|
// src/extract/calls/eloquent.ts
|
|
14550
14679
|
init_cjs_shims();
|
|
14551
|
-
var
|
|
14680
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
14552
14681
|
var import_tree_sitter14 = __toESM(require("tree-sitter"), 1);
|
|
14553
14682
|
var import_tree_sitter_php3 = __toESM(require("tree-sitter-php"), 1);
|
|
14554
14683
|
var import_types42 = require("@neat.is/types");
|
|
@@ -14805,7 +14934,7 @@ function laravelMigrationEndpointsFromFile(file, serviceDir) {
|
|
|
14805
14934
|
confidenceKind: "structural",
|
|
14806
14935
|
...columns.length > 0 ? { columns } : {},
|
|
14807
14936
|
evidence: {
|
|
14808
|
-
file:
|
|
14937
|
+
file: import_node_path55.default.relative(serviceDir, file.path),
|
|
14809
14938
|
line: bp.line,
|
|
14810
14939
|
snippet: snippet(file.content, bp.line)
|
|
14811
14940
|
}
|
|
@@ -14827,7 +14956,7 @@ function laravelMigrationForeignKeys(file, serviceDir) {
|
|
|
14827
14956
|
childTable,
|
|
14828
14957
|
parentTable,
|
|
14829
14958
|
evidence: {
|
|
14830
|
-
file:
|
|
14959
|
+
file: import_node_path55.default.relative(serviceDir, file.path),
|
|
14831
14960
|
line,
|
|
14832
14961
|
snippet: snippet(file.content, line)
|
|
14833
14962
|
}
|
|
@@ -14947,7 +15076,7 @@ function laravelModelEndpointsFromFile(file, serviceDir) {
|
|
|
14947
15076
|
edgeType: "CALLS",
|
|
14948
15077
|
confidenceKind: "verified-call-site",
|
|
14949
15078
|
evidence: {
|
|
14950
|
-
file:
|
|
15079
|
+
file: import_node_path55.default.relative(serviceDir, file.path),
|
|
14951
15080
|
line,
|
|
14952
15081
|
snippet: snippet(file.content, line)
|
|
14953
15082
|
}
|
|
@@ -14983,7 +15112,7 @@ function laravelModelForeignKeys(file, serviceDir) {
|
|
|
14983
15112
|
childTable,
|
|
14984
15113
|
parentTable,
|
|
14985
15114
|
evidence: {
|
|
14986
|
-
file:
|
|
15115
|
+
file: import_node_path55.default.relative(serviceDir, file.path),
|
|
14987
15116
|
line,
|
|
14988
15117
|
snippet: snippet(file.content, line)
|
|
14989
15118
|
}
|
|
@@ -14995,7 +15124,7 @@ function laravelModelForeignKeys(file, serviceDir) {
|
|
|
14995
15124
|
|
|
14996
15125
|
// src/extract/calls/go.ts
|
|
14997
15126
|
init_cjs_shims();
|
|
14998
|
-
var
|
|
15127
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
14999
15128
|
var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
|
|
15000
15129
|
var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
|
|
15001
15130
|
var import_types43 = require("@neat.is/types");
|
|
@@ -15070,7 +15199,7 @@ function firstStringLiteralArg(argsNode) {
|
|
|
15070
15199
|
return null;
|
|
15071
15200
|
}
|
|
15072
15201
|
function goSqlEndpointsFromFile(file, serviceDir) {
|
|
15073
|
-
if (
|
|
15202
|
+
if (import_node_path58.default.extname(file.path) !== ".go") return [];
|
|
15074
15203
|
if (!file.content.includes(DATABASE_SQL_IMPORT) && !file.content.includes(SQLX_IMPORT)) return [];
|
|
15075
15204
|
const tree = parseSource11(makeGoParser3(), file.content);
|
|
15076
15205
|
const importsDatabaseSql = goImportsAny(tree.rootNode, /* @__PURE__ */ new Set([DATABASE_SQL_IMPORT]));
|
|
@@ -15099,7 +15228,7 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
15099
15228
|
confidenceKind: "verified-call-site",
|
|
15100
15229
|
...columns.length > 0 ? { columns } : {},
|
|
15101
15230
|
evidence: {
|
|
15102
|
-
file: toPosix(
|
|
15231
|
+
file: toPosix(import_node_path58.default.relative(serviceDir, file.path)),
|
|
15103
15232
|
line,
|
|
15104
15233
|
snippet: snippet(file.content, line)
|
|
15105
15234
|
}
|
|
@@ -15110,7 +15239,7 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
15110
15239
|
|
|
15111
15240
|
// src/extract/calls/gorm.ts
|
|
15112
15241
|
init_cjs_shims();
|
|
15113
|
-
var
|
|
15242
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
15114
15243
|
var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
|
|
15115
15244
|
var import_tree_sitter_go5 = __toESM(require("tree-sitter-go"), 1);
|
|
15116
15245
|
var import_types44 = require("@neat.is/types");
|
|
@@ -15543,7 +15672,7 @@ function collectColumns(struct, structs, seen, prefix, out, emitted) {
|
|
|
15543
15672
|
seen.delete(struct.name);
|
|
15544
15673
|
}
|
|
15545
15674
|
function gormEndpointsFromFile(file, serviceDir) {
|
|
15546
|
-
if (
|
|
15675
|
+
if (import_node_path59.default.extname(file.path) !== ".go") return [];
|
|
15547
15676
|
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
15548
15677
|
const tree = parseSource12(makeGoParser4(), file.content);
|
|
15549
15678
|
const { structs, models, tableFor } = analyze(tree);
|
|
@@ -15565,7 +15694,7 @@ function gormEndpointsFromFile(file, serviceDir) {
|
|
|
15565
15694
|
confidenceKind: "structural",
|
|
15566
15695
|
...columns.length > 0 ? { columns } : {},
|
|
15567
15696
|
evidence: {
|
|
15568
|
-
file: toPosix(
|
|
15697
|
+
file: toPosix(import_node_path59.default.relative(serviceDir, file.path)),
|
|
15569
15698
|
line: struct.line,
|
|
15570
15699
|
snippet: snippet(file.content, struct.line)
|
|
15571
15700
|
}
|
|
@@ -15574,7 +15703,7 @@ function gormEndpointsFromFile(file, serviceDir) {
|
|
|
15574
15703
|
return out;
|
|
15575
15704
|
}
|
|
15576
15705
|
function gormForeignKeys(file, serviceDir) {
|
|
15577
|
-
if (
|
|
15706
|
+
if (import_node_path59.default.extname(file.path) !== ".go") return [];
|
|
15578
15707
|
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
15579
15708
|
const tree = parseSource12(makeGoParser4(), file.content);
|
|
15580
15709
|
const { structs, models, tableFor } = analyze(tree);
|
|
@@ -15589,7 +15718,7 @@ function gormForeignKeys(file, serviceDir) {
|
|
|
15589
15718
|
childTable,
|
|
15590
15719
|
parentTable,
|
|
15591
15720
|
evidence: {
|
|
15592
|
-
file: toPosix(
|
|
15721
|
+
file: toPosix(import_node_path59.default.relative(serviceDir, file.path)),
|
|
15593
15722
|
line,
|
|
15594
15723
|
snippet: snippet(file.content, line)
|
|
15595
15724
|
}
|
|
@@ -15626,7 +15755,7 @@ function gormForeignKeys(file, serviceDir) {
|
|
|
15626
15755
|
|
|
15627
15756
|
// src/extract/calls/efcore.ts
|
|
15628
15757
|
init_cjs_shims();
|
|
15629
|
-
var
|
|
15758
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
15630
15759
|
var import_tree_sitter17 = __toESM(require("tree-sitter"), 1);
|
|
15631
15760
|
var import_tree_sitter_c_sharp2 = __toESM(require("tree-sitter-c-sharp"), 1);
|
|
15632
15761
|
var import_types45 = require("@neat.is/types");
|
|
@@ -15705,7 +15834,7 @@ function tableFromToTable(call) {
|
|
|
15705
15834
|
return value ? csStringLiteral(value) : null;
|
|
15706
15835
|
}
|
|
15707
15836
|
function efcoreEndpointsFromFile(file, serviceDir) {
|
|
15708
|
-
if (
|
|
15837
|
+
if (import_node_path60.default.extname(file.path) !== ".cs") return [];
|
|
15709
15838
|
if (!EFCORE_GATE.test(file.content)) return [];
|
|
15710
15839
|
const tree = parseSource13(makeCsParser(), file.content);
|
|
15711
15840
|
const out = [];
|
|
@@ -15720,7 +15849,7 @@ function efcoreEndpointsFromFile(file, serviceDir) {
|
|
|
15720
15849
|
edgeType: "CALLS",
|
|
15721
15850
|
confidenceKind: "structural",
|
|
15722
15851
|
evidence: {
|
|
15723
|
-
file: toPosix(
|
|
15852
|
+
file: toPosix(import_node_path60.default.relative(serviceDir, file.path)),
|
|
15724
15853
|
line,
|
|
15725
15854
|
snippet: snippet(file.content, line)
|
|
15726
15855
|
}
|
|
@@ -15975,7 +16104,7 @@ init_cjs_shims();
|
|
|
15975
16104
|
|
|
15976
16105
|
// src/extract/infra/docker-compose.ts
|
|
15977
16106
|
init_cjs_shims();
|
|
15978
|
-
var
|
|
16107
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
15979
16108
|
var import_types49 = require("@neat.is/types");
|
|
15980
16109
|
|
|
15981
16110
|
// src/extract/infra/shared.ts
|
|
@@ -16046,7 +16175,7 @@ function dependsOnList(value) {
|
|
|
16046
16175
|
}
|
|
16047
16176
|
function serviceNameToServiceNode(name, services) {
|
|
16048
16177
|
for (const s of services) {
|
|
16049
|
-
if (s.node.name === name ||
|
|
16178
|
+
if (s.node.name === name || import_node_path61.default.basename(s.dir) === name) return s.node.id;
|
|
16050
16179
|
}
|
|
16051
16180
|
return null;
|
|
16052
16181
|
}
|
|
@@ -16055,7 +16184,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
16055
16184
|
let edgesAdded = 0;
|
|
16056
16185
|
let composePath = null;
|
|
16057
16186
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
16058
|
-
const abs =
|
|
16187
|
+
const abs = import_node_path61.default.join(scanPath, name);
|
|
16059
16188
|
if (await exists2(abs)) {
|
|
16060
16189
|
composePath = abs;
|
|
16061
16190
|
break;
|
|
@@ -16068,13 +16197,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
16068
16197
|
} catch (err) {
|
|
16069
16198
|
recordExtractionError(
|
|
16070
16199
|
"infra docker-compose",
|
|
16071
|
-
|
|
16200
|
+
import_node_path61.default.relative(scanPath, composePath),
|
|
16072
16201
|
err
|
|
16073
16202
|
);
|
|
16074
16203
|
return { nodesAdded, edgesAdded };
|
|
16075
16204
|
}
|
|
16076
16205
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
16077
|
-
const evidenceFile =
|
|
16206
|
+
const evidenceFile = import_node_path61.default.relative(scanPath, composePath).split(import_node_path61.default.sep).join("/");
|
|
16078
16207
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
16079
16208
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
16080
16209
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -16116,8 +16245,8 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
16116
16245
|
|
|
16117
16246
|
// src/extract/infra/dockerfile.ts
|
|
16118
16247
|
init_cjs_shims();
|
|
16119
|
-
var
|
|
16120
|
-
var
|
|
16248
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
16249
|
+
var import_node_fs28 = require("fs");
|
|
16121
16250
|
var import_types50 = require("@neat.is/types");
|
|
16122
16251
|
function readDockerfile(content) {
|
|
16123
16252
|
let image = null;
|
|
@@ -16147,15 +16276,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
16147
16276
|
let nodesAdded = 0;
|
|
16148
16277
|
let edgesAdded = 0;
|
|
16149
16278
|
for (const service of services) {
|
|
16150
|
-
const dockerfilePath =
|
|
16279
|
+
const dockerfilePath = import_node_path62.default.join(service.dir, "Dockerfile");
|
|
16151
16280
|
if (!await exists2(dockerfilePath)) continue;
|
|
16152
16281
|
let content;
|
|
16153
16282
|
try {
|
|
16154
|
-
content = await
|
|
16283
|
+
content = await import_node_fs28.promises.readFile(dockerfilePath, "utf8");
|
|
16155
16284
|
} catch (err) {
|
|
16156
16285
|
recordExtractionError(
|
|
16157
16286
|
"infra dockerfile",
|
|
16158
|
-
|
|
16287
|
+
import_node_path62.default.relative(scanPath, dockerfilePath),
|
|
16159
16288
|
err
|
|
16160
16289
|
);
|
|
16161
16290
|
continue;
|
|
@@ -16167,8 +16296,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
16167
16296
|
graph.addNode(node.id, node);
|
|
16168
16297
|
nodesAdded++;
|
|
16169
16298
|
}
|
|
16170
|
-
const relDockerfile = toPosix(
|
|
16171
|
-
const evidenceFile = toPosix(
|
|
16299
|
+
const relDockerfile = toPosix(import_node_path62.default.relative(service.dir, dockerfilePath));
|
|
16300
|
+
const evidenceFile = toPosix(import_node_path62.default.relative(scanPath, dockerfilePath));
|
|
16172
16301
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
16173
16302
|
graph,
|
|
16174
16303
|
service.pkg.name,
|
|
@@ -16220,23 +16349,23 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
16220
16349
|
|
|
16221
16350
|
// src/extract/infra/terraform.ts
|
|
16222
16351
|
init_cjs_shims();
|
|
16223
|
-
var
|
|
16224
|
-
var
|
|
16352
|
+
var import_node_fs29 = require("fs");
|
|
16353
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
16225
16354
|
var import_types51 = require("@neat.is/types");
|
|
16226
16355
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
16227
16356
|
var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
|
|
16228
16357
|
async function walkTfFiles(start, depth = 0, max = 5) {
|
|
16229
16358
|
if (depth > max) return [];
|
|
16230
16359
|
const out = [];
|
|
16231
|
-
const entries = await
|
|
16360
|
+
const entries = await import_node_fs29.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
16232
16361
|
for (const entry of entries) {
|
|
16233
16362
|
if (entry.isDirectory()) {
|
|
16234
16363
|
if (IGNORED_DIRS.has(entry.name) || entry.name === ".terraform") continue;
|
|
16235
|
-
const child =
|
|
16364
|
+
const child = import_node_path63.default.join(start, entry.name);
|
|
16236
16365
|
if (await isPythonVenvDir(child)) continue;
|
|
16237
16366
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
16238
16367
|
} else if (entry.isFile() && entry.name.endsWith(".tf")) {
|
|
16239
|
-
out.push(
|
|
16368
|
+
out.push(import_node_path63.default.join(start, entry.name));
|
|
16240
16369
|
}
|
|
16241
16370
|
}
|
|
16242
16371
|
return out;
|
|
@@ -16267,8 +16396,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
16267
16396
|
let edgesAdded = 0;
|
|
16268
16397
|
const files = await walkTfFiles(scanPath);
|
|
16269
16398
|
for (const file of files) {
|
|
16270
|
-
const content = await
|
|
16271
|
-
const evidenceFile = toPosix(
|
|
16399
|
+
const content = await import_node_fs29.promises.readFile(file, "utf8");
|
|
16400
|
+
const evidenceFile = toPosix(import_node_path63.default.relative(scanPath, file));
|
|
16272
16401
|
const resources = [];
|
|
16273
16402
|
const byKey = /* @__PURE__ */ new Map();
|
|
16274
16403
|
RESOURCE_RE.lastIndex = 0;
|
|
@@ -16325,8 +16454,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
16325
16454
|
|
|
16326
16455
|
// src/extract/infra/k8s.ts
|
|
16327
16456
|
init_cjs_shims();
|
|
16328
|
-
var
|
|
16329
|
-
var
|
|
16457
|
+
var import_node_fs30 = require("fs");
|
|
16458
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
16330
16459
|
var import_yaml3 = require("yaml");
|
|
16331
16460
|
var import_types52 = require("@neat.is/types");
|
|
16332
16461
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
@@ -16342,15 +16471,15 @@ var WORKLOAD_KINDS = /* @__PURE__ */ new Set(["Deployment", "StatefulSet", "Daem
|
|
|
16342
16471
|
async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
16343
16472
|
if (depth > max) return [];
|
|
16344
16473
|
const out = [];
|
|
16345
|
-
const entries = await
|
|
16474
|
+
const entries = await import_node_fs30.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
16346
16475
|
for (const entry of entries) {
|
|
16347
16476
|
if (entry.isDirectory()) {
|
|
16348
16477
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
16349
|
-
const child =
|
|
16478
|
+
const child = import_node_path64.default.join(start, entry.name);
|
|
16350
16479
|
if (await isPythonVenvDir(child)) continue;
|
|
16351
16480
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
16352
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
16353
|
-
out.push(
|
|
16481
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path64.default.extname(entry.name))) {
|
|
16482
|
+
out.push(import_node_path64.default.join(start, entry.name));
|
|
16354
16483
|
}
|
|
16355
16484
|
}
|
|
16356
16485
|
return out;
|
|
@@ -16360,14 +16489,14 @@ async function addK8sResources(graph, scanPath) {
|
|
|
16360
16489
|
let edgesAdded = 0;
|
|
16361
16490
|
const files = await walkYamlFiles2(scanPath);
|
|
16362
16491
|
for (const file of files) {
|
|
16363
|
-
const content = await
|
|
16492
|
+
const content = await import_node_fs30.promises.readFile(file, "utf8");
|
|
16364
16493
|
let docs;
|
|
16365
16494
|
try {
|
|
16366
16495
|
docs = (0, import_yaml3.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
16367
16496
|
} catch {
|
|
16368
16497
|
continue;
|
|
16369
16498
|
}
|
|
16370
|
-
const relFile = toPosix(
|
|
16499
|
+
const relFile = toPosix(import_node_path64.default.relative(scanPath, file));
|
|
16371
16500
|
for (const doc of docs) {
|
|
16372
16501
|
if (!doc?.kind || !doc.metadata?.name) continue;
|
|
16373
16502
|
const infraKind = K8S_KIND_TO_INFRA_KIND[doc.kind];
|
|
@@ -16416,16 +16545,16 @@ async function addK8sResources(graph, scanPath) {
|
|
|
16416
16545
|
|
|
16417
16546
|
// src/extract/infra/cloudflare.ts
|
|
16418
16547
|
init_cjs_shims();
|
|
16419
|
-
var
|
|
16420
|
-
var
|
|
16548
|
+
var import_node_fs31 = require("fs");
|
|
16549
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
16421
16550
|
var import_smol_toml3 = require("smol-toml");
|
|
16422
16551
|
var import_types53 = require("@neat.is/types");
|
|
16423
16552
|
var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
|
|
16424
16553
|
async function readWranglerConfig(dir) {
|
|
16425
16554
|
for (const filename of WRANGLER_FILENAMES) {
|
|
16426
|
-
const abs =
|
|
16555
|
+
const abs = import_node_path65.default.join(dir, filename);
|
|
16427
16556
|
if (!await exists2(abs)) continue;
|
|
16428
|
-
const raw = await
|
|
16557
|
+
const raw = await import_node_fs31.promises.readFile(abs, "utf8");
|
|
16429
16558
|
const config = filename === "wrangler.toml" ? (0, import_smol_toml3.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
16430
16559
|
return { config, relFile: filename, raw };
|
|
16431
16560
|
}
|
|
@@ -16486,11 +16615,11 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
16486
16615
|
try {
|
|
16487
16616
|
read = await readWranglerConfig(service.dir);
|
|
16488
16617
|
} catch (err) {
|
|
16489
|
-
recordExtractionError("infra cloudflare",
|
|
16618
|
+
recordExtractionError("infra cloudflare", import_node_path65.default.relative(scanPath, service.dir), err);
|
|
16490
16619
|
continue;
|
|
16491
16620
|
}
|
|
16492
16621
|
if (!read || !read.config.name) continue;
|
|
16493
|
-
const evidenceFile = toPosix(
|
|
16622
|
+
const evidenceFile = toPosix(import_node_path65.default.relative(scanPath, import_node_path65.default.join(service.dir, read.relFile)));
|
|
16494
16623
|
discovered.push({ service, config: read.config, relFile: read.relFile, raw: read.raw, evidenceFile });
|
|
16495
16624
|
}
|
|
16496
16625
|
for (const worker of discovered) {
|
|
@@ -16502,7 +16631,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
16502
16631
|
}
|
|
16503
16632
|
let anchorId = service.node.id;
|
|
16504
16633
|
if (config.main) {
|
|
16505
|
-
const entryRelPath = toPosix(
|
|
16634
|
+
const entryRelPath = toPosix(import_node_path65.default.normalize(config.main));
|
|
16506
16635
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
16507
16636
|
graph,
|
|
16508
16637
|
service.pkg.name,
|
|
@@ -16649,24 +16778,24 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
16649
16778
|
|
|
16650
16779
|
// src/extract/infra/vercel.ts
|
|
16651
16780
|
init_cjs_shims();
|
|
16652
|
-
var
|
|
16653
|
-
var
|
|
16781
|
+
var import_node_fs32 = require("fs");
|
|
16782
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
16654
16783
|
var import_types54 = require("@neat.is/types");
|
|
16655
16784
|
var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
|
|
16656
16785
|
async function readVercelConfig(dir) {
|
|
16657
16786
|
for (const filename of VERCEL_CONFIG_FILENAMES) {
|
|
16658
|
-
const abs =
|
|
16787
|
+
const abs = import_node_path66.default.join(dir, filename);
|
|
16659
16788
|
if (!await exists2(abs)) continue;
|
|
16660
|
-
const raw = await
|
|
16789
|
+
const raw = await import_node_fs32.promises.readFile(abs, "utf8");
|
|
16661
16790
|
const config = JSON.parse(maskCommentsInSource(raw));
|
|
16662
16791
|
return { config, relFile: filename, raw };
|
|
16663
16792
|
}
|
|
16664
16793
|
return null;
|
|
16665
16794
|
}
|
|
16666
16795
|
async function readLinkedProjectName(dir) {
|
|
16667
|
-
const abs =
|
|
16796
|
+
const abs = import_node_path66.default.join(dir, ".vercel", "project.json");
|
|
16668
16797
|
if (!await exists2(abs)) return void 0;
|
|
16669
|
-
const parsed = JSON.parse(await
|
|
16798
|
+
const parsed = JSON.parse(await import_node_fs32.promises.readFile(abs, "utf8"));
|
|
16670
16799
|
return typeof parsed.projectName === "string" ? parsed.projectName : void 0;
|
|
16671
16800
|
}
|
|
16672
16801
|
function routeSource(route) {
|
|
@@ -16682,7 +16811,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
16682
16811
|
read = await readVercelConfig(service.dir);
|
|
16683
16812
|
projectName = await readLinkedProjectName(service.dir);
|
|
16684
16813
|
} catch (err) {
|
|
16685
|
-
recordExtractionError("infra vercel",
|
|
16814
|
+
recordExtractionError("infra vercel", import_node_path66.default.relative(scanPath, service.dir), err);
|
|
16686
16815
|
continue;
|
|
16687
16816
|
}
|
|
16688
16817
|
if (!read && !projectName) continue;
|
|
@@ -16698,7 +16827,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
16698
16827
|
const anchorId = service.node.id;
|
|
16699
16828
|
if (!read) continue;
|
|
16700
16829
|
const { config, relFile, raw } = read;
|
|
16701
|
-
const evidenceFile = toPosix(
|
|
16830
|
+
const evidenceFile = toPosix(import_node_path66.default.relative(scanPath, import_node_path66.default.join(service.dir, relFile)));
|
|
16702
16831
|
const add = (edgeType, kind, name) => {
|
|
16703
16832
|
if (!name) return;
|
|
16704
16833
|
const result = emitPlatformResourceEdge(
|
|
@@ -16727,16 +16856,16 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
16727
16856
|
|
|
16728
16857
|
// src/extract/infra/railway.ts
|
|
16729
16858
|
init_cjs_shims();
|
|
16730
|
-
var
|
|
16731
|
-
var
|
|
16859
|
+
var import_node_fs33 = require("fs");
|
|
16860
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
16732
16861
|
var import_smol_toml4 = require("smol-toml");
|
|
16733
16862
|
var import_types55 = require("@neat.is/types");
|
|
16734
16863
|
var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
|
|
16735
16864
|
async function readRailwayConfig(dir) {
|
|
16736
16865
|
for (const filename of RAILWAY_FILENAMES) {
|
|
16737
|
-
const abs =
|
|
16866
|
+
const abs = import_node_path67.default.join(dir, filename);
|
|
16738
16867
|
if (!await exists2(abs)) continue;
|
|
16739
|
-
const raw = await
|
|
16868
|
+
const raw = await import_node_fs33.promises.readFile(abs, "utf8");
|
|
16740
16869
|
const config = filename === "railway.toml" ? (0, import_smol_toml4.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
16741
16870
|
return { config, relFile: filename, raw };
|
|
16742
16871
|
}
|
|
@@ -16750,7 +16879,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
16750
16879
|
try {
|
|
16751
16880
|
read = await readRailwayConfig(service.dir);
|
|
16752
16881
|
} catch (err) {
|
|
16753
|
-
recordExtractionError("infra railway",
|
|
16882
|
+
recordExtractionError("infra railway", import_node_path67.default.relative(scanPath, service.dir), err);
|
|
16754
16883
|
continue;
|
|
16755
16884
|
}
|
|
16756
16885
|
if (!read) continue;
|
|
@@ -16760,7 +16889,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
16760
16889
|
}
|
|
16761
16890
|
const anchorId = service.node.id;
|
|
16762
16891
|
const { config, relFile, raw } = read;
|
|
16763
|
-
const evidenceFile = toPosix(
|
|
16892
|
+
const evidenceFile = toPosix(import_node_path67.default.relative(scanPath, import_node_path67.default.join(service.dir, relFile)));
|
|
16764
16893
|
const add = (edgeType, kind, name) => {
|
|
16765
16894
|
if (!name) return;
|
|
16766
16895
|
const result = emitPlatformResourceEdge(
|
|
@@ -16785,15 +16914,15 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
16785
16914
|
|
|
16786
16915
|
// src/extract/infra/supabase.ts
|
|
16787
16916
|
init_cjs_shims();
|
|
16788
|
-
var
|
|
16789
|
-
var
|
|
16917
|
+
var import_node_fs34 = require("fs");
|
|
16918
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
16790
16919
|
var import_smol_toml5 = require("smol-toml");
|
|
16791
16920
|
var import_types56 = require("@neat.is/types");
|
|
16792
16921
|
async function readSupabaseConfig(dir) {
|
|
16793
|
-
const relFile =
|
|
16794
|
-
const abs =
|
|
16922
|
+
const relFile = import_node_path68.default.join("supabase", "config.toml");
|
|
16923
|
+
const abs = import_node_path68.default.join(dir, relFile);
|
|
16795
16924
|
if (!await exists2(abs)) return null;
|
|
16796
|
-
const raw = await
|
|
16925
|
+
const raw = await import_node_fs34.promises.readFile(abs, "utf8");
|
|
16797
16926
|
const config = (0, import_smol_toml5.parse)(raw);
|
|
16798
16927
|
return { config, relFile, raw };
|
|
16799
16928
|
}
|
|
@@ -16805,7 +16934,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
16805
16934
|
try {
|
|
16806
16935
|
read = await readSupabaseConfig(service.dir);
|
|
16807
16936
|
} catch (err) {
|
|
16808
|
-
recordExtractionError("infra supabase",
|
|
16937
|
+
recordExtractionError("infra supabase", import_node_path68.default.relative(scanPath, service.dir), err);
|
|
16809
16938
|
continue;
|
|
16810
16939
|
}
|
|
16811
16940
|
if (!read) continue;
|
|
@@ -16820,7 +16949,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
16820
16949
|
});
|
|
16821
16950
|
}
|
|
16822
16951
|
const anchorId = service.node.id;
|
|
16823
|
-
const evidenceFile = toPosix(
|
|
16952
|
+
const evidenceFile = toPosix(import_node_path68.default.relative(scanPath, import_node_path68.default.join(service.dir, relFile)));
|
|
16824
16953
|
const add = (edgeType, kind, name) => {
|
|
16825
16954
|
if (!name) return;
|
|
16826
16955
|
const result = emitPlatformResourceEdge(
|
|
@@ -16862,7 +16991,7 @@ async function addInfra(graph, scanPath, services) {
|
|
|
16862
16991
|
|
|
16863
16992
|
// src/extract/zod-shapes.ts
|
|
16864
16993
|
init_cjs_shims();
|
|
16865
|
-
var
|
|
16994
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
16866
16995
|
var import_tree_sitter18 = __toESM(require("tree-sitter"), 1);
|
|
16867
16996
|
var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
|
|
16868
16997
|
var import_types57 = require("@neat.is/types");
|
|
@@ -16957,7 +17086,7 @@ function topLevelSchemas(root) {
|
|
|
16957
17086
|
}
|
|
16958
17087
|
function zodShapesFromFile(file, serviceDir) {
|
|
16959
17088
|
if (!ZOD_IMPORT_RE.test(file.content)) return [];
|
|
16960
|
-
const tree = parseSource3(parserForExt4(
|
|
17089
|
+
const tree = parseSource3(parserForExt4(import_node_path69.default.extname(file.path)), file.content);
|
|
16961
17090
|
const out = [];
|
|
16962
17091
|
const seen = /* @__PURE__ */ new Set();
|
|
16963
17092
|
for (const { name, call } of topLevelSchemas(tree.rootNode)) {
|
|
@@ -16975,7 +17104,7 @@ function zodShapesFromFile(file, serviceDir) {
|
|
|
16975
17104
|
name,
|
|
16976
17105
|
fields,
|
|
16977
17106
|
evidence: {
|
|
16978
|
-
file:
|
|
17107
|
+
file: import_node_path69.default.relative(serviceDir, file.path),
|
|
16979
17108
|
line,
|
|
16980
17109
|
snippet: snippet(file.content, line)
|
|
16981
17110
|
}
|
|
@@ -17243,12 +17372,12 @@ async function addFirestoreRules(graph, services) {
|
|
|
17243
17372
|
}
|
|
17244
17373
|
|
|
17245
17374
|
// src/extract/index.ts
|
|
17246
|
-
var
|
|
17375
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
17247
17376
|
|
|
17248
17377
|
// src/extract/retire.ts
|
|
17249
17378
|
init_cjs_shims();
|
|
17250
|
-
var
|
|
17251
|
-
var
|
|
17379
|
+
var import_node_fs35 = require("fs");
|
|
17380
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
17252
17381
|
var import_types59 = require("@neat.is/types");
|
|
17253
17382
|
function dropOrphanedFileNodes(graph) {
|
|
17254
17383
|
const orphans = [];
|
|
@@ -17269,11 +17398,11 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
17269
17398
|
if (edge.provenance !== import_types59.Provenance.EXTRACTED) return;
|
|
17270
17399
|
const evidenceFile = edge.evidence?.file;
|
|
17271
17400
|
if (!evidenceFile) return;
|
|
17272
|
-
if (
|
|
17273
|
-
if (!(0,
|
|
17401
|
+
if (import_node_path70.default.isAbsolute(evidenceFile)) {
|
|
17402
|
+
if (!(0, import_node_fs35.existsSync)(evidenceFile)) toDrop.push(id);
|
|
17274
17403
|
return;
|
|
17275
17404
|
}
|
|
17276
|
-
const found = bases.some((base) => (0,
|
|
17405
|
+
const found = bases.some((base) => (0, import_node_fs35.existsSync)(import_node_path70.default.join(base, evidenceFile)));
|
|
17277
17406
|
if (!found) toDrop.push(id);
|
|
17278
17407
|
});
|
|
17279
17408
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -17285,6 +17414,7 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
17285
17414
|
async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
17286
17415
|
await ensureCompatLoaded();
|
|
17287
17416
|
drainExtractionErrors();
|
|
17417
|
+
drainSkippedFiles();
|
|
17288
17418
|
const services = await discoverServices(scanPath);
|
|
17289
17419
|
const phase1Nodes = addServiceNodes(graph, services);
|
|
17290
17420
|
await addServiceAliases(graph, scanPath, services);
|
|
@@ -17329,8 +17459,9 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
17329
17459
|
}
|
|
17330
17460
|
}
|
|
17331
17461
|
const droppedEntries = drainDroppedExtracted();
|
|
17462
|
+
const skippedEntries = drainSkippedFiles();
|
|
17332
17463
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
17333
|
-
const rejectedPath =
|
|
17464
|
+
const rejectedPath = import_node_path71.default.join(import_node_path71.default.dirname(opts.errorsPath), "rejected.ndjson");
|
|
17334
17465
|
try {
|
|
17335
17466
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
17336
17467
|
} catch (err) {
|
|
@@ -17347,7 +17478,9 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
17347
17478
|
errorEntries,
|
|
17348
17479
|
ghostsRetired,
|
|
17349
17480
|
extractedDropped: droppedEntries.length,
|
|
17350
|
-
droppedEntries
|
|
17481
|
+
droppedEntries,
|
|
17482
|
+
skippedFiles: skippedEntries.length,
|
|
17483
|
+
skippedEntries
|
|
17351
17484
|
};
|
|
17352
17485
|
emitNeatEvent({
|
|
17353
17486
|
type: "extraction-complete",
|
|
@@ -18267,7 +18400,7 @@ async function askGraph(graph, question, opts = {}) {
|
|
|
18267
18400
|
|
|
18268
18401
|
// src/diff.ts
|
|
18269
18402
|
init_cjs_shims();
|
|
18270
|
-
var
|
|
18403
|
+
var import_node_fs36 = require("fs");
|
|
18271
18404
|
async function loadSnapshotForDiff(target) {
|
|
18272
18405
|
if (/^https?:\/\//i.test(target)) {
|
|
18273
18406
|
const res = await fetch(target);
|
|
@@ -18276,7 +18409,7 @@ async function loadSnapshotForDiff(target) {
|
|
|
18276
18409
|
}
|
|
18277
18410
|
return await res.json();
|
|
18278
18411
|
}
|
|
18279
|
-
const raw = await
|
|
18412
|
+
const raw = await import_node_fs36.promises.readFile(target, "utf8");
|
|
18280
18413
|
return JSON.parse(raw);
|
|
18281
18414
|
}
|
|
18282
18415
|
function indexEntries(entries) {
|
|
@@ -18344,8 +18477,8 @@ function canonicalJson(value) {
|
|
|
18344
18477
|
|
|
18345
18478
|
// src/persist.ts
|
|
18346
18479
|
init_cjs_shims();
|
|
18347
|
-
var
|
|
18348
|
-
var
|
|
18480
|
+
var import_node_fs37 = require("fs");
|
|
18481
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
18349
18482
|
var import_types62 = require("@neat.is/types");
|
|
18350
18483
|
var SCHEMA_VERSION = 7;
|
|
18351
18484
|
function migrateV1ToV2(payload) {
|
|
@@ -18400,7 +18533,43 @@ function migrateV2ToV3(payload) {
|
|
|
18400
18533
|
return { ...payload, schemaVersion: 3 };
|
|
18401
18534
|
}
|
|
18402
18535
|
async function ensureDir(filePath) {
|
|
18403
|
-
await
|
|
18536
|
+
await import_node_fs37.promises.mkdir(import_node_path72.default.dirname(filePath), { recursive: true });
|
|
18537
|
+
}
|
|
18538
|
+
var WRITE_FLUSH_CHARS = 4 * 1024 * 1024;
|
|
18539
|
+
function jsonOrUndefined(value) {
|
|
18540
|
+
return JSON.stringify(value);
|
|
18541
|
+
}
|
|
18542
|
+
function* serializeArray(items) {
|
|
18543
|
+
yield "[";
|
|
18544
|
+
for (let i = 0; i < items.length; i++) {
|
|
18545
|
+
if (i > 0) yield ",";
|
|
18546
|
+
yield jsonOrUndefined(items[i]) ?? "null";
|
|
18547
|
+
}
|
|
18548
|
+
yield "]";
|
|
18549
|
+
}
|
|
18550
|
+
function isPlainObject(value) {
|
|
18551
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
18552
|
+
const proto = Object.getPrototypeOf(value);
|
|
18553
|
+
return proto === Object.prototype || proto === null;
|
|
18554
|
+
}
|
|
18555
|
+
function* serializeObject(obj) {
|
|
18556
|
+
yield "{";
|
|
18557
|
+
let first = true;
|
|
18558
|
+
for (const key of Object.keys(obj)) {
|
|
18559
|
+
const value = obj[key];
|
|
18560
|
+
const descend = Array.isArray(value) || isPlainObject(value);
|
|
18561
|
+
if (!descend && jsonOrUndefined(value) === void 0) continue;
|
|
18562
|
+
if (!first) yield ",";
|
|
18563
|
+
first = false;
|
|
18564
|
+
yield `${JSON.stringify(key)}:`;
|
|
18565
|
+
if (Array.isArray(value)) yield* serializeArray(value);
|
|
18566
|
+
else if (isPlainObject(value)) yield* serializeObject(value);
|
|
18567
|
+
else yield jsonOrUndefined(value);
|
|
18568
|
+
}
|
|
18569
|
+
yield "}";
|
|
18570
|
+
}
|
|
18571
|
+
function* serializeGraphChunks(payload) {
|
|
18572
|
+
yield* serializeObject(payload);
|
|
18404
18573
|
}
|
|
18405
18574
|
async function saveGraphToDisk(graph, outPath) {
|
|
18406
18575
|
await ensureDir(outPath);
|
|
@@ -18410,13 +18579,26 @@ async function saveGraphToDisk(graph, outPath) {
|
|
|
18410
18579
|
graph: graph.export()
|
|
18411
18580
|
};
|
|
18412
18581
|
const tmp = `${outPath}.tmp`;
|
|
18413
|
-
await
|
|
18414
|
-
|
|
18582
|
+
const handle = await import_node_fs37.promises.open(tmp, "w");
|
|
18583
|
+
try {
|
|
18584
|
+
let buffered = "";
|
|
18585
|
+
for (const chunk of serializeGraphChunks(payload)) {
|
|
18586
|
+
buffered += chunk;
|
|
18587
|
+
if (buffered.length >= WRITE_FLUSH_CHARS) {
|
|
18588
|
+
await handle.write(buffered, null, "utf8");
|
|
18589
|
+
buffered = "";
|
|
18590
|
+
}
|
|
18591
|
+
}
|
|
18592
|
+
if (buffered.length > 0) await handle.write(buffered, null, "utf8");
|
|
18593
|
+
} finally {
|
|
18594
|
+
await handle.close();
|
|
18595
|
+
}
|
|
18596
|
+
await import_node_fs37.promises.rename(tmp, outPath);
|
|
18415
18597
|
}
|
|
18416
18598
|
async function loadGraphFromDisk(graph, outPath) {
|
|
18417
18599
|
let raw;
|
|
18418
18600
|
try {
|
|
18419
|
-
raw = await
|
|
18601
|
+
raw = await import_node_fs37.promises.readFile(outPath, "utf8");
|
|
18420
18602
|
} catch (err) {
|
|
18421
18603
|
if (err.code === "ENOENT") return;
|
|
18422
18604
|
throw err;
|
|
@@ -18490,23 +18672,23 @@ function startPersistLoop(graph, outPath, opts = {}) {
|
|
|
18490
18672
|
|
|
18491
18673
|
// src/projects.ts
|
|
18492
18674
|
init_cjs_shims();
|
|
18493
|
-
var
|
|
18675
|
+
var import_node_path73 = __toESM(require("path"), 1);
|
|
18494
18676
|
function pathsForProject(project, baseDir) {
|
|
18495
18677
|
if (project === DEFAULT_PROJECT) {
|
|
18496
18678
|
return {
|
|
18497
|
-
snapshotPath:
|
|
18498
|
-
errorsPath:
|
|
18499
|
-
staleEventsPath:
|
|
18500
|
-
embeddingsCachePath:
|
|
18501
|
-
policyViolationsPath:
|
|
18679
|
+
snapshotPath: import_node_path73.default.join(baseDir, "graph.json"),
|
|
18680
|
+
errorsPath: import_node_path73.default.join(baseDir, "errors.ndjson"),
|
|
18681
|
+
staleEventsPath: import_node_path73.default.join(baseDir, "stale-events.ndjson"),
|
|
18682
|
+
embeddingsCachePath: import_node_path73.default.join(baseDir, "embeddings.json"),
|
|
18683
|
+
policyViolationsPath: import_node_path73.default.join(baseDir, "policy-violations.ndjson")
|
|
18502
18684
|
};
|
|
18503
18685
|
}
|
|
18504
18686
|
return {
|
|
18505
|
-
snapshotPath:
|
|
18506
|
-
errorsPath:
|
|
18507
|
-
staleEventsPath:
|
|
18508
|
-
embeddingsCachePath:
|
|
18509
|
-
policyViolationsPath:
|
|
18687
|
+
snapshotPath: import_node_path73.default.join(baseDir, `${project}.json`),
|
|
18688
|
+
errorsPath: import_node_path73.default.join(baseDir, `errors.${project}.ndjson`),
|
|
18689
|
+
staleEventsPath: import_node_path73.default.join(baseDir, `stale-events.${project}.ndjson`),
|
|
18690
|
+
embeddingsCachePath: import_node_path73.default.join(baseDir, `embeddings.${project}.json`),
|
|
18691
|
+
policyViolationsPath: import_node_path73.default.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
18510
18692
|
};
|
|
18511
18693
|
}
|
|
18512
18694
|
var Projects = class {
|
|
@@ -18546,20 +18728,20 @@ function parseExtraProjects(raw) {
|
|
|
18546
18728
|
|
|
18547
18729
|
// src/registry.ts
|
|
18548
18730
|
init_cjs_shims();
|
|
18549
|
-
var
|
|
18731
|
+
var import_node_fs38 = require("fs");
|
|
18550
18732
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
18551
|
-
var
|
|
18733
|
+
var import_node_path74 = __toESM(require("path"), 1);
|
|
18552
18734
|
var import_types63 = require("@neat.is/types");
|
|
18553
18735
|
function neatHome() {
|
|
18554
18736
|
const override = process.env.NEAT_HOME;
|
|
18555
|
-
if (override && override.length > 0) return
|
|
18556
|
-
return
|
|
18737
|
+
if (override && override.length > 0) return import_node_path74.default.resolve(override);
|
|
18738
|
+
return import_node_path74.default.join(import_node_os3.default.homedir(), ".neat");
|
|
18557
18739
|
}
|
|
18558
18740
|
function registryPath() {
|
|
18559
|
-
return
|
|
18741
|
+
return import_node_path74.default.join(neatHome(), "projects.json");
|
|
18560
18742
|
}
|
|
18561
18743
|
function daemonsDir() {
|
|
18562
|
-
return
|
|
18744
|
+
return import_node_path74.default.join(neatHome(), "daemons");
|
|
18563
18745
|
}
|
|
18564
18746
|
function isFiniteInt(v) {
|
|
18565
18747
|
return typeof v === "number" && Number.isFinite(v);
|
|
@@ -18592,7 +18774,7 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
18592
18774
|
const dir = daemonsDir();
|
|
18593
18775
|
let names;
|
|
18594
18776
|
try {
|
|
18595
|
-
names = await
|
|
18777
|
+
names = await import_node_fs38.promises.readdir(dir);
|
|
18596
18778
|
} catch (err) {
|
|
18597
18779
|
if (err.code === "ENOENT") return [];
|
|
18598
18780
|
throw err;
|
|
@@ -18600,10 +18782,10 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
18600
18782
|
const out = [];
|
|
18601
18783
|
for (const name of names) {
|
|
18602
18784
|
if (!name.endsWith(".json")) continue;
|
|
18603
|
-
const file =
|
|
18785
|
+
const file = import_node_path74.default.join(dir, name);
|
|
18604
18786
|
let raw;
|
|
18605
18787
|
try {
|
|
18606
|
-
raw = await
|
|
18788
|
+
raw = await import_node_fs38.promises.readFile(file, "utf8");
|
|
18607
18789
|
} catch {
|
|
18608
18790
|
continue;
|
|
18609
18791
|
}
|
|
@@ -18631,7 +18813,7 @@ async function readRegistry() {
|
|
|
18631
18813
|
const file = registryPath();
|
|
18632
18814
|
let raw;
|
|
18633
18815
|
try {
|
|
18634
|
-
raw = await
|
|
18816
|
+
raw = await import_node_fs38.promises.readFile(file, "utf8");
|
|
18635
18817
|
} catch (err) {
|
|
18636
18818
|
if (err.code === "ENOENT") {
|
|
18637
18819
|
return { version: 1, projects: [] };
|
|
@@ -18714,8 +18896,8 @@ init_auth();
|
|
|
18714
18896
|
// src/connectors-config.ts
|
|
18715
18897
|
init_cjs_shims();
|
|
18716
18898
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
18717
|
-
var
|
|
18718
|
-
var
|
|
18899
|
+
var import_node_path75 = __toESM(require("path"), 1);
|
|
18900
|
+
var import_node_fs39 = require("fs");
|
|
18719
18901
|
var CONNECTORS_CONFIG_VERSION = 1;
|
|
18720
18902
|
var EnvRefUnsetError = class extends Error {
|
|
18721
18903
|
ref;
|
|
@@ -18729,17 +18911,17 @@ var EnvRefUnsetError = class extends Error {
|
|
|
18729
18911
|
};
|
|
18730
18912
|
function neatHome2() {
|
|
18731
18913
|
const override = process.env.NEAT_HOME;
|
|
18732
|
-
if (override && override.length > 0) return
|
|
18733
|
-
return
|
|
18914
|
+
if (override && override.length > 0) return import_node_path75.default.resolve(override);
|
|
18915
|
+
return import_node_path75.default.join(import_node_os4.default.homedir(), ".neat");
|
|
18734
18916
|
}
|
|
18735
18917
|
function connectorsConfigPath(home = neatHome2()) {
|
|
18736
|
-
return
|
|
18918
|
+
return import_node_path75.default.join(home, "connectors.json");
|
|
18737
18919
|
}
|
|
18738
18920
|
var MODE_MASK_LOOSER_THAN_0600 = 63;
|
|
18739
18921
|
async function warnIfModeLooserThan0600(file) {
|
|
18740
18922
|
if (process.platform === "win32") return;
|
|
18741
18923
|
try {
|
|
18742
|
-
const stat = await
|
|
18924
|
+
const stat = await import_node_fs39.promises.stat(file);
|
|
18743
18925
|
if ((stat.mode & MODE_MASK_LOOSER_THAN_0600) !== 0) {
|
|
18744
18926
|
const mode = (stat.mode & 511).toString(8).padStart(3, "0");
|
|
18745
18927
|
console.warn(
|
|
@@ -18753,7 +18935,7 @@ async function readConnectorsConfig(home = neatHome2()) {
|
|
|
18753
18935
|
const file = connectorsConfigPath(home);
|
|
18754
18936
|
let raw;
|
|
18755
18937
|
try {
|
|
18756
|
-
raw = await
|
|
18938
|
+
raw = await import_node_fs39.promises.readFile(file, "utf8");
|
|
18757
18939
|
} catch (err) {
|
|
18758
18940
|
if (err.code === "ENOENT") {
|
|
18759
18941
|
return { version: CONNECTORS_CONFIG_VERSION, connectors: [] };
|
|
@@ -19507,10 +19689,10 @@ var SUPABASE_RPC_TARGET_KIND = "supabase-rpc";
|
|
|
19507
19689
|
// src/connectors/supabase/map.ts
|
|
19508
19690
|
var REST_RPC_PATH_RE = /^\/rest\/v1\/rpc\/([^/?]+)/;
|
|
19509
19691
|
var REST_TABLE_PATH_RE = /^\/rest\/v1\/([^/?]+)/;
|
|
19510
|
-
function targetFromRestPath(
|
|
19511
|
-
const rpcMatch = REST_RPC_PATH_RE.exec(
|
|
19692
|
+
function targetFromRestPath(path78) {
|
|
19693
|
+
const rpcMatch = REST_RPC_PATH_RE.exec(path78);
|
|
19512
19694
|
if (rpcMatch) return { targetKind: SUPABASE_RPC_TARGET_KIND, name: rpcMatch[1] };
|
|
19513
|
-
const tableMatch = REST_TABLE_PATH_RE.exec(
|
|
19695
|
+
const tableMatch = REST_TABLE_PATH_RE.exec(path78);
|
|
19514
19696
|
if (tableMatch) return { targetKind: SUPABASE_TABLE_TARGET_KIND, name: tableMatch[1] };
|
|
19515
19697
|
return null;
|
|
19516
19698
|
}
|
|
@@ -20114,9 +20296,9 @@ function parseFirebaseTargetName(targetName) {
|
|
|
20114
20296
|
const secondSep = rest.indexOf(FIELD_SEP);
|
|
20115
20297
|
if (secondSep === -1) return null;
|
|
20116
20298
|
const method = rest.slice(0, secondSep);
|
|
20117
|
-
const
|
|
20118
|
-
if (!resourceName || !method || !
|
|
20119
|
-
return { resourceName, method, path:
|
|
20299
|
+
const path78 = rest.slice(secondSep + 1);
|
|
20300
|
+
if (!resourceName || !method || !path78) return null;
|
|
20301
|
+
return { resourceName, method, path: path78 };
|
|
20120
20302
|
}
|
|
20121
20303
|
function resourceNameFor(type, labels) {
|
|
20122
20304
|
if (!labels) return null;
|
|
@@ -20154,14 +20336,14 @@ function mapLogEntryToSignal(entry) {
|
|
|
20154
20336
|
if (!req) return null;
|
|
20155
20337
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
20156
20338
|
const method = req.requestMethod.toUpperCase();
|
|
20157
|
-
const
|
|
20158
|
-
if (
|
|
20339
|
+
const path78 = pathFromRequestUrl(req.requestUrl);
|
|
20340
|
+
if (path78 === null) return null;
|
|
20159
20341
|
const timestamp = entry.timestamp;
|
|
20160
20342
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
20161
20343
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD2;
|
|
20162
20344
|
return {
|
|
20163
20345
|
targetKind: resourceType,
|
|
20164
|
-
targetName: packFirebaseTargetName({ resourceName, method, path:
|
|
20346
|
+
targetName: packFirebaseTargetName({ resourceName, method, path: path78 }),
|
|
20165
20347
|
callCount: 1,
|
|
20166
20348
|
errorCount: isError ? 1 : 0,
|
|
20167
20349
|
lastObservedIso: timestamp
|
|
@@ -20186,9 +20368,9 @@ var import_types71 = require("@neat.is/types");
|
|
|
20186
20368
|
function normalizeName(name) {
|
|
20187
20369
|
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
20188
20370
|
}
|
|
20189
|
-
function inferServiceName(graph, resourceName, method,
|
|
20371
|
+
function inferServiceName(graph, resourceName, method, path78) {
|
|
20190
20372
|
const wantedMethod = method.toUpperCase();
|
|
20191
|
-
const wantedPath = normalizePathTemplate(
|
|
20373
|
+
const wantedPath = normalizePathTemplate(path78);
|
|
20192
20374
|
const services = [];
|
|
20193
20375
|
const owners = /* @__PURE__ */ new Set();
|
|
20194
20376
|
graph.forEachNode((_id, attrs) => {
|
|
@@ -20405,7 +20587,7 @@ function mapEventToSignal(event) {
|
|
|
20405
20587
|
if (Number.isNaN(observedAt.getTime())) return null;
|
|
20406
20588
|
const statusCode = metadata?.statusCode;
|
|
20407
20589
|
const isError = typeof statusCode === "number" && statusCode >= ERROR_STATUS_THRESHOLD3;
|
|
20408
|
-
const
|
|
20590
|
+
const path78 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
|
|
20409
20591
|
return {
|
|
20410
20592
|
targetKind: CLOUDFLARE_TARGET_KIND,
|
|
20411
20593
|
targetName: scriptName,
|
|
@@ -20413,7 +20595,7 @@ function mapEventToSignal(event) {
|
|
|
20413
20595
|
errorCount: isError ? 1 : 0,
|
|
20414
20596
|
lastObservedIso: observedAt.toISOString(),
|
|
20415
20597
|
method,
|
|
20416
|
-
...
|
|
20598
|
+
...path78 ? { path: path78 } : {},
|
|
20417
20599
|
...typeof statusCode === "number" ? { statusCode } : {},
|
|
20418
20600
|
...typeof metadata?.duration === "number" ? { duration: metadata.duration } : {}
|
|
20419
20601
|
};
|
|
@@ -20459,8 +20641,8 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
20459
20641
|
});
|
|
20460
20642
|
return found;
|
|
20461
20643
|
}
|
|
20462
|
-
function findMatchingRouteNode(graph, serviceName, method,
|
|
20463
|
-
const normalizedPath = normalizePathTemplate(
|
|
20644
|
+
function findMatchingRouteNode(graph, serviceName, method, path78) {
|
|
20645
|
+
const normalizedPath = normalizePathTemplate(path78);
|
|
20464
20646
|
let found = null;
|
|
20465
20647
|
graph.forEachNode((id, attrs) => {
|
|
20466
20648
|
if (found) return;
|
|
@@ -20477,10 +20659,10 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
20477
20659
|
return (signal) => {
|
|
20478
20660
|
if (signal.targetKind !== CLOUDFLARE_TARGET_KIND) return null;
|
|
20479
20661
|
const scriptName = signal.targetName;
|
|
20480
|
-
const { method, path:
|
|
20662
|
+
const { method, path: path78 } = signal;
|
|
20481
20663
|
const resolveRouteGrain = (serviceName, wholeFileId) => {
|
|
20482
|
-
if (!method || !
|
|
20483
|
-
return findMatchingRouteNode(graph, serviceName, method,
|
|
20664
|
+
if (!method || !path78) return wholeFileId;
|
|
20665
|
+
return findMatchingRouteNode(graph, serviceName, method, path78) ?? wholeFileId;
|
|
20484
20666
|
};
|
|
20485
20667
|
const mapping = config.workers?.[scriptName];
|
|
20486
20668
|
if (mapping) {
|
|
@@ -20832,9 +21014,9 @@ function parseCloudRunTargetName(targetName) {
|
|
|
20832
21014
|
const secondSep = rest.indexOf(FIELD_SEP2);
|
|
20833
21015
|
if (secondSep === -1) return null;
|
|
20834
21016
|
const method = rest.slice(0, secondSep);
|
|
20835
|
-
const
|
|
20836
|
-
if (!serviceName || !method || !
|
|
20837
|
-
return { serviceName, method, path:
|
|
21017
|
+
const path78 = rest.slice(secondSep + 1);
|
|
21018
|
+
if (!serviceName || !method || !path78) return null;
|
|
21019
|
+
return { serviceName, method, path: path78 };
|
|
20838
21020
|
}
|
|
20839
21021
|
|
|
20840
21022
|
// src/connectors/cloud-run/map.ts
|
|
@@ -20863,14 +21045,14 @@ function mapLogEntryToSignal2(entry) {
|
|
|
20863
21045
|
if (!req) return null;
|
|
20864
21046
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
20865
21047
|
const method = req.requestMethod.toUpperCase();
|
|
20866
|
-
const
|
|
20867
|
-
if (
|
|
21048
|
+
const path78 = pathFromRequestUrl2(req.requestUrl);
|
|
21049
|
+
if (path78 === null) return null;
|
|
20868
21050
|
const timestamp = entry.timestamp;
|
|
20869
21051
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
20870
21052
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD4;
|
|
20871
21053
|
return {
|
|
20872
21054
|
targetKind: CLOUD_RUN_TARGET_KIND,
|
|
20873
|
-
targetName: packCloudRunTargetName({ serviceName, method, path:
|
|
21055
|
+
targetName: packCloudRunTargetName({ serviceName, method, path: path78 }),
|
|
20874
21056
|
callCount: 1,
|
|
20875
21057
|
errorCount: isError ? 1 : 0,
|
|
20876
21058
|
lastObservedIso: timestamp
|
|
@@ -20909,14 +21091,14 @@ function createCloudRunResolveTarget(graph, config) {
|
|
|
20909
21091
|
if (signal.targetKind !== CLOUD_RUN_TARGET_KIND) return null;
|
|
20910
21092
|
const identity = parseCloudRunTargetName(signal.targetName);
|
|
20911
21093
|
if (!identity) return null;
|
|
20912
|
-
const { serviceName: gcpServiceName, method, path:
|
|
20913
|
-
const mappedService = config.serviceMap?.[gcpServiceName] ?? (config.inferServices ? inferServiceName(graph, gcpServiceName, method,
|
|
21094
|
+
const { serviceName: gcpServiceName, method, path: path78 } = identity;
|
|
21095
|
+
const mappedService = config.serviceMap?.[gcpServiceName] ?? (config.inferServices ? inferServiceName(graph, gcpServiceName, method, path78) ?? void 0 : void 0);
|
|
20914
21096
|
if (mappedService) {
|
|
20915
21097
|
const routeNodeId = findMatchingRouteNode2(
|
|
20916
21098
|
graph,
|
|
20917
21099
|
mappedService,
|
|
20918
21100
|
method,
|
|
20919
|
-
normalizePathTemplate(
|
|
21101
|
+
normalizePathTemplate(path78)
|
|
20920
21102
|
);
|
|
20921
21103
|
if (routeNodeId) {
|
|
20922
21104
|
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types82.EdgeType.CALLS };
|
|
@@ -21052,9 +21234,9 @@ function parseGcpLbTargetName(targetName) {
|
|
|
21052
21234
|
const secondSep = rest.indexOf(FIELD_SEP3);
|
|
21053
21235
|
if (secondSep === -1) return null;
|
|
21054
21236
|
const method = rest.slice(0, secondSep);
|
|
21055
|
-
const
|
|
21056
|
-
if (!backendServiceName || !method || !
|
|
21057
|
-
return { backendServiceName, method, path:
|
|
21237
|
+
const path78 = rest.slice(secondSep + 1);
|
|
21238
|
+
if (!backendServiceName || !method || !path78) return null;
|
|
21239
|
+
return { backendServiceName, method, path: path78 };
|
|
21058
21240
|
}
|
|
21059
21241
|
|
|
21060
21242
|
// src/connectors/gcp-lb/map.ts
|
|
@@ -21083,14 +21265,14 @@ function mapLogEntryToSignal3(entry) {
|
|
|
21083
21265
|
if (!req) return null;
|
|
21084
21266
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
21085
21267
|
const method = req.requestMethod.toUpperCase();
|
|
21086
|
-
const
|
|
21087
|
-
if (
|
|
21268
|
+
const path78 = pathFromRequestUrl3(req.requestUrl);
|
|
21269
|
+
if (path78 === null) return null;
|
|
21088
21270
|
const timestamp = entry.timestamp;
|
|
21089
21271
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
21090
21272
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD5;
|
|
21091
21273
|
return {
|
|
21092
21274
|
targetKind: GCP_LB_TARGET_KIND,
|
|
21093
|
-
targetName: packGcpLbTargetName({ backendServiceName, method, path:
|
|
21275
|
+
targetName: packGcpLbTargetName({ backendServiceName, method, path: path78 }),
|
|
21094
21276
|
callCount: 1,
|
|
21095
21277
|
errorCount: isError ? 1 : 0,
|
|
21096
21278
|
lastObservedIso: timestamp
|
|
@@ -21129,14 +21311,14 @@ function createGcpLbResolveTarget(graph, config) {
|
|
|
21129
21311
|
if (signal.targetKind !== GCP_LB_TARGET_KIND) return null;
|
|
21130
21312
|
const identity = parseGcpLbTargetName(signal.targetName);
|
|
21131
21313
|
if (!identity) return null;
|
|
21132
|
-
const { backendServiceName, method, path:
|
|
21133
|
-
const mappedService = config.backendServiceMap?.[backendServiceName] ?? (config.inferServices ? inferServiceName(graph, backendServiceName, method,
|
|
21314
|
+
const { backendServiceName, method, path: path78 } = identity;
|
|
21315
|
+
const mappedService = config.backendServiceMap?.[backendServiceName] ?? (config.inferServices ? inferServiceName(graph, backendServiceName, method, path78) ?? void 0 : void 0);
|
|
21134
21316
|
if (mappedService) {
|
|
21135
21317
|
const routeNodeId = findMatchingRouteNode3(
|
|
21136
21318
|
graph,
|
|
21137
21319
|
mappedService,
|
|
21138
21320
|
method,
|
|
21139
|
-
normalizePathTemplate(
|
|
21321
|
+
normalizePathTemplate(path78)
|
|
21140
21322
|
);
|
|
21141
21323
|
if (routeNodeId) {
|
|
21142
21324
|
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types86.EdgeType.CALLS };
|
|
@@ -22398,16 +22580,18 @@ function serializeGraph(graph) {
|
|
|
22398
22580
|
});
|
|
22399
22581
|
return { nodes, edges };
|
|
22400
22582
|
}
|
|
22401
|
-
function projectFromReq(req, singleProject) {
|
|
22583
|
+
function projectFromReq(req, singleProject, registry) {
|
|
22402
22584
|
const params = req.params;
|
|
22403
22585
|
const named = params.project;
|
|
22404
22586
|
if (singleProject) {
|
|
22405
22587
|
return named === void 0 || named === DEFAULT_PROJECT ? singleProject : named;
|
|
22406
22588
|
}
|
|
22407
|
-
|
|
22589
|
+
if (named !== void 0) return named;
|
|
22590
|
+
const hosted = registry?.list() ?? [];
|
|
22591
|
+
return hosted.length === 1 ? hosted[0] : DEFAULT_PROJECT;
|
|
22408
22592
|
}
|
|
22409
22593
|
function resolveProject(registry, req, reply, bootstrap, singleProject) {
|
|
22410
|
-
const name = projectFromReq(req, singleProject);
|
|
22594
|
+
const name = projectFromReq(req, singleProject, registry);
|
|
22411
22595
|
const ctx = registry.get(name);
|
|
22412
22596
|
if (!ctx) {
|
|
22413
22597
|
const phase = bootstrap?.status(name);
|
|
@@ -22419,10 +22603,13 @@ function resolveProject(registry, req, reply, bootstrap, singleProject) {
|
|
|
22419
22603
|
void reply.code(503).send({ ready: false, project: name, status: "broken" });
|
|
22420
22604
|
return null;
|
|
22421
22605
|
}
|
|
22606
|
+
const unnamed = req.params.project === void 0;
|
|
22607
|
+
const hosted = registry.list();
|
|
22608
|
+
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).";
|
|
22422
22609
|
void reply.code(404).send({
|
|
22423
22610
|
error: "project not found",
|
|
22424
22611
|
project: name,
|
|
22425
|
-
hint
|
|
22612
|
+
hint
|
|
22426
22613
|
});
|
|
22427
22614
|
return null;
|
|
22428
22615
|
}
|
|
@@ -23305,8 +23492,8 @@ init_otel_grpc();
|
|
|
23305
23492
|
|
|
23306
23493
|
// src/search.ts
|
|
23307
23494
|
init_cjs_shims();
|
|
23308
|
-
var
|
|
23309
|
-
var
|
|
23495
|
+
var import_node_fs40 = require("fs");
|
|
23496
|
+
var import_node_path76 = __toESM(require("path"), 1);
|
|
23310
23497
|
var import_node_crypto5 = require("crypto");
|
|
23311
23498
|
var DEFAULT_LIMIT = 10;
|
|
23312
23499
|
var NOMIC_DIM = 768;
|
|
@@ -23460,7 +23647,7 @@ async function pickEmbedder() {
|
|
|
23460
23647
|
}
|
|
23461
23648
|
async function readCache(cachePath) {
|
|
23462
23649
|
try {
|
|
23463
|
-
const raw = await
|
|
23650
|
+
const raw = await import_node_fs40.promises.readFile(cachePath, "utf8");
|
|
23464
23651
|
const parsed = JSON.parse(raw);
|
|
23465
23652
|
if (parsed.version !== 1) return null;
|
|
23466
23653
|
return parsed;
|
|
@@ -23469,8 +23656,8 @@ async function readCache(cachePath) {
|
|
|
23469
23656
|
}
|
|
23470
23657
|
}
|
|
23471
23658
|
async function writeCache(cachePath, cache) {
|
|
23472
|
-
await
|
|
23473
|
-
await
|
|
23659
|
+
await import_node_fs40.promises.mkdir(import_node_path76.default.dirname(cachePath), { recursive: true });
|
|
23660
|
+
await import_node_fs40.promises.writeFile(cachePath, JSON.stringify(cache));
|
|
23474
23661
|
}
|
|
23475
23662
|
var VectorIndex = class {
|
|
23476
23663
|
constructor(embedder, cachePath) {
|
|
@@ -23684,14 +23871,14 @@ async function bootProject(registry, name, scanPath, baseDir) {
|
|
|
23684
23871
|
async function main() {
|
|
23685
23872
|
const baseDirEnv = process.env.NEAT_OUT_DIR;
|
|
23686
23873
|
const legacyOutPath = process.env.NEAT_OUT_PATH;
|
|
23687
|
-
const baseDir = baseDirEnv ?
|
|
23688
|
-
const defaultScanPath =
|
|
23874
|
+
const baseDir = baseDirEnv ? import_node_path77.default.resolve(baseDirEnv) : legacyOutPath ? import_node_path77.default.resolve(import_node_path77.default.dirname(legacyOutPath)) : import_node_path77.default.resolve("./neat-out");
|
|
23875
|
+
const defaultScanPath = import_node_path77.default.resolve(process.env.NEAT_SCAN_PATH ?? "./demo");
|
|
23689
23876
|
const registry = new Projects();
|
|
23690
23877
|
await bootProject(registry, DEFAULT_PROJECT, defaultScanPath, baseDir);
|
|
23691
23878
|
for (const name of parseExtraProjects(process.env.NEAT_PROJECTS)) {
|
|
23692
23879
|
const envKey = `NEAT_PROJECT_SCAN_PATH_${name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`;
|
|
23693
23880
|
const projectScan = process.env[envKey];
|
|
23694
|
-
await bootProject(registry, name, projectScan ?
|
|
23881
|
+
await bootProject(registry, name, projectScan ? import_node_path77.default.resolve(projectScan) : void 0, baseDir);
|
|
23695
23882
|
}
|
|
23696
23883
|
const host = process.env.HOST ?? "0.0.0.0";
|
|
23697
23884
|
const port = Number(process.env.PORT ?? 8080);
|