@neat.is/core 0.4.12 → 0.4.13
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-WDG4QEFO.js → chunk-5W7H35JJ.js} +557 -232
- package/dist/chunk-5W7H35JJ.js.map +1 -0
- package/dist/{chunk-7JY6F7BY.js → chunk-TWNJX26R.js} +2 -2
- package/dist/cli.cjs +784 -455
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +9 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +606 -284
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +613 -291
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +531 -209
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-WDG4QEFO.js.map +0 -1
- /package/dist/{chunk-7JY6F7BY.js.map → chunk-TWNJX26R.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -57,9 +57,9 @@ function mountBearerAuth(app, opts) {
|
|
|
57
57
|
const suffixes = [...DEFAULT_UNAUTH_SUFFIXES, ...opts.extraUnauthenticatedSuffixes ?? []];
|
|
58
58
|
const publicRead = opts.publicRead === true;
|
|
59
59
|
app.addHook("preHandler", (req, reply, done) => {
|
|
60
|
-
const
|
|
60
|
+
const path42 = (req.url.split("?")[0] ?? "").replace(/\/+$/, "");
|
|
61
61
|
for (const suffix of suffixes) {
|
|
62
|
-
if (
|
|
62
|
+
if (path42 === suffix || path42.endsWith(suffix)) {
|
|
63
63
|
done();
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
@@ -185,8 +185,8 @@ function reshapeGrpcRequest(req) {
|
|
|
185
185
|
};
|
|
186
186
|
}
|
|
187
187
|
function resolveProtoRoot() {
|
|
188
|
-
const here =
|
|
189
|
-
return
|
|
188
|
+
const here = import_node_path38.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
189
|
+
return import_node_path38.default.resolve(here, "..", "proto");
|
|
190
190
|
}
|
|
191
191
|
function loadTraceService() {
|
|
192
192
|
const protoRoot = resolveProtoRoot();
|
|
@@ -254,13 +254,13 @@ async function startOtelGrpcReceiver(opts) {
|
|
|
254
254
|
})
|
|
255
255
|
};
|
|
256
256
|
}
|
|
257
|
-
var import_node_url,
|
|
257
|
+
var import_node_url, import_node_path38, import_node_crypto2, grpc, protoLoader;
|
|
258
258
|
var init_otel_grpc = __esm({
|
|
259
259
|
"src/otel-grpc.ts"() {
|
|
260
260
|
"use strict";
|
|
261
261
|
init_cjs_shims();
|
|
262
262
|
import_node_url = require("url");
|
|
263
|
-
|
|
263
|
+
import_node_path38 = __toESM(require("path"), 1);
|
|
264
264
|
import_node_crypto2 = require("crypto");
|
|
265
265
|
grpc = __toESM(require("@grpc/grpc-js"), 1);
|
|
266
266
|
protoLoader = __toESM(require("@grpc/proto-loader"), 1);
|
|
@@ -370,10 +370,10 @@ function parseOtlpRequest(body) {
|
|
|
370
370
|
return out;
|
|
371
371
|
}
|
|
372
372
|
function loadProtoRoot() {
|
|
373
|
-
const here =
|
|
374
|
-
const protoRoot =
|
|
373
|
+
const here = import_node_path39.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
374
|
+
const protoRoot = import_node_path39.default.resolve(here, "..", "proto");
|
|
375
375
|
const root = new import_protobufjs.default.Root();
|
|
376
|
-
root.resolvePath = (_origin, target) =>
|
|
376
|
+
root.resolvePath = (_origin, target) => import_node_path39.default.resolve(protoRoot, target);
|
|
377
377
|
root.loadSync(
|
|
378
378
|
"opentelemetry/proto/collector/trace/v1/trace_service.proto",
|
|
379
379
|
{ keepCase: true }
|
|
@@ -574,12 +574,12 @@ function logSpanHandler(span) {
|
|
|
574
574
|
`otel: ${span.service} ${span.name} parent=${parent} status=${status2}${db}`
|
|
575
575
|
);
|
|
576
576
|
}
|
|
577
|
-
var
|
|
577
|
+
var import_node_path39, import_node_url2, import_fastify2, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody;
|
|
578
578
|
var init_otel = __esm({
|
|
579
579
|
"src/otel.ts"() {
|
|
580
580
|
"use strict";
|
|
581
581
|
init_cjs_shims();
|
|
582
|
-
|
|
582
|
+
import_node_path39 = __toESM(require("path"), 1);
|
|
583
583
|
import_node_url2 = require("url");
|
|
584
584
|
import_fastify2 = __toESM(require("fastify"), 1);
|
|
585
585
|
import_protobufjs = __toESM(require("protobufjs"), 1);
|
|
@@ -1117,19 +1117,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
1117
1117
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
1118
1118
|
let best = { path: [start], edges: [] };
|
|
1119
1119
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
1120
|
-
function step(node,
|
|
1121
|
-
if (
|
|
1122
|
-
best = { path: [...
|
|
1120
|
+
function step(node, path42, edges) {
|
|
1121
|
+
if (path42.length > best.path.length) {
|
|
1122
|
+
best = { path: [...path42], edges: [...edges] };
|
|
1123
1123
|
}
|
|
1124
|
-
if (
|
|
1124
|
+
if (path42.length - 1 >= maxDepth) return;
|
|
1125
1125
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
1126
1126
|
for (const [srcId, edge] of incoming) {
|
|
1127
1127
|
if (visited.has(srcId)) continue;
|
|
1128
1128
|
visited.add(srcId);
|
|
1129
|
-
|
|
1129
|
+
path42.push(srcId);
|
|
1130
1130
|
edges.push(edge);
|
|
1131
|
-
step(srcId,
|
|
1132
|
-
|
|
1131
|
+
step(srcId, path42, edges);
|
|
1132
|
+
path42.pop();
|
|
1133
1133
|
edges.pop();
|
|
1134
1134
|
visited.delete(srcId);
|
|
1135
1135
|
}
|
|
@@ -3089,10 +3089,8 @@ async function addServiceAliases(graph, scanPath, services) {
|
|
|
3089
3089
|
await collectK8sAliases(graph, scanPath, byName);
|
|
3090
3090
|
}
|
|
3091
3091
|
|
|
3092
|
-
// src/extract/
|
|
3092
|
+
// src/extract/files.ts
|
|
3093
3093
|
init_cjs_shims();
|
|
3094
|
-
var import_node_path18 = __toESM(require("path"), 1);
|
|
3095
|
-
var import_types8 = require("@neat.is/types");
|
|
3096
3094
|
|
|
3097
3095
|
// src/extract/calls/shared.ts
|
|
3098
3096
|
init_cjs_shims();
|
|
@@ -3191,11 +3189,333 @@ function ensureFileNode(graph, serviceName, serviceNodeId, relPath) {
|
|
|
3191
3189
|
return { fileNodeId, nodesAdded, edgesAdded };
|
|
3192
3190
|
}
|
|
3193
3191
|
|
|
3192
|
+
// src/extract/files.ts
|
|
3193
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
3194
|
+
async function addFiles(graph, services) {
|
|
3195
|
+
let nodesAdded = 0;
|
|
3196
|
+
let edgesAdded = 0;
|
|
3197
|
+
for (const service of services) {
|
|
3198
|
+
const filePaths = await walkSourceFiles(service.dir);
|
|
3199
|
+
for (const filePath of filePaths) {
|
|
3200
|
+
const relPath = toPosix2(import_node_path11.default.relative(service.dir, filePath));
|
|
3201
|
+
const { nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
3202
|
+
graph,
|
|
3203
|
+
service.pkg.name,
|
|
3204
|
+
service.node.id,
|
|
3205
|
+
relPath
|
|
3206
|
+
);
|
|
3207
|
+
nodesAdded += n;
|
|
3208
|
+
edgesAdded += e;
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
return { nodesAdded, edgesAdded };
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
// src/extract/imports.ts
|
|
3215
|
+
init_cjs_shims();
|
|
3216
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
3217
|
+
var import_node_fs11 = require("fs");
|
|
3218
|
+
var import_tree_sitter = __toESM(require("tree-sitter"), 1);
|
|
3219
|
+
var import_tree_sitter_javascript = __toESM(require("tree-sitter-javascript"), 1);
|
|
3220
|
+
var import_tree_sitter_python = __toESM(require("tree-sitter-python"), 1);
|
|
3221
|
+
var import_types8 = require("@neat.is/types");
|
|
3222
|
+
var PARSE_CHUNK = 16384;
|
|
3223
|
+
function parseSource(parser, source) {
|
|
3224
|
+
return parser.parse(
|
|
3225
|
+
(index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK)
|
|
3226
|
+
);
|
|
3227
|
+
}
|
|
3228
|
+
function makeJsParser() {
|
|
3229
|
+
const p = new import_tree_sitter.default();
|
|
3230
|
+
p.setLanguage(import_tree_sitter_javascript.default);
|
|
3231
|
+
return p;
|
|
3232
|
+
}
|
|
3233
|
+
function makePyParser() {
|
|
3234
|
+
const p = new import_tree_sitter.default();
|
|
3235
|
+
p.setLanguage(import_tree_sitter_python.default);
|
|
3236
|
+
return p;
|
|
3237
|
+
}
|
|
3238
|
+
function stringLiteralText(node) {
|
|
3239
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
3240
|
+
const child = node.child(i);
|
|
3241
|
+
if (child?.type === "string_fragment") return child.text;
|
|
3242
|
+
}
|
|
3243
|
+
const raw = node.text;
|
|
3244
|
+
if (raw.length >= 2) return raw.slice(1, -1);
|
|
3245
|
+
return raw.length === 0 ? null : "";
|
|
3246
|
+
}
|
|
3247
|
+
function clipSnippet(text) {
|
|
3248
|
+
const oneLine = text.split("\n")[0] ?? text;
|
|
3249
|
+
return oneLine.length > 120 ? oneLine.slice(0, 120) : oneLine;
|
|
3250
|
+
}
|
|
3251
|
+
function collectJsImports(node, out) {
|
|
3252
|
+
if (node.type === "import_statement") {
|
|
3253
|
+
const source = node.childForFieldName("source");
|
|
3254
|
+
if (source) {
|
|
3255
|
+
const specifier = stringLiteralText(source);
|
|
3256
|
+
if (specifier) {
|
|
3257
|
+
out.push({ specifier, line: node.startPosition.row + 1, snippet: clipSnippet(node.text) });
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
return;
|
|
3261
|
+
}
|
|
3262
|
+
if (node.type === "call_expression") {
|
|
3263
|
+
const fn = node.childForFieldName("function");
|
|
3264
|
+
if (fn?.type === "identifier" && fn.text === "require") {
|
|
3265
|
+
const args = node.childForFieldName("arguments");
|
|
3266
|
+
const firstArg = args?.namedChild(0);
|
|
3267
|
+
if (firstArg?.type === "string") {
|
|
3268
|
+
const specifier = stringLiteralText(firstArg);
|
|
3269
|
+
if (specifier) {
|
|
3270
|
+
out.push({ specifier, line: node.startPosition.row + 1, snippet: clipSnippet(node.text) });
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
3276
|
+
const child = node.namedChild(i);
|
|
3277
|
+
if (child) collectJsImports(child, out);
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
function collectPyImports(node, out) {
|
|
3281
|
+
if (node.type === "import_from_statement") {
|
|
3282
|
+
let level = 0;
|
|
3283
|
+
let modulePath = "";
|
|
3284
|
+
let pastFrom = false;
|
|
3285
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
3286
|
+
const child = node.child(i);
|
|
3287
|
+
if (!child) continue;
|
|
3288
|
+
if (!pastFrom) {
|
|
3289
|
+
if (child.type === "from") pastFrom = true;
|
|
3290
|
+
continue;
|
|
3291
|
+
}
|
|
3292
|
+
if (child.type === "import") break;
|
|
3293
|
+
if (child.type === "relative_import") {
|
|
3294
|
+
for (let j = 0; j < child.childCount; j++) {
|
|
3295
|
+
const rc = child.child(j);
|
|
3296
|
+
if (!rc) continue;
|
|
3297
|
+
if (rc.type === "import_prefix") {
|
|
3298
|
+
for (let k = 0; k < rc.childCount; k++) {
|
|
3299
|
+
if (rc.child(k)?.type === ".") level++;
|
|
3300
|
+
}
|
|
3301
|
+
} else if (rc.type === "dotted_name") modulePath = rc.text;
|
|
3302
|
+
}
|
|
3303
|
+
break;
|
|
3304
|
+
}
|
|
3305
|
+
if (child.type === "dotted_name") {
|
|
3306
|
+
modulePath = child.text;
|
|
3307
|
+
break;
|
|
3308
|
+
}
|
|
3309
|
+
}
|
|
3310
|
+
if (level > 0 || modulePath) {
|
|
3311
|
+
out.push({ modulePath, level, line: node.startPosition.row + 1, snippet: clipSnippet(node.text) });
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
3315
|
+
const child = node.namedChild(i);
|
|
3316
|
+
if (child) collectPyImports(child, out);
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
async function fileExists(p) {
|
|
3320
|
+
try {
|
|
3321
|
+
await import_node_fs11.promises.access(p);
|
|
3322
|
+
return true;
|
|
3323
|
+
} catch {
|
|
3324
|
+
return false;
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
function isWithinServiceDir(candidate, serviceDir) {
|
|
3328
|
+
const rel = import_node_path12.default.relative(serviceDir, candidate);
|
|
3329
|
+
return rel !== "" && !rel.startsWith("..") && !import_node_path12.default.isAbsolute(rel);
|
|
3330
|
+
}
|
|
3331
|
+
var JS_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
3332
|
+
var JS_INDEX_FILES = JS_EXTENSIONS.map((ext) => `index${ext}`);
|
|
3333
|
+
async function firstExistingCandidate(base, serviceDir) {
|
|
3334
|
+
for (const ext of JS_EXTENSIONS) {
|
|
3335
|
+
const candidate = base + ext;
|
|
3336
|
+
if (isWithinServiceDir(candidate, serviceDir) && await fileExists(candidate)) {
|
|
3337
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, candidate));
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
for (const indexFile of JS_INDEX_FILES) {
|
|
3341
|
+
const candidate = import_node_path12.default.join(base, indexFile);
|
|
3342
|
+
if (isWithinServiceDir(candidate, serviceDir) && await fileExists(candidate)) {
|
|
3343
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, candidate));
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
return null;
|
|
3347
|
+
}
|
|
3348
|
+
async function loadTsPathConfig(serviceDir) {
|
|
3349
|
+
const tsconfigPath = import_node_path12.default.join(serviceDir, "tsconfig.json");
|
|
3350
|
+
let raw;
|
|
3351
|
+
try {
|
|
3352
|
+
raw = await import_node_fs11.promises.readFile(tsconfigPath, "utf8");
|
|
3353
|
+
} catch {
|
|
3354
|
+
return null;
|
|
3355
|
+
}
|
|
3356
|
+
try {
|
|
3357
|
+
const parsed = JSON.parse(raw);
|
|
3358
|
+
const paths = parsed.compilerOptions?.paths;
|
|
3359
|
+
if (!paths || Object.keys(paths).length === 0) return null;
|
|
3360
|
+
const baseUrl = parsed.compilerOptions?.baseUrl;
|
|
3361
|
+
return { paths, baseDir: baseUrl ? import_node_path12.default.resolve(serviceDir, baseUrl) : serviceDir };
|
|
3362
|
+
} catch (err) {
|
|
3363
|
+
recordExtractionError("import alias resolution", tsconfigPath, err);
|
|
3364
|
+
return null;
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
async function resolveTsAlias(specifier, config, serviceDir) {
|
|
3368
|
+
for (const [pattern, targets] of Object.entries(config.paths)) {
|
|
3369
|
+
let suffix = null;
|
|
3370
|
+
if (pattern === specifier) {
|
|
3371
|
+
suffix = "";
|
|
3372
|
+
} else if (pattern.endsWith("/*")) {
|
|
3373
|
+
const prefix = pattern.slice(0, -1);
|
|
3374
|
+
if (specifier.startsWith(prefix)) suffix = specifier.slice(prefix.length);
|
|
3375
|
+
}
|
|
3376
|
+
if (suffix === null) continue;
|
|
3377
|
+
for (const target of targets) {
|
|
3378
|
+
const targetBase = target.endsWith("/*") ? target.slice(0, -2) : target.replace(/\*$/, "");
|
|
3379
|
+
const resolvedBase = import_node_path12.default.resolve(config.baseDir, targetBase, suffix);
|
|
3380
|
+
const hit = await firstExistingCandidate(resolvedBase, serviceDir);
|
|
3381
|
+
if (hit) return hit;
|
|
3382
|
+
if (isWithinServiceDir(resolvedBase, serviceDir) && await fileExists(resolvedBase)) {
|
|
3383
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, resolvedBase));
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
return null;
|
|
3388
|
+
}
|
|
3389
|
+
async function resolveJsImport(specifier, importerDir, serviceDir, tsPaths) {
|
|
3390
|
+
if (!specifier) return null;
|
|
3391
|
+
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
3392
|
+
const base = import_node_path12.default.resolve(importerDir, specifier);
|
|
3393
|
+
const ext = import_node_path12.default.extname(specifier);
|
|
3394
|
+
if (ext) {
|
|
3395
|
+
if (ext === ".js" || ext === ".jsx") {
|
|
3396
|
+
const tsExt = ext === ".jsx" ? ".tsx" : ".ts";
|
|
3397
|
+
const tsSibling = base.slice(0, -ext.length) + tsExt;
|
|
3398
|
+
if (isWithinServiceDir(tsSibling, serviceDir) && await fileExists(tsSibling)) {
|
|
3399
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, tsSibling));
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
if (isWithinServiceDir(base, serviceDir) && await fileExists(base)) {
|
|
3403
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, base));
|
|
3404
|
+
}
|
|
3405
|
+
return null;
|
|
3406
|
+
}
|
|
3407
|
+
return firstExistingCandidate(base, serviceDir);
|
|
3408
|
+
}
|
|
3409
|
+
if (tsPaths) return resolveTsAlias(specifier, tsPaths, serviceDir);
|
|
3410
|
+
return null;
|
|
3411
|
+
}
|
|
3412
|
+
async function resolvePyImport(imp, importerPath, serviceDir) {
|
|
3413
|
+
if (!imp.modulePath) return null;
|
|
3414
|
+
const relPath = imp.modulePath.split(".").join("/");
|
|
3415
|
+
let baseDir;
|
|
3416
|
+
if (imp.level > 0) {
|
|
3417
|
+
baseDir = import_node_path12.default.dirname(importerPath);
|
|
3418
|
+
for (let i = 1; i < imp.level; i++) baseDir = import_node_path12.default.dirname(baseDir);
|
|
3419
|
+
} else {
|
|
3420
|
+
baseDir = serviceDir;
|
|
3421
|
+
}
|
|
3422
|
+
const candidates = [import_node_path12.default.join(baseDir, `${relPath}.py`), import_node_path12.default.join(baseDir, relPath, "__init__.py")];
|
|
3423
|
+
for (const candidate of candidates) {
|
|
3424
|
+
if (isWithinServiceDir(candidate, serviceDir) && await fileExists(candidate)) {
|
|
3425
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, candidate));
|
|
3426
|
+
}
|
|
3427
|
+
}
|
|
3428
|
+
return null;
|
|
3429
|
+
}
|
|
3430
|
+
function emitImportEdge(graph, serviceName, importerFileId, importerRelPath, importeeRelPath, line, snippet2) {
|
|
3431
|
+
const importeeFileId = (0, import_types8.fileId)(serviceName, importeeRelPath);
|
|
3432
|
+
if (!graph.hasNode(importeeFileId)) return 0;
|
|
3433
|
+
const edgeId = (0, import_types8.extractedEdgeId)(importerFileId, importeeFileId, import_types8.EdgeType.IMPORTS);
|
|
3434
|
+
if (graph.hasEdge(edgeId)) return 0;
|
|
3435
|
+
const edge = {
|
|
3436
|
+
id: edgeId,
|
|
3437
|
+
source: importerFileId,
|
|
3438
|
+
target: importeeFileId,
|
|
3439
|
+
type: import_types8.EdgeType.IMPORTS,
|
|
3440
|
+
provenance: import_types8.Provenance.EXTRACTED,
|
|
3441
|
+
confidence: (0, import_types8.confidenceForExtracted)("structural"),
|
|
3442
|
+
evidence: { file: importerRelPath, line, snippet: snippet2 }
|
|
3443
|
+
};
|
|
3444
|
+
graph.addEdgeWithKey(edgeId, importerFileId, importeeFileId, edge);
|
|
3445
|
+
return 1;
|
|
3446
|
+
}
|
|
3447
|
+
async function addImports(graph, services) {
|
|
3448
|
+
const jsParser = makeJsParser();
|
|
3449
|
+
const pyParser = makePyParser();
|
|
3450
|
+
let edgesAdded = 0;
|
|
3451
|
+
for (const service of services) {
|
|
3452
|
+
const tsPaths = await loadTsPathConfig(service.dir);
|
|
3453
|
+
const files = await loadSourceFiles(service.dir);
|
|
3454
|
+
for (const file of files) {
|
|
3455
|
+
if (isTestPath(file.path)) continue;
|
|
3456
|
+
const relFile = toPosix2(import_node_path12.default.relative(service.dir, file.path));
|
|
3457
|
+
const importerFileId = (0, import_types8.fileId)(service.pkg.name, relFile);
|
|
3458
|
+
const isPython = import_node_path12.default.extname(file.path) === ".py";
|
|
3459
|
+
if (isPython) {
|
|
3460
|
+
let pyImports = [];
|
|
3461
|
+
try {
|
|
3462
|
+
const tree = parseSource(pyParser, file.content);
|
|
3463
|
+
collectPyImports(tree.rootNode, pyImports);
|
|
3464
|
+
} catch (err) {
|
|
3465
|
+
recordExtractionError("import extraction", file.path, err);
|
|
3466
|
+
continue;
|
|
3467
|
+
}
|
|
3468
|
+
for (const imp of pyImports) {
|
|
3469
|
+
const resolved = await resolvePyImport(imp, file.path, service.dir);
|
|
3470
|
+
if (!resolved) continue;
|
|
3471
|
+
edgesAdded += emitImportEdge(
|
|
3472
|
+
graph,
|
|
3473
|
+
service.pkg.name,
|
|
3474
|
+
importerFileId,
|
|
3475
|
+
relFile,
|
|
3476
|
+
resolved,
|
|
3477
|
+
imp.line,
|
|
3478
|
+
imp.snippet
|
|
3479
|
+
);
|
|
3480
|
+
}
|
|
3481
|
+
continue;
|
|
3482
|
+
}
|
|
3483
|
+
let jsImports = [];
|
|
3484
|
+
try {
|
|
3485
|
+
const tree = parseSource(jsParser, file.content);
|
|
3486
|
+
collectJsImports(tree.rootNode, jsImports);
|
|
3487
|
+
} catch (err) {
|
|
3488
|
+
recordExtractionError("import extraction", file.path, err);
|
|
3489
|
+
continue;
|
|
3490
|
+
}
|
|
3491
|
+
for (const imp of jsImports) {
|
|
3492
|
+
const resolved = await resolveJsImport(imp.specifier, import_node_path12.default.dirname(file.path), service.dir, tsPaths);
|
|
3493
|
+
if (!resolved) continue;
|
|
3494
|
+
edgesAdded += emitImportEdge(
|
|
3495
|
+
graph,
|
|
3496
|
+
service.pkg.name,
|
|
3497
|
+
importerFileId,
|
|
3498
|
+
relFile,
|
|
3499
|
+
resolved,
|
|
3500
|
+
imp.line,
|
|
3501
|
+
imp.snippet
|
|
3502
|
+
);
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
return { nodesAdded: 0, edgesAdded };
|
|
3507
|
+
}
|
|
3508
|
+
|
|
3509
|
+
// src/extract/databases/index.ts
|
|
3510
|
+
init_cjs_shims();
|
|
3511
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
3512
|
+
var import_types9 = require("@neat.is/types");
|
|
3513
|
+
|
|
3194
3514
|
// src/extract/databases/db-config-yaml.ts
|
|
3195
3515
|
init_cjs_shims();
|
|
3196
|
-
var
|
|
3516
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
3197
3517
|
async function parse(serviceDir) {
|
|
3198
|
-
const yamlPath =
|
|
3518
|
+
const yamlPath = import_node_path13.default.join(serviceDir, "db-config.yaml");
|
|
3199
3519
|
if (!await exists(yamlPath)) return [];
|
|
3200
3520
|
const raw = await readYaml(yamlPath);
|
|
3201
3521
|
return [
|
|
@@ -3213,13 +3533,13 @@ var dbConfigYamlParser = { name: "db-config.yaml", parse };
|
|
|
3213
3533
|
|
|
3214
3534
|
// src/extract/databases/dotenv.ts
|
|
3215
3535
|
init_cjs_shims();
|
|
3216
|
-
var
|
|
3217
|
-
var
|
|
3536
|
+
var import_node_fs13 = require("fs");
|
|
3537
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
3218
3538
|
|
|
3219
3539
|
// src/extract/databases/shared.ts
|
|
3220
3540
|
init_cjs_shims();
|
|
3221
|
-
var
|
|
3222
|
-
var
|
|
3541
|
+
var import_node_fs12 = require("fs");
|
|
3542
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
3223
3543
|
function schemeToEngine(scheme) {
|
|
3224
3544
|
const s = scheme.toLowerCase().split("+")[0];
|
|
3225
3545
|
switch (s) {
|
|
@@ -3258,14 +3578,14 @@ function parseConnectionString(url) {
|
|
|
3258
3578
|
}
|
|
3259
3579
|
async function readIfExists(filePath) {
|
|
3260
3580
|
try {
|
|
3261
|
-
return await
|
|
3581
|
+
return await import_node_fs12.promises.readFile(filePath, "utf8");
|
|
3262
3582
|
} catch {
|
|
3263
3583
|
return null;
|
|
3264
3584
|
}
|
|
3265
3585
|
}
|
|
3266
3586
|
async function findFirst(serviceDir, candidates) {
|
|
3267
3587
|
for (const rel of candidates) {
|
|
3268
|
-
const abs =
|
|
3588
|
+
const abs = import_node_path14.default.join(serviceDir, rel);
|
|
3269
3589
|
const content = await readIfExists(abs);
|
|
3270
3590
|
if (content !== null) return abs;
|
|
3271
3591
|
}
|
|
@@ -3316,15 +3636,15 @@ function parseDotenvLine(line) {
|
|
|
3316
3636
|
return { key, value };
|
|
3317
3637
|
}
|
|
3318
3638
|
async function parse2(serviceDir) {
|
|
3319
|
-
const entries = await
|
|
3639
|
+
const entries = await import_node_fs13.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
3320
3640
|
const configs = [];
|
|
3321
3641
|
const seen = /* @__PURE__ */ new Set();
|
|
3322
3642
|
for (const entry of entries) {
|
|
3323
3643
|
if (!entry.isFile()) continue;
|
|
3324
3644
|
const match = isConfigFile(entry.name);
|
|
3325
3645
|
if (!match.match || match.fileType !== "env") continue;
|
|
3326
|
-
const filePath =
|
|
3327
|
-
const content = await
|
|
3646
|
+
const filePath = import_node_path15.default.join(serviceDir, entry.name);
|
|
3647
|
+
const content = await import_node_fs13.promises.readFile(filePath, "utf8");
|
|
3328
3648
|
for (const line of content.split("\n")) {
|
|
3329
3649
|
const parsed = parseDotenvLine(line);
|
|
3330
3650
|
if (!parsed) continue;
|
|
@@ -3343,9 +3663,9 @@ var dotenvParser = { name: ".env", parse: parse2 };
|
|
|
3343
3663
|
|
|
3344
3664
|
// src/extract/databases/prisma.ts
|
|
3345
3665
|
init_cjs_shims();
|
|
3346
|
-
var
|
|
3666
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
3347
3667
|
async function parse3(serviceDir) {
|
|
3348
|
-
const schemaPath =
|
|
3668
|
+
const schemaPath = import_node_path16.default.join(serviceDir, "prisma", "schema.prisma");
|
|
3349
3669
|
const content = await readIfExists(schemaPath);
|
|
3350
3670
|
if (!content) return [];
|
|
3351
3671
|
const block = content.match(/datasource\s+\w+\s*\{([^}]*)\}/s);
|
|
@@ -3477,10 +3797,10 @@ var knexParser = { name: "knex", parse: parse5 };
|
|
|
3477
3797
|
|
|
3478
3798
|
// src/extract/databases/ormconfig.ts
|
|
3479
3799
|
init_cjs_shims();
|
|
3480
|
-
var
|
|
3800
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
3481
3801
|
async function parse6(serviceDir) {
|
|
3482
3802
|
for (const candidate of ["ormconfig.json", "ormconfig.yaml", "ormconfig.yml"]) {
|
|
3483
|
-
const abs =
|
|
3803
|
+
const abs = import_node_path17.default.join(serviceDir, candidate);
|
|
3484
3804
|
if (!await exists(abs)) continue;
|
|
3485
3805
|
const raw = candidate.endsWith(".json") ? await readJson(abs) : await readYaml(abs);
|
|
3486
3806
|
const entries = Array.isArray(raw) ? raw : [raw];
|
|
@@ -3540,9 +3860,9 @@ var typeormParser = { name: "typeorm", parse: parse7 };
|
|
|
3540
3860
|
|
|
3541
3861
|
// src/extract/databases/sequelize.ts
|
|
3542
3862
|
init_cjs_shims();
|
|
3543
|
-
var
|
|
3863
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
3544
3864
|
async function parse8(serviceDir) {
|
|
3545
|
-
const configPath =
|
|
3865
|
+
const configPath = import_node_path18.default.join(serviceDir, "config", "config.json");
|
|
3546
3866
|
if (!await exists(configPath)) return [];
|
|
3547
3867
|
const raw = await readJson(configPath);
|
|
3548
3868
|
const out = [];
|
|
@@ -3569,7 +3889,7 @@ var sequelizeParser = { name: "sequelize", parse: parse8 };
|
|
|
3569
3889
|
|
|
3570
3890
|
// src/extract/databases/docker-compose.ts
|
|
3571
3891
|
init_cjs_shims();
|
|
3572
|
-
var
|
|
3892
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
3573
3893
|
function portFromService(svc) {
|
|
3574
3894
|
for (const raw of svc.ports ?? []) {
|
|
3575
3895
|
const str = String(raw);
|
|
@@ -3596,7 +3916,7 @@ function databaseFromEnv(svc) {
|
|
|
3596
3916
|
}
|
|
3597
3917
|
async function parse9(serviceDir) {
|
|
3598
3918
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
3599
|
-
const abs =
|
|
3919
|
+
const abs = import_node_path19.default.join(serviceDir, name);
|
|
3600
3920
|
if (!await exists(abs)) continue;
|
|
3601
3921
|
const raw = await readYaml(abs);
|
|
3602
3922
|
if (!raw?.services) return [];
|
|
@@ -3637,8 +3957,8 @@ function compatibleDriversFor(engine) {
|
|
|
3637
3957
|
}
|
|
3638
3958
|
function toDatabaseNode(config) {
|
|
3639
3959
|
return {
|
|
3640
|
-
id: (0,
|
|
3641
|
-
type:
|
|
3960
|
+
id: (0, import_types9.databaseId)(config.host),
|
|
3961
|
+
type: import_types9.NodeType.DatabaseNode,
|
|
3642
3962
|
name: config.database || config.host,
|
|
3643
3963
|
engine: config.engine,
|
|
3644
3964
|
engineVersion: config.engineVersion,
|
|
@@ -3768,7 +4088,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
3768
4088
|
discoveredVia: mergedDiscoveredVia
|
|
3769
4089
|
});
|
|
3770
4090
|
}
|
|
3771
|
-
const relConfigFile = toPosix2(
|
|
4091
|
+
const relConfigFile = toPosix2(import_node_path20.default.relative(service.dir, config.sourceFile));
|
|
3772
4092
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
3773
4093
|
graph,
|
|
3774
4094
|
service.pkg.name,
|
|
@@ -3777,14 +4097,14 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
3777
4097
|
);
|
|
3778
4098
|
nodesAdded += fn;
|
|
3779
4099
|
edgesAdded += fe;
|
|
3780
|
-
const evidenceFile = toPosix2(
|
|
4100
|
+
const evidenceFile = toPosix2(import_node_path20.default.relative(scanPath, config.sourceFile));
|
|
3781
4101
|
const edge = {
|
|
3782
|
-
id: (0, import_types4.extractedEdgeId)(fileNodeId, dbNode.id,
|
|
4102
|
+
id: (0, import_types4.extractedEdgeId)(fileNodeId, dbNode.id, import_types9.EdgeType.CONNECTS_TO),
|
|
3783
4103
|
source: fileNodeId,
|
|
3784
4104
|
target: dbNode.id,
|
|
3785
|
-
type:
|
|
3786
|
-
provenance:
|
|
3787
|
-
confidence: (0,
|
|
4105
|
+
type: import_types9.EdgeType.CONNECTS_TO,
|
|
4106
|
+
provenance: import_types9.Provenance.EXTRACTED,
|
|
4107
|
+
confidence: (0, import_types9.confidenceForExtracted)("structural"),
|
|
3788
4108
|
evidence: { file: evidenceFile }
|
|
3789
4109
|
};
|
|
3790
4110
|
if (!graph.hasEdge(edge.id)) {
|
|
@@ -3811,15 +4131,15 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
3811
4131
|
|
|
3812
4132
|
// src/extract/configs.ts
|
|
3813
4133
|
init_cjs_shims();
|
|
3814
|
-
var
|
|
3815
|
-
var
|
|
3816
|
-
var
|
|
4134
|
+
var import_node_fs14 = require("fs");
|
|
4135
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
4136
|
+
var import_types10 = require("@neat.is/types");
|
|
3817
4137
|
async function walkConfigFiles(dir) {
|
|
3818
4138
|
const out = [];
|
|
3819
4139
|
async function walk(current) {
|
|
3820
|
-
const entries = await
|
|
4140
|
+
const entries = await import_node_fs14.promises.readdir(current, { withFileTypes: true });
|
|
3821
4141
|
for (const entry of entries) {
|
|
3822
|
-
const full =
|
|
4142
|
+
const full = import_node_path21.default.join(current, entry.name);
|
|
3823
4143
|
if (entry.isDirectory()) {
|
|
3824
4144
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
3825
4145
|
if (await isPythonVenvDir(full)) continue;
|
|
@@ -3838,19 +4158,19 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
3838
4158
|
for (const service of services) {
|
|
3839
4159
|
const configFiles = await walkConfigFiles(service.dir);
|
|
3840
4160
|
for (const file of configFiles) {
|
|
3841
|
-
const relPath =
|
|
4161
|
+
const relPath = import_node_path21.default.relative(scanPath, file);
|
|
3842
4162
|
const node = {
|
|
3843
|
-
id: (0,
|
|
3844
|
-
type:
|
|
3845
|
-
name:
|
|
4163
|
+
id: (0, import_types10.configId)(relPath),
|
|
4164
|
+
type: import_types10.NodeType.ConfigNode,
|
|
4165
|
+
name: import_node_path21.default.basename(file),
|
|
3846
4166
|
path: relPath,
|
|
3847
|
-
fileType: isConfigFile(
|
|
4167
|
+
fileType: isConfigFile(import_node_path21.default.basename(file)).fileType
|
|
3848
4168
|
};
|
|
3849
4169
|
if (!graph.hasNode(node.id)) {
|
|
3850
4170
|
graph.addNode(node.id, node);
|
|
3851
4171
|
nodesAdded++;
|
|
3852
4172
|
}
|
|
3853
|
-
const relToService = toPosix2(
|
|
4173
|
+
const relToService = toPosix2(import_node_path21.default.relative(service.dir, file));
|
|
3854
4174
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
3855
4175
|
graph,
|
|
3856
4176
|
service.pkg.name,
|
|
@@ -3860,13 +4180,13 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
3860
4180
|
nodesAdded += fn;
|
|
3861
4181
|
edgesAdded += fe;
|
|
3862
4182
|
const edge = {
|
|
3863
|
-
id: (0, import_types4.extractedEdgeId)(fileNodeId, node.id,
|
|
4183
|
+
id: (0, import_types4.extractedEdgeId)(fileNodeId, node.id, import_types10.EdgeType.CONFIGURED_BY),
|
|
3864
4184
|
source: fileNodeId,
|
|
3865
4185
|
target: node.id,
|
|
3866
|
-
type:
|
|
3867
|
-
provenance:
|
|
3868
|
-
confidence: (0,
|
|
3869
|
-
evidence: { file: relPath.split(
|
|
4186
|
+
type: import_types10.EdgeType.CONFIGURED_BY,
|
|
4187
|
+
provenance: import_types10.Provenance.EXTRACTED,
|
|
4188
|
+
confidence: (0, import_types10.confidenceForExtracted)("structural"),
|
|
4189
|
+
evidence: { file: relPath.split(import_node_path21.default.sep).join("/") }
|
|
3870
4190
|
};
|
|
3871
4191
|
if (!graph.hasEdge(edge.id)) {
|
|
3872
4192
|
graph.addEdgeWithKey(edge.id, edge.source, edge.target, edge);
|
|
@@ -3879,15 +4199,15 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
3879
4199
|
|
|
3880
4200
|
// src/extract/calls/index.ts
|
|
3881
4201
|
init_cjs_shims();
|
|
3882
|
-
var
|
|
4202
|
+
var import_types16 = require("@neat.is/types");
|
|
3883
4203
|
|
|
3884
4204
|
// src/extract/calls/http.ts
|
|
3885
4205
|
init_cjs_shims();
|
|
3886
|
-
var
|
|
3887
|
-
var
|
|
3888
|
-
var
|
|
3889
|
-
var
|
|
3890
|
-
var
|
|
4206
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
4207
|
+
var import_tree_sitter2 = __toESM(require("tree-sitter"), 1);
|
|
4208
|
+
var import_tree_sitter_javascript2 = __toESM(require("tree-sitter-javascript"), 1);
|
|
4209
|
+
var import_tree_sitter_python2 = __toESM(require("tree-sitter-python"), 1);
|
|
4210
|
+
var import_types11 = require("@neat.is/types");
|
|
3891
4211
|
var STRING_LITERAL_NODE_TYPES = /* @__PURE__ */ new Set(["string_fragment", "string_content"]);
|
|
3892
4212
|
var JSX_EXTERNAL_LINK_TAGS = /* @__PURE__ */ new Set(["a", "Link", "NavLink", "ExternalLink", "Anchor"]);
|
|
3893
4213
|
function isInsideJsxExternalLink(node) {
|
|
@@ -3915,14 +4235,14 @@ function collectStringLiterals(node, out) {
|
|
|
3915
4235
|
if (child) collectStringLiterals(child, out);
|
|
3916
4236
|
}
|
|
3917
4237
|
}
|
|
3918
|
-
var
|
|
3919
|
-
function
|
|
4238
|
+
var PARSE_CHUNK2 = 16384;
|
|
4239
|
+
function parseSource2(parser, source) {
|
|
3920
4240
|
return parser.parse(
|
|
3921
|
-
(index) => index >= source.length ? "" : source.slice(index, index +
|
|
4241
|
+
(index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK2)
|
|
3922
4242
|
);
|
|
3923
4243
|
}
|
|
3924
4244
|
function callsFromSource(source, parser, knownHosts) {
|
|
3925
|
-
const tree =
|
|
4245
|
+
const tree = parseSource2(parser, source);
|
|
3926
4246
|
const literals = [];
|
|
3927
4247
|
collectStringLiterals(tree.rootNode, literals);
|
|
3928
4248
|
const out = [];
|
|
@@ -3936,25 +4256,25 @@ function callsFromSource(source, parser, knownHosts) {
|
|
|
3936
4256
|
}
|
|
3937
4257
|
return out;
|
|
3938
4258
|
}
|
|
3939
|
-
function
|
|
3940
|
-
const p = new
|
|
3941
|
-
p.setLanguage(
|
|
4259
|
+
function makeJsParser2() {
|
|
4260
|
+
const p = new import_tree_sitter2.default();
|
|
4261
|
+
p.setLanguage(import_tree_sitter_javascript2.default);
|
|
3942
4262
|
return p;
|
|
3943
4263
|
}
|
|
3944
|
-
function
|
|
3945
|
-
const p = new
|
|
3946
|
-
p.setLanguage(
|
|
4264
|
+
function makePyParser2() {
|
|
4265
|
+
const p = new import_tree_sitter2.default();
|
|
4266
|
+
p.setLanguage(import_tree_sitter_python2.default);
|
|
3947
4267
|
return p;
|
|
3948
4268
|
}
|
|
3949
4269
|
async function addHttpCallEdges(graph, services) {
|
|
3950
|
-
const jsParser =
|
|
3951
|
-
const pyParser =
|
|
4270
|
+
const jsParser = makeJsParser2();
|
|
4271
|
+
const pyParser = makePyParser2();
|
|
3952
4272
|
const knownHosts = /* @__PURE__ */ new Set();
|
|
3953
4273
|
const hostToNodeId = /* @__PURE__ */ new Map();
|
|
3954
4274
|
for (const service of services) {
|
|
3955
|
-
knownHosts.add(
|
|
4275
|
+
knownHosts.add(import_node_path22.default.basename(service.dir));
|
|
3956
4276
|
knownHosts.add(service.pkg.name);
|
|
3957
|
-
hostToNodeId.set(
|
|
4277
|
+
hostToNodeId.set(import_node_path22.default.basename(service.dir), service.node.id);
|
|
3958
4278
|
hostToNodeId.set(service.pkg.name, service.node.id);
|
|
3959
4279
|
}
|
|
3960
4280
|
let nodesAdded = 0;
|
|
@@ -3964,7 +4284,7 @@ async function addHttpCallEdges(graph, services) {
|
|
|
3964
4284
|
const seen = /* @__PURE__ */ new Set();
|
|
3965
4285
|
for (const file of files) {
|
|
3966
4286
|
if (isTestPath(file.path)) continue;
|
|
3967
|
-
const parser =
|
|
4287
|
+
const parser = import_node_path22.default.extname(file.path) === ".py" ? pyParser : jsParser;
|
|
3968
4288
|
let sites;
|
|
3969
4289
|
try {
|
|
3970
4290
|
sites = callsFromSource(file.content, parser, knownHosts);
|
|
@@ -3973,14 +4293,14 @@ async function addHttpCallEdges(graph, services) {
|
|
|
3973
4293
|
continue;
|
|
3974
4294
|
}
|
|
3975
4295
|
if (sites.length === 0) continue;
|
|
3976
|
-
const relFile = toPosix2(
|
|
4296
|
+
const relFile = toPosix2(import_node_path22.default.relative(service.dir, file.path));
|
|
3977
4297
|
for (const site of sites) {
|
|
3978
4298
|
const targetId = hostToNodeId.get(site.host);
|
|
3979
4299
|
if (!targetId || targetId === service.node.id) continue;
|
|
3980
4300
|
const dedupKey = `${relFile}|${targetId}`;
|
|
3981
4301
|
if (seen.has(dedupKey)) continue;
|
|
3982
4302
|
seen.add(dedupKey);
|
|
3983
|
-
const confidence = (0,
|
|
4303
|
+
const confidence = (0, import_types11.confidenceForExtracted)("hostname-shape-match");
|
|
3984
4304
|
const ev = {
|
|
3985
4305
|
file: relFile,
|
|
3986
4306
|
line: site.line,
|
|
@@ -3994,25 +4314,25 @@ async function addHttpCallEdges(graph, services) {
|
|
|
3994
4314
|
);
|
|
3995
4315
|
nodesAdded += n;
|
|
3996
4316
|
edgesAdded += e;
|
|
3997
|
-
if (!(0,
|
|
4317
|
+
if (!(0, import_types11.passesExtractedFloor)(confidence)) {
|
|
3998
4318
|
noteExtractedDropped({
|
|
3999
4319
|
source: fileNodeId,
|
|
4000
4320
|
target: targetId,
|
|
4001
|
-
type:
|
|
4321
|
+
type: import_types11.EdgeType.CALLS,
|
|
4002
4322
|
confidence,
|
|
4003
4323
|
confidenceKind: "hostname-shape-match",
|
|
4004
4324
|
evidence: ev
|
|
4005
4325
|
});
|
|
4006
4326
|
continue;
|
|
4007
4327
|
}
|
|
4008
|
-
const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, targetId,
|
|
4328
|
+
const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, targetId, import_types11.EdgeType.CALLS);
|
|
4009
4329
|
if (!graph.hasEdge(edgeId)) {
|
|
4010
4330
|
const edge = {
|
|
4011
4331
|
id: edgeId,
|
|
4012
4332
|
source: fileNodeId,
|
|
4013
4333
|
target: targetId,
|
|
4014
|
-
type:
|
|
4015
|
-
provenance:
|
|
4334
|
+
type: import_types11.EdgeType.CALLS,
|
|
4335
|
+
provenance: import_types11.Provenance.EXTRACTED,
|
|
4016
4336
|
confidence,
|
|
4017
4337
|
evidence: ev
|
|
4018
4338
|
};
|
|
@@ -4027,8 +4347,8 @@ async function addHttpCallEdges(graph, services) {
|
|
|
4027
4347
|
|
|
4028
4348
|
// src/extract/calls/kafka.ts
|
|
4029
4349
|
init_cjs_shims();
|
|
4030
|
-
var
|
|
4031
|
-
var
|
|
4350
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
4351
|
+
var import_types12 = require("@neat.is/types");
|
|
4032
4352
|
var PRODUCER_TOPIC_RE = /(?:producer|kafkaProducer)[\s\S]{0,40}?\.send\s*\(\s*\{[\s\S]{0,200}?topic\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
4033
4353
|
var CONSUMER_TOPIC_RE = /(?:consumer|kafkaConsumer)[\s\S]{0,40}?\.(?:subscribe|run)\s*\(\s*\{[\s\S]{0,200}?topic[s]?\s*:\s*(?:\[\s*)?['"`]([^'"`]+)['"`]/g;
|
|
4034
4354
|
function findAll(re, text) {
|
|
@@ -4049,7 +4369,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
4049
4369
|
seen.add(key);
|
|
4050
4370
|
const line = lineOf(file.content, topic);
|
|
4051
4371
|
out.push({
|
|
4052
|
-
infraId: (0,
|
|
4372
|
+
infraId: (0, import_types12.infraId)("kafka-topic", topic),
|
|
4053
4373
|
name: topic,
|
|
4054
4374
|
kind: "kafka-topic",
|
|
4055
4375
|
edgeType,
|
|
@@ -4058,7 +4378,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
4058
4378
|
// tier (ADR-066).
|
|
4059
4379
|
confidenceKind: "verified-call-site",
|
|
4060
4380
|
evidence: {
|
|
4061
|
-
file:
|
|
4381
|
+
file: import_node_path23.default.relative(serviceDir, file.path),
|
|
4062
4382
|
line,
|
|
4063
4383
|
snippet: snippet(file.content, line)
|
|
4064
4384
|
}
|
|
@@ -4071,8 +4391,8 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
4071
4391
|
|
|
4072
4392
|
// src/extract/calls/redis.ts
|
|
4073
4393
|
init_cjs_shims();
|
|
4074
|
-
var
|
|
4075
|
-
var
|
|
4394
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
4395
|
+
var import_types13 = require("@neat.is/types");
|
|
4076
4396
|
var REDIS_URL_RE = /redis(?:s)?:\/\/(?:[^@'"`\s]+@)?([^:/'"`\s]+)(?::(\d+))?/g;
|
|
4077
4397
|
function redisEndpointsFromFile(file, serviceDir) {
|
|
4078
4398
|
const out = [];
|
|
@@ -4085,7 +4405,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
4085
4405
|
seen.add(host);
|
|
4086
4406
|
const line = lineOf(file.content, host);
|
|
4087
4407
|
out.push({
|
|
4088
|
-
infraId: (0,
|
|
4408
|
+
infraId: (0, import_types13.infraId)("redis", host),
|
|
4089
4409
|
name: host,
|
|
4090
4410
|
kind: "redis",
|
|
4091
4411
|
edgeType: "CALLS",
|
|
@@ -4094,7 +4414,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
4094
4414
|
// support tier (ADR-066).
|
|
4095
4415
|
confidenceKind: "url-with-structural-support",
|
|
4096
4416
|
evidence: {
|
|
4097
|
-
file:
|
|
4417
|
+
file: import_node_path24.default.relative(serviceDir, file.path),
|
|
4098
4418
|
line,
|
|
4099
4419
|
snippet: snippet(file.content, line)
|
|
4100
4420
|
}
|
|
@@ -4105,8 +4425,8 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
4105
4425
|
|
|
4106
4426
|
// src/extract/calls/aws.ts
|
|
4107
4427
|
init_cjs_shims();
|
|
4108
|
-
var
|
|
4109
|
-
var
|
|
4428
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
4429
|
+
var import_types14 = require("@neat.is/types");
|
|
4110
4430
|
var S3_BUCKET_RE = /Bucket\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
4111
4431
|
var DYNAMO_TABLE_RE = /TableName\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
4112
4432
|
function hasMarker(text, markers) {
|
|
@@ -4130,7 +4450,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
4130
4450
|
seen.add(key);
|
|
4131
4451
|
const line = lineOf(file.content, name);
|
|
4132
4452
|
out.push({
|
|
4133
|
-
infraId: (0,
|
|
4453
|
+
infraId: (0, import_types14.infraId)(kind, name),
|
|
4134
4454
|
name,
|
|
4135
4455
|
kind,
|
|
4136
4456
|
edgeType: "CALLS",
|
|
@@ -4139,7 +4459,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
4139
4459
|
// (ADR-066).
|
|
4140
4460
|
confidenceKind: "verified-call-site",
|
|
4141
4461
|
evidence: {
|
|
4142
|
-
file:
|
|
4462
|
+
file: import_node_path25.default.relative(serviceDir, file.path),
|
|
4143
4463
|
line,
|
|
4144
4464
|
snippet: snippet(file.content, line)
|
|
4145
4465
|
}
|
|
@@ -4164,8 +4484,8 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
4164
4484
|
|
|
4165
4485
|
// src/extract/calls/grpc.ts
|
|
4166
4486
|
init_cjs_shims();
|
|
4167
|
-
var
|
|
4168
|
-
var
|
|
4487
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
4488
|
+
var import_types15 = require("@neat.is/types");
|
|
4169
4489
|
var GRPC_CLIENT_RE = /new\s+([A-Z][A-Za-z0-9_]*)Client\s*\(\s*['"`]?([^,'"`)]+)?/g;
|
|
4170
4490
|
var AWS_SDK_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@aws-sdk\/client-([a-z0-9-]+)['"`]/g;
|
|
4171
4491
|
var GRPC_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@grpc\/grpc-js['"`]|_grpc_pb['"`]/;
|
|
@@ -4214,7 +4534,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
4214
4534
|
const { kind } = classified;
|
|
4215
4535
|
const line = lineOf(file.content, m[0]);
|
|
4216
4536
|
out.push({
|
|
4217
|
-
infraId: (0,
|
|
4537
|
+
infraId: (0, import_types15.infraId)(kind, name),
|
|
4218
4538
|
name,
|
|
4219
4539
|
kind,
|
|
4220
4540
|
edgeType: "CALLS",
|
|
@@ -4223,7 +4543,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
4223
4543
|
// tier (ADR-066).
|
|
4224
4544
|
confidenceKind: "verified-call-site",
|
|
4225
4545
|
evidence: {
|
|
4226
|
-
file:
|
|
4546
|
+
file: import_node_path26.default.relative(serviceDir, file.path),
|
|
4227
4547
|
line,
|
|
4228
4548
|
snippet: snippet(file.content, line)
|
|
4229
4549
|
}
|
|
@@ -4236,11 +4556,11 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
4236
4556
|
function edgeTypeFromEndpoint(ep) {
|
|
4237
4557
|
switch (ep.edgeType) {
|
|
4238
4558
|
case "PUBLISHES_TO":
|
|
4239
|
-
return
|
|
4559
|
+
return import_types16.EdgeType.PUBLISHES_TO;
|
|
4240
4560
|
case "CONSUMES_FROM":
|
|
4241
|
-
return
|
|
4561
|
+
return import_types16.EdgeType.CONSUMES_FROM;
|
|
4242
4562
|
default:
|
|
4243
|
-
return
|
|
4563
|
+
return import_types16.EdgeType.CALLS;
|
|
4244
4564
|
}
|
|
4245
4565
|
}
|
|
4246
4566
|
function isAwsKind(kind) {
|
|
@@ -4267,7 +4587,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
4267
4587
|
if (!graph.hasNode(ep.infraId)) {
|
|
4268
4588
|
const node = {
|
|
4269
4589
|
id: ep.infraId,
|
|
4270
|
-
type:
|
|
4590
|
+
type: import_types16.NodeType.InfraNode,
|
|
4271
4591
|
name: ep.name,
|
|
4272
4592
|
// #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
|
|
4273
4593
|
// aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
|
|
@@ -4279,7 +4599,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
4279
4599
|
nodesAdded++;
|
|
4280
4600
|
}
|
|
4281
4601
|
const edgeType = edgeTypeFromEndpoint(ep);
|
|
4282
|
-
const confidence = (0,
|
|
4602
|
+
const confidence = (0, import_types16.confidenceForExtracted)(ep.confidenceKind);
|
|
4283
4603
|
const relFile = toPosix2(ep.evidence.file);
|
|
4284
4604
|
const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
4285
4605
|
graph,
|
|
@@ -4289,7 +4609,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
4289
4609
|
);
|
|
4290
4610
|
nodesAdded += n;
|
|
4291
4611
|
edgesAdded += e;
|
|
4292
|
-
if (!(0,
|
|
4612
|
+
if (!(0, import_types16.passesExtractedFloor)(confidence)) {
|
|
4293
4613
|
noteExtractedDropped({
|
|
4294
4614
|
source: fileNodeId,
|
|
4295
4615
|
target: ep.infraId,
|
|
@@ -4309,7 +4629,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
4309
4629
|
source: fileNodeId,
|
|
4310
4630
|
target: ep.infraId,
|
|
4311
4631
|
type: edgeType,
|
|
4312
|
-
provenance:
|
|
4632
|
+
provenance: import_types16.Provenance.EXTRACTED,
|
|
4313
4633
|
confidence,
|
|
4314
4634
|
evidence: ep.evidence
|
|
4315
4635
|
};
|
|
@@ -4334,16 +4654,16 @@ init_cjs_shims();
|
|
|
4334
4654
|
|
|
4335
4655
|
// src/extract/infra/docker-compose.ts
|
|
4336
4656
|
init_cjs_shims();
|
|
4337
|
-
var
|
|
4338
|
-
var
|
|
4657
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
4658
|
+
var import_types18 = require("@neat.is/types");
|
|
4339
4659
|
|
|
4340
4660
|
// src/extract/infra/shared.ts
|
|
4341
4661
|
init_cjs_shims();
|
|
4342
|
-
var
|
|
4662
|
+
var import_types17 = require("@neat.is/types");
|
|
4343
4663
|
function makeInfraNode(kind, name, provider = "self", extras) {
|
|
4344
4664
|
return {
|
|
4345
|
-
id: (0,
|
|
4346
|
-
type:
|
|
4665
|
+
id: (0, import_types17.infraId)(kind, name),
|
|
4666
|
+
type: import_types17.NodeType.InfraNode,
|
|
4347
4667
|
name,
|
|
4348
4668
|
provider,
|
|
4349
4669
|
kind,
|
|
@@ -4372,7 +4692,7 @@ function dependsOnList(value) {
|
|
|
4372
4692
|
}
|
|
4373
4693
|
function serviceNameToServiceNode(name, services) {
|
|
4374
4694
|
for (const s of services) {
|
|
4375
|
-
if (s.node.name === name ||
|
|
4695
|
+
if (s.node.name === name || import_node_path27.default.basename(s.dir) === name) return s.node.id;
|
|
4376
4696
|
}
|
|
4377
4697
|
return null;
|
|
4378
4698
|
}
|
|
@@ -4381,7 +4701,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
4381
4701
|
let edgesAdded = 0;
|
|
4382
4702
|
let composePath = null;
|
|
4383
4703
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
4384
|
-
const abs =
|
|
4704
|
+
const abs = import_node_path27.default.join(scanPath, name);
|
|
4385
4705
|
if (await exists(abs)) {
|
|
4386
4706
|
composePath = abs;
|
|
4387
4707
|
break;
|
|
@@ -4394,13 +4714,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
4394
4714
|
} catch (err) {
|
|
4395
4715
|
recordExtractionError(
|
|
4396
4716
|
"infra docker-compose",
|
|
4397
|
-
|
|
4717
|
+
import_node_path27.default.relative(scanPath, composePath),
|
|
4398
4718
|
err
|
|
4399
4719
|
);
|
|
4400
4720
|
return { nodesAdded, edgesAdded };
|
|
4401
4721
|
}
|
|
4402
4722
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
4403
|
-
const evidenceFile =
|
|
4723
|
+
const evidenceFile = import_node_path27.default.relative(scanPath, composePath).split(import_node_path27.default.sep).join("/");
|
|
4404
4724
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
4405
4725
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
4406
4726
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -4422,15 +4742,15 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
4422
4742
|
for (const dep of dependsOnList(svc.depends_on)) {
|
|
4423
4743
|
const targetId = composeNameToNodeId.get(dep);
|
|
4424
4744
|
if (!targetId) continue;
|
|
4425
|
-
const edgeId = (0, import_types4.extractedEdgeId)(sourceId, targetId,
|
|
4745
|
+
const edgeId = (0, import_types4.extractedEdgeId)(sourceId, targetId, import_types18.EdgeType.DEPENDS_ON);
|
|
4426
4746
|
if (graph.hasEdge(edgeId)) continue;
|
|
4427
4747
|
const edge = {
|
|
4428
4748
|
id: edgeId,
|
|
4429
4749
|
source: sourceId,
|
|
4430
4750
|
target: targetId,
|
|
4431
|
-
type:
|
|
4432
|
-
provenance:
|
|
4433
|
-
confidence: (0,
|
|
4751
|
+
type: import_types18.EdgeType.DEPENDS_ON,
|
|
4752
|
+
provenance: import_types18.Provenance.EXTRACTED,
|
|
4753
|
+
confidence: (0, import_types18.confidenceForExtracted)("structural"),
|
|
4434
4754
|
evidence: { file: evidenceFile }
|
|
4435
4755
|
};
|
|
4436
4756
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -4442,9 +4762,9 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
4442
4762
|
|
|
4443
4763
|
// src/extract/infra/dockerfile.ts
|
|
4444
4764
|
init_cjs_shims();
|
|
4445
|
-
var
|
|
4446
|
-
var
|
|
4447
|
-
var
|
|
4765
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
4766
|
+
var import_node_fs15 = require("fs");
|
|
4767
|
+
var import_types19 = require("@neat.is/types");
|
|
4448
4768
|
function runtimeImage(content) {
|
|
4449
4769
|
const lines = content.split("\n");
|
|
4450
4770
|
let last = null;
|
|
@@ -4463,15 +4783,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
4463
4783
|
let nodesAdded = 0;
|
|
4464
4784
|
let edgesAdded = 0;
|
|
4465
4785
|
for (const service of services) {
|
|
4466
|
-
const dockerfilePath =
|
|
4786
|
+
const dockerfilePath = import_node_path28.default.join(service.dir, "Dockerfile");
|
|
4467
4787
|
if (!await exists(dockerfilePath)) continue;
|
|
4468
4788
|
let content;
|
|
4469
4789
|
try {
|
|
4470
|
-
content = await
|
|
4790
|
+
content = await import_node_fs15.promises.readFile(dockerfilePath, "utf8");
|
|
4471
4791
|
} catch (err) {
|
|
4472
4792
|
recordExtractionError(
|
|
4473
4793
|
"infra dockerfile",
|
|
4474
|
-
|
|
4794
|
+
import_node_path28.default.relative(scanPath, dockerfilePath),
|
|
4475
4795
|
err
|
|
4476
4796
|
);
|
|
4477
4797
|
continue;
|
|
@@ -4483,7 +4803,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
4483
4803
|
graph.addNode(node.id, node);
|
|
4484
4804
|
nodesAdded++;
|
|
4485
4805
|
}
|
|
4486
|
-
const relDockerfile = toPosix2(
|
|
4806
|
+
const relDockerfile = toPosix2(import_node_path28.default.relative(service.dir, dockerfilePath));
|
|
4487
4807
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
4488
4808
|
graph,
|
|
4489
4809
|
service.pkg.name,
|
|
@@ -4492,17 +4812,17 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
4492
4812
|
);
|
|
4493
4813
|
nodesAdded += fn;
|
|
4494
4814
|
edgesAdded += fe;
|
|
4495
|
-
const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, node.id,
|
|
4815
|
+
const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, node.id, import_types19.EdgeType.RUNS_ON);
|
|
4496
4816
|
if (!graph.hasEdge(edgeId)) {
|
|
4497
4817
|
const edge = {
|
|
4498
4818
|
id: edgeId,
|
|
4499
4819
|
source: fileNodeId,
|
|
4500
4820
|
target: node.id,
|
|
4501
|
-
type:
|
|
4502
|
-
provenance:
|
|
4503
|
-
confidence: (0,
|
|
4821
|
+
type: import_types19.EdgeType.RUNS_ON,
|
|
4822
|
+
provenance: import_types19.Provenance.EXTRACTED,
|
|
4823
|
+
confidence: (0, import_types19.confidenceForExtracted)("structural"),
|
|
4504
4824
|
evidence: {
|
|
4505
|
-
file: toPosix2(
|
|
4825
|
+
file: toPosix2(import_node_path28.default.relative(scanPath, dockerfilePath))
|
|
4506
4826
|
}
|
|
4507
4827
|
};
|
|
4508
4828
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -4514,21 +4834,21 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
4514
4834
|
|
|
4515
4835
|
// src/extract/infra/terraform.ts
|
|
4516
4836
|
init_cjs_shims();
|
|
4517
|
-
var
|
|
4518
|
-
var
|
|
4837
|
+
var import_node_fs16 = require("fs");
|
|
4838
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
4519
4839
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
4520
4840
|
async function walkTfFiles(start, depth = 0, max = 5) {
|
|
4521
4841
|
if (depth > max) return [];
|
|
4522
4842
|
const out = [];
|
|
4523
|
-
const entries = await
|
|
4843
|
+
const entries = await import_node_fs16.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
4524
4844
|
for (const entry of entries) {
|
|
4525
4845
|
if (entry.isDirectory()) {
|
|
4526
4846
|
if (IGNORED_DIRS.has(entry.name) || entry.name === ".terraform") continue;
|
|
4527
|
-
const child =
|
|
4847
|
+
const child = import_node_path29.default.join(start, entry.name);
|
|
4528
4848
|
if (await isPythonVenvDir(child)) continue;
|
|
4529
4849
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
4530
4850
|
} else if (entry.isFile() && entry.name.endsWith(".tf")) {
|
|
4531
|
-
out.push(
|
|
4851
|
+
out.push(import_node_path29.default.join(start, entry.name));
|
|
4532
4852
|
}
|
|
4533
4853
|
}
|
|
4534
4854
|
return out;
|
|
@@ -4537,7 +4857,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
4537
4857
|
let nodesAdded = 0;
|
|
4538
4858
|
const files = await walkTfFiles(scanPath);
|
|
4539
4859
|
for (const file of files) {
|
|
4540
|
-
const content = await
|
|
4860
|
+
const content = await import_node_fs16.promises.readFile(file, "utf8");
|
|
4541
4861
|
RESOURCE_RE.lastIndex = 0;
|
|
4542
4862
|
let m;
|
|
4543
4863
|
while ((m = RESOURCE_RE.exec(content)) !== null) {
|
|
@@ -4555,8 +4875,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
4555
4875
|
|
|
4556
4876
|
// src/extract/infra/k8s.ts
|
|
4557
4877
|
init_cjs_shims();
|
|
4558
|
-
var
|
|
4559
|
-
var
|
|
4878
|
+
var import_node_fs17 = require("fs");
|
|
4879
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
4560
4880
|
var import_yaml3 = require("yaml");
|
|
4561
4881
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
4562
4882
|
Service: "k8s-service",
|
|
@@ -4570,15 +4890,15 @@ var K8S_KIND_TO_INFRA_KIND = {
|
|
|
4570
4890
|
async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
4571
4891
|
if (depth > max) return [];
|
|
4572
4892
|
const out = [];
|
|
4573
|
-
const entries = await
|
|
4893
|
+
const entries = await import_node_fs17.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
4574
4894
|
for (const entry of entries) {
|
|
4575
4895
|
if (entry.isDirectory()) {
|
|
4576
4896
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
4577
|
-
const child =
|
|
4897
|
+
const child = import_node_path30.default.join(start, entry.name);
|
|
4578
4898
|
if (await isPythonVenvDir(child)) continue;
|
|
4579
4899
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
4580
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
4581
|
-
out.push(
|
|
4900
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path30.default.extname(entry.name))) {
|
|
4901
|
+
out.push(import_node_path30.default.join(start, entry.name));
|
|
4582
4902
|
}
|
|
4583
4903
|
}
|
|
4584
4904
|
return out;
|
|
@@ -4587,7 +4907,7 @@ async function addK8sResources(graph, scanPath) {
|
|
|
4587
4907
|
let nodesAdded = 0;
|
|
4588
4908
|
const files = await walkYamlFiles2(scanPath);
|
|
4589
4909
|
for (const file of files) {
|
|
4590
|
-
const content = await
|
|
4910
|
+
const content = await import_node_fs17.promises.readFile(file, "utf8");
|
|
4591
4911
|
let docs;
|
|
4592
4912
|
try {
|
|
4593
4913
|
docs = (0, import_yaml3.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
@@ -4622,17 +4942,17 @@ async function addInfra(graph, scanPath, services) {
|
|
|
4622
4942
|
}
|
|
4623
4943
|
|
|
4624
4944
|
// src/extract/index.ts
|
|
4625
|
-
var
|
|
4945
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
4626
4946
|
|
|
4627
4947
|
// src/extract/retire.ts
|
|
4628
4948
|
init_cjs_shims();
|
|
4629
|
-
var
|
|
4630
|
-
var
|
|
4631
|
-
var
|
|
4949
|
+
var import_node_fs18 = require("fs");
|
|
4950
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
4951
|
+
var import_types20 = require("@neat.is/types");
|
|
4632
4952
|
function dropOrphanedFileNodes(graph) {
|
|
4633
4953
|
const orphans = [];
|
|
4634
4954
|
graph.forEachNode((id, attrs) => {
|
|
4635
|
-
if (attrs.type !==
|
|
4955
|
+
if (attrs.type !== import_types20.NodeType.FileNode) return;
|
|
4636
4956
|
if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
|
|
4637
4957
|
orphans.push(id);
|
|
4638
4958
|
}
|
|
@@ -4645,14 +4965,14 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
4645
4965
|
const bases = [scanPath, ...serviceDirs];
|
|
4646
4966
|
graph.forEachEdge((id, attrs) => {
|
|
4647
4967
|
const edge = attrs;
|
|
4648
|
-
if (edge.provenance !==
|
|
4968
|
+
if (edge.provenance !== import_types20.Provenance.EXTRACTED) return;
|
|
4649
4969
|
const evidenceFile = edge.evidence?.file;
|
|
4650
4970
|
if (!evidenceFile) return;
|
|
4651
|
-
if (
|
|
4652
|
-
if (!(0,
|
|
4971
|
+
if (import_node_path31.default.isAbsolute(evidenceFile)) {
|
|
4972
|
+
if (!(0, import_node_fs18.existsSync)(evidenceFile)) toDrop.push(id);
|
|
4653
4973
|
return;
|
|
4654
4974
|
}
|
|
4655
|
-
const found = bases.some((base) => (0,
|
|
4975
|
+
const found = bases.some((base) => (0, import_node_fs18.existsSync)(import_node_path31.default.join(base, evidenceFile)));
|
|
4656
4976
|
if (!found) toDrop.push(id);
|
|
4657
4977
|
});
|
|
4658
4978
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -4667,6 +4987,8 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
4667
4987
|
const services = await discoverServices(scanPath);
|
|
4668
4988
|
const phase1Nodes = addServiceNodes(graph, services);
|
|
4669
4989
|
await addServiceAliases(graph, scanPath, services);
|
|
4990
|
+
const fileEnum = await addFiles(graph, services);
|
|
4991
|
+
const importGraph = await addImports(graph, services);
|
|
4670
4992
|
const phase2 = await addDatabasesAndCompat(graph, services, scanPath);
|
|
4671
4993
|
const phase3 = await addConfigNodes(graph, services, scanPath);
|
|
4672
4994
|
const phase4 = await addCallEdges(graph, services);
|
|
@@ -4690,7 +5012,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
4690
5012
|
}
|
|
4691
5013
|
const droppedEntries = drainDroppedExtracted();
|
|
4692
5014
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
4693
|
-
const rejectedPath =
|
|
5015
|
+
const rejectedPath = import_node_path32.default.join(import_node_path32.default.dirname(opts.errorsPath), "rejected.ndjson");
|
|
4694
5016
|
try {
|
|
4695
5017
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
4696
5018
|
} catch (err) {
|
|
@@ -4700,8 +5022,8 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
4700
5022
|
}
|
|
4701
5023
|
}
|
|
4702
5024
|
const result = {
|
|
4703
|
-
nodesAdded: phase1Nodes + phase2.nodesAdded + phase3.nodesAdded + phase4.nodesAdded + phase5.nodesAdded,
|
|
4704
|
-
edgesAdded: phase2.edgesAdded + phase3.edgesAdded + phase4.edgesAdded + phase5.edgesAdded,
|
|
5025
|
+
nodesAdded: phase1Nodes + fileEnum.nodesAdded + importGraph.nodesAdded + phase2.nodesAdded + phase3.nodesAdded + phase4.nodesAdded + phase5.nodesAdded,
|
|
5026
|
+
edgesAdded: fileEnum.edgesAdded + importGraph.edgesAdded + phase2.edgesAdded + phase3.edgesAdded + phase4.edgesAdded + phase5.edgesAdded,
|
|
4705
5027
|
frontiersPromoted,
|
|
4706
5028
|
extractionErrors: errorEntries.length,
|
|
4707
5029
|
errorEntries,
|
|
@@ -4724,9 +5046,9 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
4724
5046
|
|
|
4725
5047
|
// src/persist.ts
|
|
4726
5048
|
init_cjs_shims();
|
|
4727
|
-
var
|
|
4728
|
-
var
|
|
4729
|
-
var
|
|
5049
|
+
var import_node_fs19 = require("fs");
|
|
5050
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
5051
|
+
var import_types21 = require("@neat.is/types");
|
|
4730
5052
|
var SCHEMA_VERSION = 4;
|
|
4731
5053
|
function migrateV1ToV2(payload) {
|
|
4732
5054
|
const nodes = payload.graph.nodes;
|
|
@@ -4748,12 +5070,12 @@ function migrateV2ToV3(payload) {
|
|
|
4748
5070
|
for (const edge of edges) {
|
|
4749
5071
|
const attrs = edge.attributes;
|
|
4750
5072
|
if (!attrs || attrs.provenance !== "FRONTIER") continue;
|
|
4751
|
-
attrs.provenance =
|
|
5073
|
+
attrs.provenance = import_types21.Provenance.OBSERVED;
|
|
4752
5074
|
const type = typeof attrs.type === "string" ? attrs.type : void 0;
|
|
4753
5075
|
const source = typeof attrs.source === "string" ? attrs.source : void 0;
|
|
4754
5076
|
const target = typeof attrs.target === "string" ? attrs.target : void 0;
|
|
4755
5077
|
if (type && source && target) {
|
|
4756
|
-
const newId = (0,
|
|
5078
|
+
const newId = (0, import_types21.observedEdgeId)(source, target, type);
|
|
4757
5079
|
attrs.id = newId;
|
|
4758
5080
|
if (edge.key) edge.key = newId;
|
|
4759
5081
|
}
|
|
@@ -4762,7 +5084,7 @@ function migrateV2ToV3(payload) {
|
|
|
4762
5084
|
return { ...payload, schemaVersion: 3 };
|
|
4763
5085
|
}
|
|
4764
5086
|
async function ensureDir(filePath) {
|
|
4765
|
-
await
|
|
5087
|
+
await import_node_fs19.promises.mkdir(import_node_path33.default.dirname(filePath), { recursive: true });
|
|
4766
5088
|
}
|
|
4767
5089
|
async function saveGraphToDisk(graph, outPath) {
|
|
4768
5090
|
await ensureDir(outPath);
|
|
@@ -4772,13 +5094,13 @@ async function saveGraphToDisk(graph, outPath) {
|
|
|
4772
5094
|
graph: graph.export()
|
|
4773
5095
|
};
|
|
4774
5096
|
const tmp = `${outPath}.tmp`;
|
|
4775
|
-
await
|
|
4776
|
-
await
|
|
5097
|
+
await import_node_fs19.promises.writeFile(tmp, JSON.stringify(payload), "utf8");
|
|
5098
|
+
await import_node_fs19.promises.rename(tmp, outPath);
|
|
4777
5099
|
}
|
|
4778
5100
|
async function loadGraphFromDisk(graph, outPath) {
|
|
4779
5101
|
let raw;
|
|
4780
5102
|
try {
|
|
4781
|
-
raw = await
|
|
5103
|
+
raw = await import_node_fs19.promises.readFile(outPath, "utf8");
|
|
4782
5104
|
} catch (err) {
|
|
4783
5105
|
if (err.code === "ENOENT") return;
|
|
4784
5106
|
throw err;
|
|
@@ -4839,19 +5161,19 @@ function startPersistLoop(graph, outPath, intervalMs = 6e4) {
|
|
|
4839
5161
|
init_cjs_shims();
|
|
4840
5162
|
var import_fastify = __toESM(require("fastify"), 1);
|
|
4841
5163
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
4842
|
-
var
|
|
5164
|
+
var import_types24 = require("@neat.is/types");
|
|
4843
5165
|
|
|
4844
5166
|
// src/extend/index.ts
|
|
4845
5167
|
init_cjs_shims();
|
|
4846
|
-
var
|
|
4847
|
-
var
|
|
5168
|
+
var import_node_fs21 = require("fs");
|
|
5169
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
4848
5170
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
4849
5171
|
var import_instrumentation_registry = require("@neat.is/instrumentation-registry");
|
|
4850
5172
|
|
|
4851
5173
|
// src/installers/package-manager.ts
|
|
4852
5174
|
init_cjs_shims();
|
|
4853
|
-
var
|
|
4854
|
-
var
|
|
5175
|
+
var import_node_fs20 = require("fs");
|
|
5176
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
4855
5177
|
var import_node_child_process = require("child_process");
|
|
4856
5178
|
var LOCKFILE_PRIORITY = [
|
|
4857
5179
|
{ lockfile: "bun.lockb", pm: "bun", args: ["install", "--no-summary"] },
|
|
@@ -4866,29 +5188,29 @@ var LOCKFILE_PRIORITY = [
|
|
|
4866
5188
|
var NPM_FALLBACK_ARGS = ["install", "--no-audit", "--no-fund", "--prefer-offline"];
|
|
4867
5189
|
async function exists2(p) {
|
|
4868
5190
|
try {
|
|
4869
|
-
await
|
|
5191
|
+
await import_node_fs20.promises.access(p);
|
|
4870
5192
|
return true;
|
|
4871
5193
|
} catch {
|
|
4872
5194
|
return false;
|
|
4873
5195
|
}
|
|
4874
5196
|
}
|
|
4875
5197
|
async function detectPackageManager(serviceDir) {
|
|
4876
|
-
let dir =
|
|
5198
|
+
let dir = import_node_path34.default.resolve(serviceDir);
|
|
4877
5199
|
const stops = /* @__PURE__ */ new Set();
|
|
4878
5200
|
for (let i = 0; i < 64; i++) {
|
|
4879
5201
|
if (stops.has(dir)) break;
|
|
4880
5202
|
stops.add(dir);
|
|
4881
5203
|
for (const candidate of LOCKFILE_PRIORITY) {
|
|
4882
|
-
const lockPath =
|
|
5204
|
+
const lockPath = import_node_path34.default.join(dir, candidate.lockfile);
|
|
4883
5205
|
if (await exists2(lockPath)) {
|
|
4884
5206
|
return { pm: candidate.pm, cwd: dir, args: [...candidate.args] };
|
|
4885
5207
|
}
|
|
4886
5208
|
}
|
|
4887
|
-
const parent =
|
|
5209
|
+
const parent = import_node_path34.default.dirname(dir);
|
|
4888
5210
|
if (parent === dir) break;
|
|
4889
5211
|
dir = parent;
|
|
4890
5212
|
}
|
|
4891
|
-
return { pm: "npm", cwd:
|
|
5213
|
+
return { pm: "npm", cwd: import_node_path34.default.resolve(serviceDir), args: [...NPM_FALLBACK_ARGS] };
|
|
4892
5214
|
}
|
|
4893
5215
|
async function runPackageManagerInstall(cmd) {
|
|
4894
5216
|
return new Promise((resolve) => {
|
|
@@ -4928,32 +5250,32 @@ ${err.message}`
|
|
|
4928
5250
|
}
|
|
4929
5251
|
|
|
4930
5252
|
// src/extend/index.ts
|
|
4931
|
-
async function
|
|
5253
|
+
async function fileExists2(p) {
|
|
4932
5254
|
try {
|
|
4933
|
-
await
|
|
5255
|
+
await import_node_fs21.promises.access(p);
|
|
4934
5256
|
return true;
|
|
4935
5257
|
} catch {
|
|
4936
5258
|
return false;
|
|
4937
5259
|
}
|
|
4938
5260
|
}
|
|
4939
5261
|
async function readPackageJson(scanPath) {
|
|
4940
|
-
const pkgPath =
|
|
4941
|
-
const raw = await
|
|
5262
|
+
const pkgPath = import_node_path35.default.join(scanPath, "package.json");
|
|
5263
|
+
const raw = await import_node_fs21.promises.readFile(pkgPath, "utf8");
|
|
4942
5264
|
return JSON.parse(raw);
|
|
4943
5265
|
}
|
|
4944
5266
|
async function findHookFiles(scanPath) {
|
|
4945
|
-
const entries = await
|
|
5267
|
+
const entries = await import_node_fs21.promises.readdir(scanPath);
|
|
4946
5268
|
return entries.filter(
|
|
4947
5269
|
(e) => (e.startsWith("instrumentation") || e.startsWith("otel-init")) && /\.(ts|js)$/.test(e)
|
|
4948
5270
|
).sort();
|
|
4949
5271
|
}
|
|
4950
5272
|
function extendLogPath() {
|
|
4951
|
-
return process.env.NEAT_EXTEND_LOG ??
|
|
5273
|
+
return process.env.NEAT_EXTEND_LOG ?? import_node_path35.default.join(import_node_os2.default.homedir(), ".neat", "extend-log.ndjson");
|
|
4952
5274
|
}
|
|
4953
5275
|
async function appendExtendLog(entry) {
|
|
4954
5276
|
const logPath = extendLogPath();
|
|
4955
|
-
await
|
|
4956
|
-
await
|
|
5277
|
+
await import_node_fs21.promises.mkdir(import_node_path35.default.dirname(logPath), { recursive: true });
|
|
5278
|
+
await import_node_fs21.promises.appendFile(logPath, JSON.stringify(entry) + "\n", "utf8");
|
|
4957
5279
|
}
|
|
4958
5280
|
function splicedContent(fileContent, snippet2) {
|
|
4959
5281
|
if (fileContent.includes("__INSTRUMENTATION_BLOCK__")) {
|
|
@@ -5011,7 +5333,7 @@ function lookupInstrumentation(library, installedVersion) {
|
|
|
5011
5333
|
}
|
|
5012
5334
|
async function describeProjectInstrumentation(ctx) {
|
|
5013
5335
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
5014
|
-
const envNeat = await
|
|
5336
|
+
const envNeat = await fileExists2(import_node_path35.default.join(ctx.scanPath, ".env.neat"));
|
|
5015
5337
|
const registryInstrPackages = new Set(
|
|
5016
5338
|
(0, import_instrumentation_registry.list)().map((e) => e.instrumentation_package).filter((p) => !!p)
|
|
5017
5339
|
);
|
|
@@ -5033,31 +5355,31 @@ async function applyExtension(ctx, args, options) {
|
|
|
5033
5355
|
);
|
|
5034
5356
|
}
|
|
5035
5357
|
for (const file of hookFiles) {
|
|
5036
|
-
const content = await
|
|
5358
|
+
const content = await import_node_fs21.promises.readFile(import_node_path35.default.join(ctx.scanPath, file), "utf8");
|
|
5037
5359
|
if (content.includes(args.registration_snippet)) {
|
|
5038
5360
|
return { library: args.library, filesTouched: [], depsAdded: [], installOutput: "", alreadyApplied: true };
|
|
5039
5361
|
}
|
|
5040
5362
|
}
|
|
5041
5363
|
const primaryFile = hookFiles[0];
|
|
5042
|
-
const primaryPath =
|
|
5364
|
+
const primaryPath = import_node_path35.default.join(ctx.scanPath, primaryFile);
|
|
5043
5365
|
const filesTouched = [];
|
|
5044
5366
|
const depsAdded = [];
|
|
5045
|
-
const pkgPath =
|
|
5367
|
+
const pkgPath = import_node_path35.default.join(ctx.scanPath, "package.json");
|
|
5046
5368
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
5047
5369
|
if (!(pkg.dependencies ?? {})[args.instrumentation_package]) {
|
|
5048
5370
|
pkg.dependencies = { ...pkg.dependencies ?? {}, [args.instrumentation_package]: args.version };
|
|
5049
|
-
await
|
|
5371
|
+
await import_node_fs21.promises.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
5050
5372
|
filesTouched.push("package.json");
|
|
5051
5373
|
depsAdded.push(`${args.instrumentation_package}@${args.version}`);
|
|
5052
5374
|
}
|
|
5053
|
-
const hookContent = await
|
|
5375
|
+
const hookContent = await import_node_fs21.promises.readFile(primaryPath, "utf8");
|
|
5054
5376
|
const patched = splicedContent(hookContent, args.registration_snippet);
|
|
5055
5377
|
if (!patched) {
|
|
5056
5378
|
throw new Error(
|
|
5057
5379
|
`Could not find instrumentation insertion point in ${primaryFile}. Expected __INSTRUMENTATION_BLOCK__, instrumentations.push(, or new NodeSDK(.`
|
|
5058
5380
|
);
|
|
5059
5381
|
}
|
|
5060
|
-
await
|
|
5382
|
+
await import_node_fs21.promises.writeFile(primaryPath, patched, "utf8");
|
|
5061
5383
|
filesTouched.push(primaryFile);
|
|
5062
5384
|
const cmd = await detectPackageManager(ctx.scanPath);
|
|
5063
5385
|
const installer = options?.runInstall ?? runPackageManagerInstall;
|
|
@@ -5088,7 +5410,7 @@ async function dryRunExtension(ctx, args) {
|
|
|
5088
5410
|
};
|
|
5089
5411
|
}
|
|
5090
5412
|
for (const file of hookFiles) {
|
|
5091
|
-
const content = await
|
|
5413
|
+
const content = await import_node_fs21.promises.readFile(import_node_path35.default.join(ctx.scanPath, file), "utf8");
|
|
5092
5414
|
if (content.includes(args.registration_snippet)) {
|
|
5093
5415
|
return {
|
|
5094
5416
|
library: args.library,
|
|
@@ -5110,7 +5432,7 @@ async function dryRunExtension(ctx, args) {
|
|
|
5110
5432
|
depsToAdd.push(`${args.instrumentation_package}@${args.version}`);
|
|
5111
5433
|
filesTouched.push("package.json");
|
|
5112
5434
|
}
|
|
5113
|
-
const hookContent = await
|
|
5435
|
+
const hookContent = await import_node_fs21.promises.readFile(import_node_path35.default.join(ctx.scanPath, primaryFile), "utf8");
|
|
5114
5436
|
const patched = splicedContent(hookContent, args.registration_snippet);
|
|
5115
5437
|
if (patched) {
|
|
5116
5438
|
filesTouched.push(primaryFile);
|
|
@@ -5122,31 +5444,31 @@ async function dryRunExtension(ctx, args) {
|
|
|
5122
5444
|
}
|
|
5123
5445
|
async function rollbackExtension(ctx, args) {
|
|
5124
5446
|
const logPath = extendLogPath();
|
|
5125
|
-
if (!await
|
|
5447
|
+
if (!await fileExists2(logPath)) {
|
|
5126
5448
|
return { undone: false, message: "no apply found for library" };
|
|
5127
5449
|
}
|
|
5128
|
-
const raw = await
|
|
5450
|
+
const raw = await import_node_fs21.promises.readFile(logPath, "utf8");
|
|
5129
5451
|
const entries = raw.trim().split("\n").filter(Boolean).map((line) => JSON.parse(line));
|
|
5130
5452
|
const match = [...entries].reverse().find((e) => e.project === ctx.project && e.library === args.library);
|
|
5131
5453
|
if (!match) {
|
|
5132
5454
|
return { undone: false, message: "no apply found for library" };
|
|
5133
5455
|
}
|
|
5134
|
-
const pkgPath =
|
|
5135
|
-
if (await
|
|
5456
|
+
const pkgPath = import_node_path35.default.join(ctx.scanPath, "package.json");
|
|
5457
|
+
if (await fileExists2(pkgPath)) {
|
|
5136
5458
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
5137
5459
|
if (pkg.dependencies?.[match.instrumentation_package]) {
|
|
5138
5460
|
const { [match.instrumentation_package]: _removed, ...rest } = pkg.dependencies;
|
|
5139
5461
|
pkg.dependencies = rest;
|
|
5140
|
-
await
|
|
5462
|
+
await import_node_fs21.promises.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
5141
5463
|
}
|
|
5142
5464
|
}
|
|
5143
5465
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
5144
5466
|
for (const file of hookFiles) {
|
|
5145
|
-
const filePath =
|
|
5146
|
-
const content = await
|
|
5467
|
+
const filePath = import_node_path35.default.join(ctx.scanPath, file);
|
|
5468
|
+
const content = await import_node_fs21.promises.readFile(filePath, "utf8");
|
|
5147
5469
|
if (content.includes(match.registration_snippet)) {
|
|
5148
5470
|
const filtered = content.split("\n").filter((line) => !line.includes(match.registration_snippet)).join("\n");
|
|
5149
|
-
await
|
|
5471
|
+
await import_node_fs21.promises.writeFile(filePath, filtered, "utf8");
|
|
5150
5472
|
break;
|
|
5151
5473
|
}
|
|
5152
5474
|
}
|
|
@@ -5158,7 +5480,7 @@ async function rollbackExtension(ctx, args) {
|
|
|
5158
5480
|
|
|
5159
5481
|
// src/divergences.ts
|
|
5160
5482
|
init_cjs_shims();
|
|
5161
|
-
var
|
|
5483
|
+
var import_types22 = require("@neat.is/types");
|
|
5162
5484
|
function bucketKey(source, target, type) {
|
|
5163
5485
|
return `${type}|${source}|${target}`;
|
|
5164
5486
|
}
|
|
@@ -5166,22 +5488,22 @@ function bucketEdges(graph) {
|
|
|
5166
5488
|
const buckets = /* @__PURE__ */ new Map();
|
|
5167
5489
|
graph.forEachEdge((id, attrs) => {
|
|
5168
5490
|
const e = attrs;
|
|
5169
|
-
const parsed = (0,
|
|
5491
|
+
const parsed = (0, import_types22.parseEdgeId)(id);
|
|
5170
5492
|
const provenance = parsed?.provenance ?? e.provenance;
|
|
5171
5493
|
const key = bucketKey(e.source, e.target, e.type);
|
|
5172
5494
|
const cur = buckets.get(key) ?? { source: e.source, target: e.target, type: e.type };
|
|
5173
5495
|
switch (provenance) {
|
|
5174
|
-
case
|
|
5496
|
+
case import_types22.Provenance.EXTRACTED:
|
|
5175
5497
|
cur.extracted = e;
|
|
5176
5498
|
break;
|
|
5177
|
-
case
|
|
5499
|
+
case import_types22.Provenance.OBSERVED:
|
|
5178
5500
|
cur.observed = e;
|
|
5179
5501
|
break;
|
|
5180
|
-
case
|
|
5502
|
+
case import_types22.Provenance.INFERRED:
|
|
5181
5503
|
cur.inferred = e;
|
|
5182
5504
|
break;
|
|
5183
5505
|
default:
|
|
5184
|
-
if (e.provenance ===
|
|
5506
|
+
if (e.provenance === import_types22.Provenance.STALE) cur.stale = e;
|
|
5185
5507
|
}
|
|
5186
5508
|
buckets.set(key, cur);
|
|
5187
5509
|
});
|
|
@@ -5190,7 +5512,7 @@ function bucketEdges(graph) {
|
|
|
5190
5512
|
function nodeIsFrontier(graph, nodeId) {
|
|
5191
5513
|
if (!graph.hasNode(nodeId)) return false;
|
|
5192
5514
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
5193
|
-
return attrs.type ===
|
|
5515
|
+
return attrs.type === import_types22.NodeType.FrontierNode;
|
|
5194
5516
|
}
|
|
5195
5517
|
function clampConfidence(n) {
|
|
5196
5518
|
if (!Number.isFinite(n)) return 0;
|
|
@@ -5211,7 +5533,7 @@ function gradedConfidence(edge) {
|
|
|
5211
5533
|
}
|
|
5212
5534
|
function detectMissingDivergences(graph, bucket) {
|
|
5213
5535
|
const out = [];
|
|
5214
|
-
if (bucket.type ===
|
|
5536
|
+
if (bucket.type === import_types22.EdgeType.CONTAINS) return out;
|
|
5215
5537
|
if (bucket.extracted && !bucket.observed) {
|
|
5216
5538
|
if (!nodeIsFrontier(graph, bucket.target)) {
|
|
5217
5539
|
out.push({
|
|
@@ -5252,7 +5574,7 @@ function declaredHostFor(svc) {
|
|
|
5252
5574
|
function hasExtractedConfiguredBy(graph, svcId) {
|
|
5253
5575
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
5254
5576
|
const e = graph.getEdgeAttributes(edgeId);
|
|
5255
|
-
if (e.type ===
|
|
5577
|
+
if (e.type === import_types22.EdgeType.CONFIGURED_BY && e.provenance === import_types22.Provenance.EXTRACTED) {
|
|
5256
5578
|
return true;
|
|
5257
5579
|
}
|
|
5258
5580
|
}
|
|
@@ -5265,10 +5587,10 @@ function detectHostMismatch(graph, svcId, svc) {
|
|
|
5265
5587
|
const out = [];
|
|
5266
5588
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
5267
5589
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
5268
|
-
if (edge.type !==
|
|
5269
|
-
if (edge.provenance !==
|
|
5590
|
+
if (edge.type !== import_types22.EdgeType.CONNECTS_TO) continue;
|
|
5591
|
+
if (edge.provenance !== import_types22.Provenance.OBSERVED) continue;
|
|
5270
5592
|
const target = graph.getNodeAttributes(edge.target);
|
|
5271
|
-
if (target.type !==
|
|
5593
|
+
if (target.type !== import_types22.NodeType.DatabaseNode) continue;
|
|
5272
5594
|
const observedHost = target.host?.trim();
|
|
5273
5595
|
if (!observedHost) continue;
|
|
5274
5596
|
if (observedHost === declaredHost) continue;
|
|
@@ -5290,10 +5612,10 @@ function detectCompatDivergences(graph, svcId, svc) {
|
|
|
5290
5612
|
const deps = svc.dependencies ?? {};
|
|
5291
5613
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
5292
5614
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
5293
|
-
if (edge.type !==
|
|
5294
|
-
if (edge.provenance !==
|
|
5615
|
+
if (edge.type !== import_types22.EdgeType.CONNECTS_TO) continue;
|
|
5616
|
+
if (edge.provenance !== import_types22.Provenance.OBSERVED) continue;
|
|
5295
5617
|
const target = graph.getNodeAttributes(edge.target);
|
|
5296
|
-
if (target.type !==
|
|
5618
|
+
if (target.type !== import_types22.NodeType.DatabaseNode) continue;
|
|
5297
5619
|
for (const pair of compatPairs()) {
|
|
5298
5620
|
if (pair.engine !== target.engine) continue;
|
|
5299
5621
|
const declared = deps[pair.driver];
|
|
@@ -5354,7 +5676,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
5354
5676
|
}
|
|
5355
5677
|
graph.forEachNode((nodeId, attrs) => {
|
|
5356
5678
|
const n = attrs;
|
|
5357
|
-
if (n.type !==
|
|
5679
|
+
if (n.type !== import_types22.NodeType.ServiceNode) return;
|
|
5358
5680
|
const svc = n;
|
|
5359
5681
|
for (const d of detectHostMismatch(graph, nodeId, svc)) all.push(d);
|
|
5360
5682
|
for (const d of detectCompatDivergences(graph, nodeId, svc)) all.push(d);
|
|
@@ -5387,7 +5709,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
5387
5709
|
if (a.source !== b.source) return a.source.localeCompare(b.source);
|
|
5388
5710
|
return a.target.localeCompare(b.target);
|
|
5389
5711
|
});
|
|
5390
|
-
return
|
|
5712
|
+
return import_types22.DivergenceResultSchema.parse({
|
|
5391
5713
|
divergences: filtered,
|
|
5392
5714
|
totalAffected: filtered.length,
|
|
5393
5715
|
computedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -5396,7 +5718,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
5396
5718
|
|
|
5397
5719
|
// src/diff.ts
|
|
5398
5720
|
init_cjs_shims();
|
|
5399
|
-
var
|
|
5721
|
+
var import_node_fs22 = require("fs");
|
|
5400
5722
|
async function loadSnapshotForDiff(target) {
|
|
5401
5723
|
if (/^https?:\/\//i.test(target)) {
|
|
5402
5724
|
const res = await fetch(target);
|
|
@@ -5405,7 +5727,7 @@ async function loadSnapshotForDiff(target) {
|
|
|
5405
5727
|
}
|
|
5406
5728
|
return await res.json();
|
|
5407
5729
|
}
|
|
5408
|
-
const raw = await
|
|
5730
|
+
const raw = await import_node_fs22.promises.readFile(target, "utf8");
|
|
5409
5731
|
return JSON.parse(raw);
|
|
5410
5732
|
}
|
|
5411
5733
|
function indexEntries(entries) {
|
|
@@ -5473,23 +5795,23 @@ function canonicalJson(value) {
|
|
|
5473
5795
|
|
|
5474
5796
|
// src/projects.ts
|
|
5475
5797
|
init_cjs_shims();
|
|
5476
|
-
var
|
|
5798
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
5477
5799
|
function pathsForProject(project, baseDir) {
|
|
5478
5800
|
if (project === DEFAULT_PROJECT) {
|
|
5479
5801
|
return {
|
|
5480
|
-
snapshotPath:
|
|
5481
|
-
errorsPath:
|
|
5482
|
-
staleEventsPath:
|
|
5483
|
-
embeddingsCachePath:
|
|
5484
|
-
policyViolationsPath:
|
|
5802
|
+
snapshotPath: import_node_path36.default.join(baseDir, "graph.json"),
|
|
5803
|
+
errorsPath: import_node_path36.default.join(baseDir, "errors.ndjson"),
|
|
5804
|
+
staleEventsPath: import_node_path36.default.join(baseDir, "stale-events.ndjson"),
|
|
5805
|
+
embeddingsCachePath: import_node_path36.default.join(baseDir, "embeddings.json"),
|
|
5806
|
+
policyViolationsPath: import_node_path36.default.join(baseDir, "policy-violations.ndjson")
|
|
5485
5807
|
};
|
|
5486
5808
|
}
|
|
5487
5809
|
return {
|
|
5488
|
-
snapshotPath:
|
|
5489
|
-
errorsPath:
|
|
5490
|
-
staleEventsPath:
|
|
5491
|
-
embeddingsCachePath:
|
|
5492
|
-
policyViolationsPath:
|
|
5810
|
+
snapshotPath: import_node_path36.default.join(baseDir, `${project}.json`),
|
|
5811
|
+
errorsPath: import_node_path36.default.join(baseDir, `errors.${project}.ndjson`),
|
|
5812
|
+
staleEventsPath: import_node_path36.default.join(baseDir, `stale-events.${project}.ndjson`),
|
|
5813
|
+
embeddingsCachePath: import_node_path36.default.join(baseDir, `embeddings.${project}.json`),
|
|
5814
|
+
policyViolationsPath: import_node_path36.default.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
5493
5815
|
};
|
|
5494
5816
|
}
|
|
5495
5817
|
var Projects = class {
|
|
@@ -5525,25 +5847,25 @@ var Projects = class {
|
|
|
5525
5847
|
|
|
5526
5848
|
// src/registry.ts
|
|
5527
5849
|
init_cjs_shims();
|
|
5528
|
-
var
|
|
5850
|
+
var import_node_fs23 = require("fs");
|
|
5529
5851
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
5530
|
-
var
|
|
5531
|
-
var
|
|
5852
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
5853
|
+
var import_types23 = require("@neat.is/types");
|
|
5532
5854
|
var LOCK_TIMEOUT_MS = 5e3;
|
|
5533
5855
|
var LOCK_RETRY_MS = 50;
|
|
5534
5856
|
function neatHome() {
|
|
5535
5857
|
const override = process.env.NEAT_HOME;
|
|
5536
|
-
if (override && override.length > 0) return
|
|
5537
|
-
return
|
|
5858
|
+
if (override && override.length > 0) return import_node_path37.default.resolve(override);
|
|
5859
|
+
return import_node_path37.default.join(import_node_os3.default.homedir(), ".neat");
|
|
5538
5860
|
}
|
|
5539
5861
|
function registryPath() {
|
|
5540
|
-
return
|
|
5862
|
+
return import_node_path37.default.join(neatHome(), "projects.json");
|
|
5541
5863
|
}
|
|
5542
5864
|
function registryLockPath() {
|
|
5543
|
-
return
|
|
5865
|
+
return import_node_path37.default.join(neatHome(), "projects.json.lock");
|
|
5544
5866
|
}
|
|
5545
5867
|
function daemonPidPath() {
|
|
5546
|
-
return
|
|
5868
|
+
return import_node_path37.default.join(neatHome(), "neatd.pid");
|
|
5547
5869
|
}
|
|
5548
5870
|
function isPidAliveDefault(pid) {
|
|
5549
5871
|
try {
|
|
@@ -5555,7 +5877,7 @@ function isPidAliveDefault(pid) {
|
|
|
5555
5877
|
}
|
|
5556
5878
|
async function readPidFile(file) {
|
|
5557
5879
|
try {
|
|
5558
|
-
const raw = await
|
|
5880
|
+
const raw = await import_node_fs23.promises.readFile(file, "utf8");
|
|
5559
5881
|
const pid = Number.parseInt(raw.trim(), 10);
|
|
5560
5882
|
return Number.isInteger(pid) && pid > 0 ? pid : void 0;
|
|
5561
5883
|
} catch {
|
|
@@ -5603,32 +5925,32 @@ function lockHolderMessage(holder, lockPath, timeoutMs) {
|
|
|
5603
5925
|
}
|
|
5604
5926
|
}
|
|
5605
5927
|
async function normalizeProjectPath(input) {
|
|
5606
|
-
const resolved =
|
|
5928
|
+
const resolved = import_node_path37.default.resolve(input);
|
|
5607
5929
|
try {
|
|
5608
|
-
return await
|
|
5930
|
+
return await import_node_fs23.promises.realpath(resolved);
|
|
5609
5931
|
} catch {
|
|
5610
5932
|
return resolved;
|
|
5611
5933
|
}
|
|
5612
5934
|
}
|
|
5613
5935
|
async function writeAtomically(target, contents) {
|
|
5614
|
-
await
|
|
5936
|
+
await import_node_fs23.promises.mkdir(import_node_path37.default.dirname(target), { recursive: true });
|
|
5615
5937
|
const tmp = `${target}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
5616
|
-
const fd = await
|
|
5938
|
+
const fd = await import_node_fs23.promises.open(tmp, "w");
|
|
5617
5939
|
try {
|
|
5618
5940
|
await fd.writeFile(contents, "utf8");
|
|
5619
5941
|
await fd.sync();
|
|
5620
5942
|
} finally {
|
|
5621
5943
|
await fd.close();
|
|
5622
5944
|
}
|
|
5623
|
-
await
|
|
5945
|
+
await import_node_fs23.promises.rename(tmp, target);
|
|
5624
5946
|
}
|
|
5625
5947
|
async function acquireLock(lockPath, timeoutMs = LOCK_TIMEOUT_MS, probe = defaultLockHolderProbe) {
|
|
5626
5948
|
const deadline = Date.now() + timeoutMs;
|
|
5627
|
-
await
|
|
5949
|
+
await import_node_fs23.promises.mkdir(import_node_path37.default.dirname(lockPath), { recursive: true });
|
|
5628
5950
|
let probedHolder = false;
|
|
5629
5951
|
while (true) {
|
|
5630
5952
|
try {
|
|
5631
|
-
const fd = await
|
|
5953
|
+
const fd = await import_node_fs23.promises.open(lockPath, "wx");
|
|
5632
5954
|
try {
|
|
5633
5955
|
await fd.writeFile(`${process.pid}
|
|
5634
5956
|
`, "utf8");
|
|
@@ -5653,7 +5975,7 @@ async function acquireLock(lockPath, timeoutMs = LOCK_TIMEOUT_MS, probe = defaul
|
|
|
5653
5975
|
}
|
|
5654
5976
|
}
|
|
5655
5977
|
async function releaseLock(lockPath) {
|
|
5656
|
-
await
|
|
5978
|
+
await import_node_fs23.promises.unlink(lockPath).catch(() => {
|
|
5657
5979
|
});
|
|
5658
5980
|
}
|
|
5659
5981
|
async function withLock(fn) {
|
|
@@ -5669,7 +5991,7 @@ async function readRegistry() {
|
|
|
5669
5991
|
const file = registryPath();
|
|
5670
5992
|
let raw;
|
|
5671
5993
|
try {
|
|
5672
|
-
raw = await
|
|
5994
|
+
raw = await import_node_fs23.promises.readFile(file, "utf8");
|
|
5673
5995
|
} catch (err) {
|
|
5674
5996
|
if (err.code === "ENOENT") {
|
|
5675
5997
|
return { version: 1, projects: [] };
|
|
@@ -5677,10 +5999,10 @@ async function readRegistry() {
|
|
|
5677
5999
|
throw err;
|
|
5678
6000
|
}
|
|
5679
6001
|
const parsed = JSON.parse(raw);
|
|
5680
|
-
return
|
|
6002
|
+
return import_types23.RegistryFileSchema.parse(parsed);
|
|
5681
6003
|
}
|
|
5682
6004
|
async function writeRegistry(reg) {
|
|
5683
|
-
const validated =
|
|
6005
|
+
const validated = import_types23.RegistryFileSchema.parse(reg);
|
|
5684
6006
|
await writeAtomically(registryPath(), JSON.stringify(validated, null, 2) + "\n");
|
|
5685
6007
|
}
|
|
5686
6008
|
var ProjectNameCollisionError = class extends Error {
|
|
@@ -5952,11 +6274,11 @@ function registerRoutes(scope, ctx) {
|
|
|
5952
6274
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
5953
6275
|
const parsed = [];
|
|
5954
6276
|
for (const c of candidates) {
|
|
5955
|
-
const r =
|
|
6277
|
+
const r = import_types24.DivergenceTypeSchema.safeParse(c);
|
|
5956
6278
|
if (!r.success) {
|
|
5957
6279
|
return reply.code(400).send({
|
|
5958
6280
|
error: `unknown divergence type "${c}"`,
|
|
5959
|
-
allowed:
|
|
6281
|
+
allowed: import_types24.DivergenceTypeSchema.options
|
|
5960
6282
|
});
|
|
5961
6283
|
}
|
|
5962
6284
|
parsed.push(r.data);
|
|
@@ -6169,7 +6491,7 @@ function registerRoutes(scope, ctx) {
|
|
|
6169
6491
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
6170
6492
|
let violations = await log.readAll();
|
|
6171
6493
|
if (req.query.severity) {
|
|
6172
|
-
const sev =
|
|
6494
|
+
const sev = import_types24.PolicySeveritySchema.safeParse(req.query.severity);
|
|
6173
6495
|
if (!sev.success) {
|
|
6174
6496
|
return reply.code(400).send({
|
|
6175
6497
|
error: "invalid severity",
|
|
@@ -6186,7 +6508,7 @@ function registerRoutes(scope, ctx) {
|
|
|
6186
6508
|
scope.post("/policies/check", async (req, reply) => {
|
|
6187
6509
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap);
|
|
6188
6510
|
if (!proj) return;
|
|
6189
|
-
const parsed =
|
|
6511
|
+
const parsed = import_types24.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
6190
6512
|
if (!parsed.success) {
|
|
6191
6513
|
return reply.code(400).send({
|
|
6192
6514
|
error: "invalid /policies/check body",
|
|
@@ -6428,15 +6750,15 @@ init_otel_grpc();
|
|
|
6428
6750
|
|
|
6429
6751
|
// src/daemon.ts
|
|
6430
6752
|
init_cjs_shims();
|
|
6431
|
-
var
|
|
6432
|
-
var
|
|
6753
|
+
var import_node_fs25 = require("fs");
|
|
6754
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
6433
6755
|
init_otel();
|
|
6434
6756
|
init_auth();
|
|
6435
6757
|
|
|
6436
6758
|
// src/unrouted.ts
|
|
6437
6759
|
init_cjs_shims();
|
|
6438
|
-
var
|
|
6439
|
-
var
|
|
6760
|
+
var import_node_fs24 = require("fs");
|
|
6761
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
6440
6762
|
function buildUnroutedSpanRecord(serviceName, traceId, now = /* @__PURE__ */ new Date()) {
|
|
6441
6763
|
return {
|
|
6442
6764
|
timestamp: now.toISOString(),
|
|
@@ -6446,21 +6768,21 @@ function buildUnroutedSpanRecord(serviceName, traceId, now = /* @__PURE__ */ new
|
|
|
6446
6768
|
};
|
|
6447
6769
|
}
|
|
6448
6770
|
async function appendUnroutedSpan(neatHome2, record) {
|
|
6449
|
-
const target =
|
|
6450
|
-
await
|
|
6451
|
-
await
|
|
6771
|
+
const target = import_node_path40.default.join(neatHome2, "errors.ndjson");
|
|
6772
|
+
await import_node_fs24.promises.mkdir(neatHome2, { recursive: true });
|
|
6773
|
+
await import_node_fs24.promises.appendFile(target, JSON.stringify(record) + "\n", "utf8");
|
|
6452
6774
|
}
|
|
6453
6775
|
function unroutedErrorsPath(neatHome2) {
|
|
6454
|
-
return
|
|
6776
|
+
return import_node_path40.default.join(neatHome2, "errors.ndjson");
|
|
6455
6777
|
}
|
|
6456
6778
|
|
|
6457
6779
|
// src/daemon.ts
|
|
6458
6780
|
function neatHomeFor(opts) {
|
|
6459
|
-
if (opts.neatHome && opts.neatHome.length > 0) return
|
|
6781
|
+
if (opts.neatHome && opts.neatHome.length > 0) return import_node_path41.default.resolve(opts.neatHome);
|
|
6460
6782
|
const env = process.env.NEAT_HOME;
|
|
6461
|
-
if (env && env.length > 0) return
|
|
6783
|
+
if (env && env.length > 0) return import_node_path41.default.resolve(env);
|
|
6462
6784
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
6463
|
-
return
|
|
6785
|
+
return import_node_path41.default.join(home, ".neat");
|
|
6464
6786
|
}
|
|
6465
6787
|
function routeSpanToProject(serviceName, projects) {
|
|
6466
6788
|
if (!serviceName) return DEFAULT_PROJECT;
|
|
@@ -6495,9 +6817,9 @@ function isTokenContained(needle, haystack) {
|
|
|
6495
6817
|
return tokens.includes(needle);
|
|
6496
6818
|
}
|
|
6497
6819
|
async function bootstrapProject(entry) {
|
|
6498
|
-
const paths = pathsForProject(entry.name,
|
|
6820
|
+
const paths = pathsForProject(entry.name, import_node_path41.default.join(entry.path, "neat-out"));
|
|
6499
6821
|
try {
|
|
6500
|
-
const stat = await
|
|
6822
|
+
const stat = await import_node_fs25.promises.stat(entry.path);
|
|
6501
6823
|
if (!stat.isDirectory()) {
|
|
6502
6824
|
throw new Error(`registered path ${entry.path} is not a directory`);
|
|
6503
6825
|
}
|
|
@@ -6563,13 +6885,13 @@ async function startDaemon(opts = {}) {
|
|
|
6563
6885
|
const home = neatHomeFor(opts);
|
|
6564
6886
|
const regPath = registryPath();
|
|
6565
6887
|
try {
|
|
6566
|
-
await
|
|
6888
|
+
await import_node_fs25.promises.access(regPath);
|
|
6567
6889
|
} catch {
|
|
6568
6890
|
throw new Error(
|
|
6569
6891
|
`neatd: registry not found at ${regPath}. Run \`neat init <path>\` to register a project before starting the daemon.`
|
|
6570
6892
|
);
|
|
6571
6893
|
}
|
|
6572
|
-
const pidPath =
|
|
6894
|
+
const pidPath = import_node_path41.default.join(home, "neatd.pid");
|
|
6573
6895
|
await writeAtomically(pidPath, `${process.pid}
|
|
6574
6896
|
`);
|
|
6575
6897
|
const slots = /* @__PURE__ */ new Map();
|
|
@@ -6727,7 +7049,7 @@ async function startDaemon(opts = {}) {
|
|
|
6727
7049
|
}
|
|
6728
7050
|
if (restApp) await restApp.close().catch(() => {
|
|
6729
7051
|
});
|
|
6730
|
-
await
|
|
7052
|
+
await import_node_fs25.promises.unlink(pidPath).catch(() => {
|
|
6731
7053
|
});
|
|
6732
7054
|
throw new Error(
|
|
6733
7055
|
`neatd: failed to bind REST on port ${restPort} \u2014 ${err.message}`
|
|
@@ -6833,7 +7155,7 @@ async function startDaemon(opts = {}) {
|
|
|
6833
7155
|
});
|
|
6834
7156
|
if (otlpApp) await otlpApp.close().catch(() => {
|
|
6835
7157
|
});
|
|
6836
|
-
await
|
|
7158
|
+
await import_node_fs25.promises.unlink(pidPath).catch(() => {
|
|
6837
7159
|
});
|
|
6838
7160
|
throw new Error(
|
|
6839
7161
|
`neatd: failed to bind OTLP on port ${otlpPort} \u2014 ${err.message}`
|
|
@@ -6879,9 +7201,9 @@ async function startDaemon(opts = {}) {
|
|
|
6879
7201
|
let registryWatcher = null;
|
|
6880
7202
|
let reloadTimer = null;
|
|
6881
7203
|
try {
|
|
6882
|
-
const regDir =
|
|
6883
|
-
const regBase =
|
|
6884
|
-
registryWatcher = (0,
|
|
7204
|
+
const regDir = import_node_path41.default.dirname(regPath);
|
|
7205
|
+
const regBase = import_node_path41.default.basename(regPath);
|
|
7206
|
+
registryWatcher = (0, import_node_fs25.watch)(regDir, (_eventType, filename) => {
|
|
6885
7207
|
if (filename !== null && filename !== regBase) return;
|
|
6886
7208
|
if (reloadTimer) clearTimeout(reloadTimer);
|
|
6887
7209
|
reloadTimer = setTimeout(() => {
|
|
@@ -6924,7 +7246,7 @@ async function startDaemon(opts = {}) {
|
|
|
6924
7246
|
} catch {
|
|
6925
7247
|
}
|
|
6926
7248
|
}
|
|
6927
|
-
await
|
|
7249
|
+
await import_node_fs25.promises.unlink(pidPath).catch(() => {
|
|
6928
7250
|
});
|
|
6929
7251
|
};
|
|
6930
7252
|
return {
|