@neat.is/core 0.4.12 → 0.4.14
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-HVF4S7J3.js → chunk-6CO7C4IU.js} +6 -3
- package/dist/{chunk-HVF4S7J3.js.map → chunk-6CO7C4IU.js.map} +1 -1
- package/dist/{chunk-3QCRUEQD.js → chunk-GHPHVXYM.js} +5 -3
- package/dist/chunk-GHPHVXYM.js.map +1 -0
- package/dist/{chunk-7JY6F7BY.js → chunk-QZRDQ7WX.js} +3 -3
- package/dist/{chunk-WDG4QEFO.js → chunk-XS4CGNRO.js} +558 -233
- package/dist/chunk-XS4CGNRO.js.map +1 -0
- package/dist/cli.cjs +801 -458
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +21 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +613 -286
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +620 -293
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-VSPMP3OS.js → otel-grpc-QAISVAY5.js} +3 -3
- package/dist/server.cjs +538 -211
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +6 -2
- package/dist/chunk-3QCRUEQD.js.map +0 -1
- package/dist/chunk-WDG4QEFO.js.map +0 -1
- /package/dist/{chunk-7JY6F7BY.js.map → chunk-QZRDQ7WX.js.map} +0 -0
- /package/dist/{otel-grpc-VSPMP3OS.js.map → otel-grpc-QAISVAY5.js.map} +0 -0
package/dist/neatd.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", (req2, reply, done) => {
|
|
60
|
-
const
|
|
60
|
+
const path44 = (req2.url.split("?")[0] ?? "").replace(/\/+$/, "");
|
|
61
61
|
for (const suffix of suffixes) {
|
|
62
|
-
if (
|
|
62
|
+
if (path44 === suffix || path44.endsWith(suffix)) {
|
|
63
63
|
done();
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
@@ -133,7 +133,9 @@ __export(otel_grpc_exports, {
|
|
|
133
133
|
});
|
|
134
134
|
function bytesToHex(buf) {
|
|
135
135
|
if (!buf) return "";
|
|
136
|
-
|
|
136
|
+
if (Buffer.isBuffer(buf)) return buf.toString("hex");
|
|
137
|
+
if (buf instanceof Uint8Array) return Buffer.from(buf).toString("hex");
|
|
138
|
+
return "";
|
|
137
139
|
}
|
|
138
140
|
function nanosToString(n) {
|
|
139
141
|
if (n === void 0 || n === null) return "0";
|
|
@@ -185,8 +187,8 @@ function reshapeGrpcRequest(req2) {
|
|
|
185
187
|
};
|
|
186
188
|
}
|
|
187
189
|
function resolveProtoRoot() {
|
|
188
|
-
const here =
|
|
189
|
-
return
|
|
190
|
+
const here = import_node_path38.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
191
|
+
return import_node_path38.default.resolve(here, "..", "proto");
|
|
190
192
|
}
|
|
191
193
|
function loadTraceService() {
|
|
192
194
|
const protoRoot = resolveProtoRoot();
|
|
@@ -254,13 +256,13 @@ async function startOtelGrpcReceiver(opts) {
|
|
|
254
256
|
})
|
|
255
257
|
};
|
|
256
258
|
}
|
|
257
|
-
var import_node_url,
|
|
259
|
+
var import_node_url, import_node_path38, import_node_crypto2, grpc, protoLoader;
|
|
258
260
|
var init_otel_grpc = __esm({
|
|
259
261
|
"src/otel-grpc.ts"() {
|
|
260
262
|
"use strict";
|
|
261
263
|
init_cjs_shims();
|
|
262
264
|
import_node_url = require("url");
|
|
263
|
-
|
|
265
|
+
import_node_path38 = __toESM(require("path"), 1);
|
|
264
266
|
import_node_crypto2 = require("crypto");
|
|
265
267
|
grpc = __toESM(require("@grpc/grpc-js"), 1);
|
|
266
268
|
protoLoader = __toESM(require("@grpc/proto-loader"), 1);
|
|
@@ -370,10 +372,10 @@ function parseOtlpRequest(body) {
|
|
|
370
372
|
return out;
|
|
371
373
|
}
|
|
372
374
|
function loadProtoRoot() {
|
|
373
|
-
const here =
|
|
374
|
-
const protoRoot =
|
|
375
|
+
const here = import_node_path39.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
376
|
+
const protoRoot = import_node_path39.default.resolve(here, "..", "proto");
|
|
375
377
|
const root = new import_protobufjs.default.Root();
|
|
376
|
-
root.resolvePath = (_origin, target) =>
|
|
378
|
+
root.resolvePath = (_origin, target) => import_node_path39.default.resolve(protoRoot, target);
|
|
377
379
|
root.loadSync(
|
|
378
380
|
"opentelemetry/proto/collector/trace/v1/trace_service.proto",
|
|
379
381
|
{ keepCase: true }
|
|
@@ -406,7 +408,10 @@ function encodeProtobufResponseBody() {
|
|
|
406
408
|
}
|
|
407
409
|
async function decodeProtobufBody(buf) {
|
|
408
410
|
const Type = loadProtobufDecoder();
|
|
409
|
-
const decoded = Type.decode(buf)
|
|
411
|
+
const decoded = Type.toObject(Type.decode(buf), {
|
|
412
|
+
longs: String,
|
|
413
|
+
enums: Number
|
|
414
|
+
});
|
|
410
415
|
const { reshapeGrpcRequest: reshapeGrpcRequest2 } = await Promise.resolve().then(() => (init_otel_grpc(), otel_grpc_exports));
|
|
411
416
|
return reshapeGrpcRequest2(decoded);
|
|
412
417
|
}
|
|
@@ -566,12 +571,12 @@ async function buildOtelReceiver(opts) {
|
|
|
566
571
|
};
|
|
567
572
|
return decorated;
|
|
568
573
|
}
|
|
569
|
-
var
|
|
574
|
+
var import_node_path39, import_node_url2, import_fastify2, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody;
|
|
570
575
|
var init_otel = __esm({
|
|
571
576
|
"src/otel.ts"() {
|
|
572
577
|
"use strict";
|
|
573
578
|
init_cjs_shims();
|
|
574
|
-
|
|
579
|
+
import_node_path39 = __toESM(require("path"), 1);
|
|
575
580
|
import_node_url2 = require("url");
|
|
576
581
|
import_fastify2 = __toESM(require("fastify"), 1);
|
|
577
582
|
import_protobufjs = __toESM(require("protobufjs"), 1);
|
|
@@ -587,14 +592,14 @@ var init_otel = __esm({
|
|
|
587
592
|
|
|
588
593
|
// src/neatd.ts
|
|
589
594
|
init_cjs_shims();
|
|
590
|
-
var
|
|
591
|
-
var
|
|
595
|
+
var import_node_fs26 = require("fs");
|
|
596
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
592
597
|
var import_node_module = require("module");
|
|
593
598
|
|
|
594
599
|
// src/daemon.ts
|
|
595
600
|
init_cjs_shims();
|
|
596
|
-
var
|
|
597
|
-
var
|
|
601
|
+
var import_node_fs25 = require("fs");
|
|
602
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
598
603
|
|
|
599
604
|
// src/graph.ts
|
|
600
605
|
init_cjs_shims();
|
|
@@ -1073,19 +1078,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
1073
1078
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
1074
1079
|
let best = { path: [start], edges: [] };
|
|
1075
1080
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
1076
|
-
function step(node,
|
|
1077
|
-
if (
|
|
1078
|
-
best = { path: [...
|
|
1081
|
+
function step(node, path44, edges) {
|
|
1082
|
+
if (path44.length > best.path.length) {
|
|
1083
|
+
best = { path: [...path44], edges: [...edges] };
|
|
1079
1084
|
}
|
|
1080
|
-
if (
|
|
1085
|
+
if (path44.length - 1 >= maxDepth) return;
|
|
1081
1086
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
1082
1087
|
for (const [srcId, edge] of incoming) {
|
|
1083
1088
|
if (visited.has(srcId)) continue;
|
|
1084
1089
|
visited.add(srcId);
|
|
1085
|
-
|
|
1090
|
+
path44.push(srcId);
|
|
1086
1091
|
edges.push(edge);
|
|
1087
|
-
step(srcId,
|
|
1088
|
-
|
|
1092
|
+
step(srcId, path44, edges);
|
|
1093
|
+
path44.pop();
|
|
1089
1094
|
edges.pop();
|
|
1090
1095
|
visited.delete(srcId);
|
|
1091
1096
|
}
|
|
@@ -2950,10 +2955,8 @@ async function addServiceAliases(graph, scanPath, services) {
|
|
|
2950
2955
|
await collectK8sAliases(graph, scanPath, byName);
|
|
2951
2956
|
}
|
|
2952
2957
|
|
|
2953
|
-
// src/extract/
|
|
2958
|
+
// src/extract/files.ts
|
|
2954
2959
|
init_cjs_shims();
|
|
2955
|
-
var import_node_path18 = __toESM(require("path"), 1);
|
|
2956
|
-
var import_types8 = require("@neat.is/types");
|
|
2957
2960
|
|
|
2958
2961
|
// src/extract/calls/shared.ts
|
|
2959
2962
|
init_cjs_shims();
|
|
@@ -3052,11 +3055,333 @@ function ensureFileNode(graph, serviceName, serviceNodeId, relPath) {
|
|
|
3052
3055
|
return { fileNodeId, nodesAdded, edgesAdded };
|
|
3053
3056
|
}
|
|
3054
3057
|
|
|
3058
|
+
// src/extract/files.ts
|
|
3059
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
3060
|
+
async function addFiles(graph, services) {
|
|
3061
|
+
let nodesAdded = 0;
|
|
3062
|
+
let edgesAdded = 0;
|
|
3063
|
+
for (const service of services) {
|
|
3064
|
+
const filePaths = await walkSourceFiles(service.dir);
|
|
3065
|
+
for (const filePath of filePaths) {
|
|
3066
|
+
const relPath = toPosix2(import_node_path11.default.relative(service.dir, filePath));
|
|
3067
|
+
const { nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
3068
|
+
graph,
|
|
3069
|
+
service.pkg.name,
|
|
3070
|
+
service.node.id,
|
|
3071
|
+
relPath
|
|
3072
|
+
);
|
|
3073
|
+
nodesAdded += n;
|
|
3074
|
+
edgesAdded += e;
|
|
3075
|
+
}
|
|
3076
|
+
}
|
|
3077
|
+
return { nodesAdded, edgesAdded };
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
// src/extract/imports.ts
|
|
3081
|
+
init_cjs_shims();
|
|
3082
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
3083
|
+
var import_node_fs11 = require("fs");
|
|
3084
|
+
var import_tree_sitter = __toESM(require("tree-sitter"), 1);
|
|
3085
|
+
var import_tree_sitter_javascript = __toESM(require("tree-sitter-javascript"), 1);
|
|
3086
|
+
var import_tree_sitter_python = __toESM(require("tree-sitter-python"), 1);
|
|
3087
|
+
var import_types8 = require("@neat.is/types");
|
|
3088
|
+
var PARSE_CHUNK = 16384;
|
|
3089
|
+
function parseSource(parser, source) {
|
|
3090
|
+
return parser.parse(
|
|
3091
|
+
(index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK)
|
|
3092
|
+
);
|
|
3093
|
+
}
|
|
3094
|
+
function makeJsParser() {
|
|
3095
|
+
const p = new import_tree_sitter.default();
|
|
3096
|
+
p.setLanguage(import_tree_sitter_javascript.default);
|
|
3097
|
+
return p;
|
|
3098
|
+
}
|
|
3099
|
+
function makePyParser() {
|
|
3100
|
+
const p = new import_tree_sitter.default();
|
|
3101
|
+
p.setLanguage(import_tree_sitter_python.default);
|
|
3102
|
+
return p;
|
|
3103
|
+
}
|
|
3104
|
+
function stringLiteralText(node) {
|
|
3105
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
3106
|
+
const child = node.child(i);
|
|
3107
|
+
if (child?.type === "string_fragment") return child.text;
|
|
3108
|
+
}
|
|
3109
|
+
const raw = node.text;
|
|
3110
|
+
if (raw.length >= 2) return raw.slice(1, -1);
|
|
3111
|
+
return raw.length === 0 ? null : "";
|
|
3112
|
+
}
|
|
3113
|
+
function clipSnippet(text) {
|
|
3114
|
+
const oneLine = text.split("\n")[0] ?? text;
|
|
3115
|
+
return oneLine.length > 120 ? oneLine.slice(0, 120) : oneLine;
|
|
3116
|
+
}
|
|
3117
|
+
function collectJsImports(node, out) {
|
|
3118
|
+
if (node.type === "import_statement") {
|
|
3119
|
+
const source = node.childForFieldName("source");
|
|
3120
|
+
if (source) {
|
|
3121
|
+
const specifier = stringLiteralText(source);
|
|
3122
|
+
if (specifier) {
|
|
3123
|
+
out.push({ specifier, line: node.startPosition.row + 1, snippet: clipSnippet(node.text) });
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
return;
|
|
3127
|
+
}
|
|
3128
|
+
if (node.type === "call_expression") {
|
|
3129
|
+
const fn = node.childForFieldName("function");
|
|
3130
|
+
if (fn?.type === "identifier" && fn.text === "require") {
|
|
3131
|
+
const args = node.childForFieldName("arguments");
|
|
3132
|
+
const firstArg = args?.namedChild(0);
|
|
3133
|
+
if (firstArg?.type === "string") {
|
|
3134
|
+
const specifier = stringLiteralText(firstArg);
|
|
3135
|
+
if (specifier) {
|
|
3136
|
+
out.push({ specifier, line: node.startPosition.row + 1, snippet: clipSnippet(node.text) });
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
3142
|
+
const child = node.namedChild(i);
|
|
3143
|
+
if (child) collectJsImports(child, out);
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
function collectPyImports(node, out) {
|
|
3147
|
+
if (node.type === "import_from_statement") {
|
|
3148
|
+
let level = 0;
|
|
3149
|
+
let modulePath = "";
|
|
3150
|
+
let pastFrom = false;
|
|
3151
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
3152
|
+
const child = node.child(i);
|
|
3153
|
+
if (!child) continue;
|
|
3154
|
+
if (!pastFrom) {
|
|
3155
|
+
if (child.type === "from") pastFrom = true;
|
|
3156
|
+
continue;
|
|
3157
|
+
}
|
|
3158
|
+
if (child.type === "import") break;
|
|
3159
|
+
if (child.type === "relative_import") {
|
|
3160
|
+
for (let j = 0; j < child.childCount; j++) {
|
|
3161
|
+
const rc = child.child(j);
|
|
3162
|
+
if (!rc) continue;
|
|
3163
|
+
if (rc.type === "import_prefix") {
|
|
3164
|
+
for (let k = 0; k < rc.childCount; k++) {
|
|
3165
|
+
if (rc.child(k)?.type === ".") level++;
|
|
3166
|
+
}
|
|
3167
|
+
} else if (rc.type === "dotted_name") modulePath = rc.text;
|
|
3168
|
+
}
|
|
3169
|
+
break;
|
|
3170
|
+
}
|
|
3171
|
+
if (child.type === "dotted_name") {
|
|
3172
|
+
modulePath = child.text;
|
|
3173
|
+
break;
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
if (level > 0 || modulePath) {
|
|
3177
|
+
out.push({ modulePath, level, line: node.startPosition.row + 1, snippet: clipSnippet(node.text) });
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
3181
|
+
const child = node.namedChild(i);
|
|
3182
|
+
if (child) collectPyImports(child, out);
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
async function fileExists(p) {
|
|
3186
|
+
try {
|
|
3187
|
+
await import_node_fs11.promises.access(p);
|
|
3188
|
+
return true;
|
|
3189
|
+
} catch {
|
|
3190
|
+
return false;
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
function isWithinServiceDir(candidate, serviceDir) {
|
|
3194
|
+
const rel = import_node_path12.default.relative(serviceDir, candidate);
|
|
3195
|
+
return rel !== "" && !rel.startsWith("..") && !import_node_path12.default.isAbsolute(rel);
|
|
3196
|
+
}
|
|
3197
|
+
var JS_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
3198
|
+
var JS_INDEX_FILES = JS_EXTENSIONS.map((ext) => `index${ext}`);
|
|
3199
|
+
async function firstExistingCandidate(base, serviceDir) {
|
|
3200
|
+
for (const ext of JS_EXTENSIONS) {
|
|
3201
|
+
const candidate = base + ext;
|
|
3202
|
+
if (isWithinServiceDir(candidate, serviceDir) && await fileExists(candidate)) {
|
|
3203
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, candidate));
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
for (const indexFile of JS_INDEX_FILES) {
|
|
3207
|
+
const candidate = import_node_path12.default.join(base, indexFile);
|
|
3208
|
+
if (isWithinServiceDir(candidate, serviceDir) && await fileExists(candidate)) {
|
|
3209
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, candidate));
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
return null;
|
|
3213
|
+
}
|
|
3214
|
+
async function loadTsPathConfig(serviceDir) {
|
|
3215
|
+
const tsconfigPath = import_node_path12.default.join(serviceDir, "tsconfig.json");
|
|
3216
|
+
let raw;
|
|
3217
|
+
try {
|
|
3218
|
+
raw = await import_node_fs11.promises.readFile(tsconfigPath, "utf8");
|
|
3219
|
+
} catch {
|
|
3220
|
+
return null;
|
|
3221
|
+
}
|
|
3222
|
+
try {
|
|
3223
|
+
const parsed = JSON.parse(raw);
|
|
3224
|
+
const paths = parsed.compilerOptions?.paths;
|
|
3225
|
+
if (!paths || Object.keys(paths).length === 0) return null;
|
|
3226
|
+
const baseUrl = parsed.compilerOptions?.baseUrl;
|
|
3227
|
+
return { paths, baseDir: baseUrl ? import_node_path12.default.resolve(serviceDir, baseUrl) : serviceDir };
|
|
3228
|
+
} catch (err) {
|
|
3229
|
+
recordExtractionError("import alias resolution", tsconfigPath, err);
|
|
3230
|
+
return null;
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
async function resolveTsAlias(specifier, config, serviceDir) {
|
|
3234
|
+
for (const [pattern, targets] of Object.entries(config.paths)) {
|
|
3235
|
+
let suffix = null;
|
|
3236
|
+
if (pattern === specifier) {
|
|
3237
|
+
suffix = "";
|
|
3238
|
+
} else if (pattern.endsWith("/*")) {
|
|
3239
|
+
const prefix = pattern.slice(0, -1);
|
|
3240
|
+
if (specifier.startsWith(prefix)) suffix = specifier.slice(prefix.length);
|
|
3241
|
+
}
|
|
3242
|
+
if (suffix === null) continue;
|
|
3243
|
+
for (const target of targets) {
|
|
3244
|
+
const targetBase = target.endsWith("/*") ? target.slice(0, -2) : target.replace(/\*$/, "");
|
|
3245
|
+
const resolvedBase = import_node_path12.default.resolve(config.baseDir, targetBase, suffix);
|
|
3246
|
+
const hit = await firstExistingCandidate(resolvedBase, serviceDir);
|
|
3247
|
+
if (hit) return hit;
|
|
3248
|
+
if (isWithinServiceDir(resolvedBase, serviceDir) && await fileExists(resolvedBase)) {
|
|
3249
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, resolvedBase));
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
return null;
|
|
3254
|
+
}
|
|
3255
|
+
async function resolveJsImport(specifier, importerDir, serviceDir, tsPaths) {
|
|
3256
|
+
if (!specifier) return null;
|
|
3257
|
+
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
3258
|
+
const base = import_node_path12.default.resolve(importerDir, specifier);
|
|
3259
|
+
const ext = import_node_path12.default.extname(specifier);
|
|
3260
|
+
if (ext) {
|
|
3261
|
+
if (ext === ".js" || ext === ".jsx") {
|
|
3262
|
+
const tsExt = ext === ".jsx" ? ".tsx" : ".ts";
|
|
3263
|
+
const tsSibling = base.slice(0, -ext.length) + tsExt;
|
|
3264
|
+
if (isWithinServiceDir(tsSibling, serviceDir) && await fileExists(tsSibling)) {
|
|
3265
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, tsSibling));
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
if (isWithinServiceDir(base, serviceDir) && await fileExists(base)) {
|
|
3269
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, base));
|
|
3270
|
+
}
|
|
3271
|
+
return null;
|
|
3272
|
+
}
|
|
3273
|
+
return firstExistingCandidate(base, serviceDir);
|
|
3274
|
+
}
|
|
3275
|
+
if (tsPaths) return resolveTsAlias(specifier, tsPaths, serviceDir);
|
|
3276
|
+
return null;
|
|
3277
|
+
}
|
|
3278
|
+
async function resolvePyImport(imp, importerPath, serviceDir) {
|
|
3279
|
+
if (!imp.modulePath) return null;
|
|
3280
|
+
const relPath = imp.modulePath.split(".").join("/");
|
|
3281
|
+
let baseDir;
|
|
3282
|
+
if (imp.level > 0) {
|
|
3283
|
+
baseDir = import_node_path12.default.dirname(importerPath);
|
|
3284
|
+
for (let i = 1; i < imp.level; i++) baseDir = import_node_path12.default.dirname(baseDir);
|
|
3285
|
+
} else {
|
|
3286
|
+
baseDir = serviceDir;
|
|
3287
|
+
}
|
|
3288
|
+
const candidates = [import_node_path12.default.join(baseDir, `${relPath}.py`), import_node_path12.default.join(baseDir, relPath, "__init__.py")];
|
|
3289
|
+
for (const candidate of candidates) {
|
|
3290
|
+
if (isWithinServiceDir(candidate, serviceDir) && await fileExists(candidate)) {
|
|
3291
|
+
return toPosix2(import_node_path12.default.relative(serviceDir, candidate));
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
3294
|
+
return null;
|
|
3295
|
+
}
|
|
3296
|
+
function emitImportEdge(graph, serviceName, importerFileId, importerRelPath, importeeRelPath, line, snippet2) {
|
|
3297
|
+
const importeeFileId = (0, import_types8.fileId)(serviceName, importeeRelPath);
|
|
3298
|
+
if (!graph.hasNode(importeeFileId)) return 0;
|
|
3299
|
+
const edgeId = (0, import_types8.extractedEdgeId)(importerFileId, importeeFileId, import_types8.EdgeType.IMPORTS);
|
|
3300
|
+
if (graph.hasEdge(edgeId)) return 0;
|
|
3301
|
+
const edge = {
|
|
3302
|
+
id: edgeId,
|
|
3303
|
+
source: importerFileId,
|
|
3304
|
+
target: importeeFileId,
|
|
3305
|
+
type: import_types8.EdgeType.IMPORTS,
|
|
3306
|
+
provenance: import_types8.Provenance.EXTRACTED,
|
|
3307
|
+
confidence: (0, import_types8.confidenceForExtracted)("structural"),
|
|
3308
|
+
evidence: { file: importerRelPath, line, snippet: snippet2 }
|
|
3309
|
+
};
|
|
3310
|
+
graph.addEdgeWithKey(edgeId, importerFileId, importeeFileId, edge);
|
|
3311
|
+
return 1;
|
|
3312
|
+
}
|
|
3313
|
+
async function addImports(graph, services) {
|
|
3314
|
+
const jsParser = makeJsParser();
|
|
3315
|
+
const pyParser = makePyParser();
|
|
3316
|
+
let edgesAdded = 0;
|
|
3317
|
+
for (const service of services) {
|
|
3318
|
+
const tsPaths = await loadTsPathConfig(service.dir);
|
|
3319
|
+
const files = await loadSourceFiles(service.dir);
|
|
3320
|
+
for (const file of files) {
|
|
3321
|
+
if (isTestPath(file.path)) continue;
|
|
3322
|
+
const relFile = toPosix2(import_node_path12.default.relative(service.dir, file.path));
|
|
3323
|
+
const importerFileId = (0, import_types8.fileId)(service.pkg.name, relFile);
|
|
3324
|
+
const isPython = import_node_path12.default.extname(file.path) === ".py";
|
|
3325
|
+
if (isPython) {
|
|
3326
|
+
let pyImports = [];
|
|
3327
|
+
try {
|
|
3328
|
+
const tree = parseSource(pyParser, file.content);
|
|
3329
|
+
collectPyImports(tree.rootNode, pyImports);
|
|
3330
|
+
} catch (err) {
|
|
3331
|
+
recordExtractionError("import extraction", file.path, err);
|
|
3332
|
+
continue;
|
|
3333
|
+
}
|
|
3334
|
+
for (const imp of pyImports) {
|
|
3335
|
+
const resolved = await resolvePyImport(imp, file.path, service.dir);
|
|
3336
|
+
if (!resolved) continue;
|
|
3337
|
+
edgesAdded += emitImportEdge(
|
|
3338
|
+
graph,
|
|
3339
|
+
service.pkg.name,
|
|
3340
|
+
importerFileId,
|
|
3341
|
+
relFile,
|
|
3342
|
+
resolved,
|
|
3343
|
+
imp.line,
|
|
3344
|
+
imp.snippet
|
|
3345
|
+
);
|
|
3346
|
+
}
|
|
3347
|
+
continue;
|
|
3348
|
+
}
|
|
3349
|
+
let jsImports = [];
|
|
3350
|
+
try {
|
|
3351
|
+
const tree = parseSource(jsParser, file.content);
|
|
3352
|
+
collectJsImports(tree.rootNode, jsImports);
|
|
3353
|
+
} catch (err) {
|
|
3354
|
+
recordExtractionError("import extraction", file.path, err);
|
|
3355
|
+
continue;
|
|
3356
|
+
}
|
|
3357
|
+
for (const imp of jsImports) {
|
|
3358
|
+
const resolved = await resolveJsImport(imp.specifier, import_node_path12.default.dirname(file.path), service.dir, tsPaths);
|
|
3359
|
+
if (!resolved) continue;
|
|
3360
|
+
edgesAdded += emitImportEdge(
|
|
3361
|
+
graph,
|
|
3362
|
+
service.pkg.name,
|
|
3363
|
+
importerFileId,
|
|
3364
|
+
relFile,
|
|
3365
|
+
resolved,
|
|
3366
|
+
imp.line,
|
|
3367
|
+
imp.snippet
|
|
3368
|
+
);
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
return { nodesAdded: 0, edgesAdded };
|
|
3373
|
+
}
|
|
3374
|
+
|
|
3375
|
+
// src/extract/databases/index.ts
|
|
3376
|
+
init_cjs_shims();
|
|
3377
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
3378
|
+
var import_types9 = require("@neat.is/types");
|
|
3379
|
+
|
|
3055
3380
|
// src/extract/databases/db-config-yaml.ts
|
|
3056
3381
|
init_cjs_shims();
|
|
3057
|
-
var
|
|
3382
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
3058
3383
|
async function parse(serviceDir) {
|
|
3059
|
-
const yamlPath =
|
|
3384
|
+
const yamlPath = import_node_path13.default.join(serviceDir, "db-config.yaml");
|
|
3060
3385
|
if (!await exists(yamlPath)) return [];
|
|
3061
3386
|
const raw = await readYaml(yamlPath);
|
|
3062
3387
|
return [
|
|
@@ -3074,13 +3399,13 @@ var dbConfigYamlParser = { name: "db-config.yaml", parse };
|
|
|
3074
3399
|
|
|
3075
3400
|
// src/extract/databases/dotenv.ts
|
|
3076
3401
|
init_cjs_shims();
|
|
3077
|
-
var
|
|
3078
|
-
var
|
|
3402
|
+
var import_node_fs13 = require("fs");
|
|
3403
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
3079
3404
|
|
|
3080
3405
|
// src/extract/databases/shared.ts
|
|
3081
3406
|
init_cjs_shims();
|
|
3082
|
-
var
|
|
3083
|
-
var
|
|
3407
|
+
var import_node_fs12 = require("fs");
|
|
3408
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
3084
3409
|
function schemeToEngine(scheme) {
|
|
3085
3410
|
const s = scheme.toLowerCase().split("+")[0];
|
|
3086
3411
|
switch (s) {
|
|
@@ -3119,14 +3444,14 @@ function parseConnectionString(url) {
|
|
|
3119
3444
|
}
|
|
3120
3445
|
async function readIfExists(filePath) {
|
|
3121
3446
|
try {
|
|
3122
|
-
return await
|
|
3447
|
+
return await import_node_fs12.promises.readFile(filePath, "utf8");
|
|
3123
3448
|
} catch {
|
|
3124
3449
|
return null;
|
|
3125
3450
|
}
|
|
3126
3451
|
}
|
|
3127
3452
|
async function findFirst(serviceDir, candidates) {
|
|
3128
3453
|
for (const rel of candidates) {
|
|
3129
|
-
const abs =
|
|
3454
|
+
const abs = import_node_path14.default.join(serviceDir, rel);
|
|
3130
3455
|
const content = await readIfExists(abs);
|
|
3131
3456
|
if (content !== null) return abs;
|
|
3132
3457
|
}
|
|
@@ -3177,15 +3502,15 @@ function parseDotenvLine(line) {
|
|
|
3177
3502
|
return { key, value };
|
|
3178
3503
|
}
|
|
3179
3504
|
async function parse2(serviceDir) {
|
|
3180
|
-
const entries = await
|
|
3505
|
+
const entries = await import_node_fs13.promises.readdir(serviceDir, { withFileTypes: true }).catch(() => []);
|
|
3181
3506
|
const configs = [];
|
|
3182
3507
|
const seen = /* @__PURE__ */ new Set();
|
|
3183
3508
|
for (const entry2 of entries) {
|
|
3184
3509
|
if (!entry2.isFile()) continue;
|
|
3185
3510
|
const match = isConfigFile(entry2.name);
|
|
3186
3511
|
if (!match.match || match.fileType !== "env") continue;
|
|
3187
|
-
const filePath =
|
|
3188
|
-
const content = await
|
|
3512
|
+
const filePath = import_node_path15.default.join(serviceDir, entry2.name);
|
|
3513
|
+
const content = await import_node_fs13.promises.readFile(filePath, "utf8");
|
|
3189
3514
|
for (const line of content.split("\n")) {
|
|
3190
3515
|
const parsed = parseDotenvLine(line);
|
|
3191
3516
|
if (!parsed) continue;
|
|
@@ -3204,9 +3529,9 @@ var dotenvParser = { name: ".env", parse: parse2 };
|
|
|
3204
3529
|
|
|
3205
3530
|
// src/extract/databases/prisma.ts
|
|
3206
3531
|
init_cjs_shims();
|
|
3207
|
-
var
|
|
3532
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
3208
3533
|
async function parse3(serviceDir) {
|
|
3209
|
-
const schemaPath =
|
|
3534
|
+
const schemaPath = import_node_path16.default.join(serviceDir, "prisma", "schema.prisma");
|
|
3210
3535
|
const content = await readIfExists(schemaPath);
|
|
3211
3536
|
if (!content) return [];
|
|
3212
3537
|
const block = content.match(/datasource\s+\w+\s*\{([^}]*)\}/s);
|
|
@@ -3338,10 +3663,10 @@ var knexParser = { name: "knex", parse: parse5 };
|
|
|
3338
3663
|
|
|
3339
3664
|
// src/extract/databases/ormconfig.ts
|
|
3340
3665
|
init_cjs_shims();
|
|
3341
|
-
var
|
|
3666
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
3342
3667
|
async function parse6(serviceDir) {
|
|
3343
3668
|
for (const candidate of ["ormconfig.json", "ormconfig.yaml", "ormconfig.yml"]) {
|
|
3344
|
-
const abs =
|
|
3669
|
+
const abs = import_node_path17.default.join(serviceDir, candidate);
|
|
3345
3670
|
if (!await exists(abs)) continue;
|
|
3346
3671
|
const raw = candidate.endsWith(".json") ? await readJson(abs) : await readYaml(abs);
|
|
3347
3672
|
const entries = Array.isArray(raw) ? raw : [raw];
|
|
@@ -3401,9 +3726,9 @@ var typeormParser = { name: "typeorm", parse: parse7 };
|
|
|
3401
3726
|
|
|
3402
3727
|
// src/extract/databases/sequelize.ts
|
|
3403
3728
|
init_cjs_shims();
|
|
3404
|
-
var
|
|
3729
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
3405
3730
|
async function parse8(serviceDir) {
|
|
3406
|
-
const configPath =
|
|
3731
|
+
const configPath = import_node_path18.default.join(serviceDir, "config", "config.json");
|
|
3407
3732
|
if (!await exists(configPath)) return [];
|
|
3408
3733
|
const raw = await readJson(configPath);
|
|
3409
3734
|
const out = [];
|
|
@@ -3430,7 +3755,7 @@ var sequelizeParser = { name: "sequelize", parse: parse8 };
|
|
|
3430
3755
|
|
|
3431
3756
|
// src/extract/databases/docker-compose.ts
|
|
3432
3757
|
init_cjs_shims();
|
|
3433
|
-
var
|
|
3758
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
3434
3759
|
function portFromService(svc) {
|
|
3435
3760
|
for (const raw of svc.ports ?? []) {
|
|
3436
3761
|
const str = String(raw);
|
|
@@ -3457,7 +3782,7 @@ function databaseFromEnv(svc) {
|
|
|
3457
3782
|
}
|
|
3458
3783
|
async function parse9(serviceDir) {
|
|
3459
3784
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
3460
|
-
const abs =
|
|
3785
|
+
const abs = import_node_path19.default.join(serviceDir, name);
|
|
3461
3786
|
if (!await exists(abs)) continue;
|
|
3462
3787
|
const raw = await readYaml(abs);
|
|
3463
3788
|
if (!raw?.services) return [];
|
|
@@ -3498,8 +3823,8 @@ function compatibleDriversFor(engine) {
|
|
|
3498
3823
|
}
|
|
3499
3824
|
function toDatabaseNode(config) {
|
|
3500
3825
|
return {
|
|
3501
|
-
id: (0,
|
|
3502
|
-
type:
|
|
3826
|
+
id: (0, import_types9.databaseId)(config.host),
|
|
3827
|
+
type: import_types9.NodeType.DatabaseNode,
|
|
3503
3828
|
name: config.database || config.host,
|
|
3504
3829
|
engine: config.engine,
|
|
3505
3830
|
engineVersion: config.engineVersion,
|
|
@@ -3629,7 +3954,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
3629
3954
|
discoveredVia: mergedDiscoveredVia
|
|
3630
3955
|
});
|
|
3631
3956
|
}
|
|
3632
|
-
const relConfigFile = toPosix2(
|
|
3957
|
+
const relConfigFile = toPosix2(import_node_path20.default.relative(service.dir, config.sourceFile));
|
|
3633
3958
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
3634
3959
|
graph,
|
|
3635
3960
|
service.pkg.name,
|
|
@@ -3638,14 +3963,14 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
3638
3963
|
);
|
|
3639
3964
|
nodesAdded += fn;
|
|
3640
3965
|
edgesAdded += fe;
|
|
3641
|
-
const evidenceFile = toPosix2(
|
|
3966
|
+
const evidenceFile = toPosix2(import_node_path20.default.relative(scanPath, config.sourceFile));
|
|
3642
3967
|
const edge = {
|
|
3643
|
-
id: (0, import_types4.extractedEdgeId)(fileNodeId, dbNode.id,
|
|
3968
|
+
id: (0, import_types4.extractedEdgeId)(fileNodeId, dbNode.id, import_types9.EdgeType.CONNECTS_TO),
|
|
3644
3969
|
source: fileNodeId,
|
|
3645
3970
|
target: dbNode.id,
|
|
3646
|
-
type:
|
|
3647
|
-
provenance:
|
|
3648
|
-
confidence: (0,
|
|
3971
|
+
type: import_types9.EdgeType.CONNECTS_TO,
|
|
3972
|
+
provenance: import_types9.Provenance.EXTRACTED,
|
|
3973
|
+
confidence: (0, import_types9.confidenceForExtracted)("structural"),
|
|
3649
3974
|
evidence: { file: evidenceFile }
|
|
3650
3975
|
};
|
|
3651
3976
|
if (!graph.hasEdge(edge.id)) {
|
|
@@ -3672,15 +3997,15 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
|
|
|
3672
3997
|
|
|
3673
3998
|
// src/extract/configs.ts
|
|
3674
3999
|
init_cjs_shims();
|
|
3675
|
-
var
|
|
3676
|
-
var
|
|
3677
|
-
var
|
|
4000
|
+
var import_node_fs14 = require("fs");
|
|
4001
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
4002
|
+
var import_types10 = require("@neat.is/types");
|
|
3678
4003
|
async function walkConfigFiles(dir) {
|
|
3679
4004
|
const out = [];
|
|
3680
4005
|
async function walk(current) {
|
|
3681
|
-
const entries = await
|
|
4006
|
+
const entries = await import_node_fs14.promises.readdir(current, { withFileTypes: true });
|
|
3682
4007
|
for (const entry2 of entries) {
|
|
3683
|
-
const full =
|
|
4008
|
+
const full = import_node_path21.default.join(current, entry2.name);
|
|
3684
4009
|
if (entry2.isDirectory()) {
|
|
3685
4010
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
3686
4011
|
if (await isPythonVenvDir(full)) continue;
|
|
@@ -3699,19 +4024,19 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
3699
4024
|
for (const service of services) {
|
|
3700
4025
|
const configFiles = await walkConfigFiles(service.dir);
|
|
3701
4026
|
for (const file of configFiles) {
|
|
3702
|
-
const relPath =
|
|
4027
|
+
const relPath = import_node_path21.default.relative(scanPath, file);
|
|
3703
4028
|
const node = {
|
|
3704
|
-
id: (0,
|
|
3705
|
-
type:
|
|
3706
|
-
name:
|
|
4029
|
+
id: (0, import_types10.configId)(relPath),
|
|
4030
|
+
type: import_types10.NodeType.ConfigNode,
|
|
4031
|
+
name: import_node_path21.default.basename(file),
|
|
3707
4032
|
path: relPath,
|
|
3708
|
-
fileType: isConfigFile(
|
|
4033
|
+
fileType: isConfigFile(import_node_path21.default.basename(file)).fileType
|
|
3709
4034
|
};
|
|
3710
4035
|
if (!graph.hasNode(node.id)) {
|
|
3711
4036
|
graph.addNode(node.id, node);
|
|
3712
4037
|
nodesAdded++;
|
|
3713
4038
|
}
|
|
3714
|
-
const relToService = toPosix2(
|
|
4039
|
+
const relToService = toPosix2(import_node_path21.default.relative(service.dir, file));
|
|
3715
4040
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
3716
4041
|
graph,
|
|
3717
4042
|
service.pkg.name,
|
|
@@ -3721,13 +4046,13 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
3721
4046
|
nodesAdded += fn;
|
|
3722
4047
|
edgesAdded += fe;
|
|
3723
4048
|
const edge = {
|
|
3724
|
-
id: (0, import_types4.extractedEdgeId)(fileNodeId, node.id,
|
|
4049
|
+
id: (0, import_types4.extractedEdgeId)(fileNodeId, node.id, import_types10.EdgeType.CONFIGURED_BY),
|
|
3725
4050
|
source: fileNodeId,
|
|
3726
4051
|
target: node.id,
|
|
3727
|
-
type:
|
|
3728
|
-
provenance:
|
|
3729
|
-
confidence: (0,
|
|
3730
|
-
evidence: { file: relPath.split(
|
|
4052
|
+
type: import_types10.EdgeType.CONFIGURED_BY,
|
|
4053
|
+
provenance: import_types10.Provenance.EXTRACTED,
|
|
4054
|
+
confidence: (0, import_types10.confidenceForExtracted)("structural"),
|
|
4055
|
+
evidence: { file: relPath.split(import_node_path21.default.sep).join("/") }
|
|
3731
4056
|
};
|
|
3732
4057
|
if (!graph.hasEdge(edge.id)) {
|
|
3733
4058
|
graph.addEdgeWithKey(edge.id, edge.source, edge.target, edge);
|
|
@@ -3740,15 +4065,15 @@ async function addConfigNodes(graph, services, scanPath) {
|
|
|
3740
4065
|
|
|
3741
4066
|
// src/extract/calls/index.ts
|
|
3742
4067
|
init_cjs_shims();
|
|
3743
|
-
var
|
|
4068
|
+
var import_types16 = require("@neat.is/types");
|
|
3744
4069
|
|
|
3745
4070
|
// src/extract/calls/http.ts
|
|
3746
4071
|
init_cjs_shims();
|
|
3747
|
-
var
|
|
3748
|
-
var
|
|
3749
|
-
var
|
|
3750
|
-
var
|
|
3751
|
-
var
|
|
4072
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
4073
|
+
var import_tree_sitter2 = __toESM(require("tree-sitter"), 1);
|
|
4074
|
+
var import_tree_sitter_javascript2 = __toESM(require("tree-sitter-javascript"), 1);
|
|
4075
|
+
var import_tree_sitter_python2 = __toESM(require("tree-sitter-python"), 1);
|
|
4076
|
+
var import_types11 = require("@neat.is/types");
|
|
3752
4077
|
var STRING_LITERAL_NODE_TYPES = /* @__PURE__ */ new Set(["string_fragment", "string_content"]);
|
|
3753
4078
|
var JSX_EXTERNAL_LINK_TAGS = /* @__PURE__ */ new Set(["a", "Link", "NavLink", "ExternalLink", "Anchor"]);
|
|
3754
4079
|
function isInsideJsxExternalLink(node) {
|
|
@@ -3776,14 +4101,14 @@ function collectStringLiterals(node, out) {
|
|
|
3776
4101
|
if (child) collectStringLiterals(child, out);
|
|
3777
4102
|
}
|
|
3778
4103
|
}
|
|
3779
|
-
var
|
|
3780
|
-
function
|
|
4104
|
+
var PARSE_CHUNK2 = 16384;
|
|
4105
|
+
function parseSource2(parser, source) {
|
|
3781
4106
|
return parser.parse(
|
|
3782
|
-
(index) => index >= source.length ? "" : source.slice(index, index +
|
|
4107
|
+
(index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK2)
|
|
3783
4108
|
);
|
|
3784
4109
|
}
|
|
3785
4110
|
function callsFromSource(source, parser, knownHosts) {
|
|
3786
|
-
const tree =
|
|
4111
|
+
const tree = parseSource2(parser, source);
|
|
3787
4112
|
const literals = [];
|
|
3788
4113
|
collectStringLiterals(tree.rootNode, literals);
|
|
3789
4114
|
const out = [];
|
|
@@ -3797,25 +4122,25 @@ function callsFromSource(source, parser, knownHosts) {
|
|
|
3797
4122
|
}
|
|
3798
4123
|
return out;
|
|
3799
4124
|
}
|
|
3800
|
-
function
|
|
3801
|
-
const p = new
|
|
3802
|
-
p.setLanguage(
|
|
4125
|
+
function makeJsParser2() {
|
|
4126
|
+
const p = new import_tree_sitter2.default();
|
|
4127
|
+
p.setLanguage(import_tree_sitter_javascript2.default);
|
|
3803
4128
|
return p;
|
|
3804
4129
|
}
|
|
3805
|
-
function
|
|
3806
|
-
const p = new
|
|
3807
|
-
p.setLanguage(
|
|
4130
|
+
function makePyParser2() {
|
|
4131
|
+
const p = new import_tree_sitter2.default();
|
|
4132
|
+
p.setLanguage(import_tree_sitter_python2.default);
|
|
3808
4133
|
return p;
|
|
3809
4134
|
}
|
|
3810
4135
|
async function addHttpCallEdges(graph, services) {
|
|
3811
|
-
const jsParser =
|
|
3812
|
-
const pyParser =
|
|
4136
|
+
const jsParser = makeJsParser2();
|
|
4137
|
+
const pyParser = makePyParser2();
|
|
3813
4138
|
const knownHosts = /* @__PURE__ */ new Set();
|
|
3814
4139
|
const hostToNodeId = /* @__PURE__ */ new Map();
|
|
3815
4140
|
for (const service of services) {
|
|
3816
|
-
knownHosts.add(
|
|
4141
|
+
knownHosts.add(import_node_path22.default.basename(service.dir));
|
|
3817
4142
|
knownHosts.add(service.pkg.name);
|
|
3818
|
-
hostToNodeId.set(
|
|
4143
|
+
hostToNodeId.set(import_node_path22.default.basename(service.dir), service.node.id);
|
|
3819
4144
|
hostToNodeId.set(service.pkg.name, service.node.id);
|
|
3820
4145
|
}
|
|
3821
4146
|
let nodesAdded = 0;
|
|
@@ -3825,7 +4150,7 @@ async function addHttpCallEdges(graph, services) {
|
|
|
3825
4150
|
const seen = /* @__PURE__ */ new Set();
|
|
3826
4151
|
for (const file of files) {
|
|
3827
4152
|
if (isTestPath(file.path)) continue;
|
|
3828
|
-
const parser =
|
|
4153
|
+
const parser = import_node_path22.default.extname(file.path) === ".py" ? pyParser : jsParser;
|
|
3829
4154
|
let sites;
|
|
3830
4155
|
try {
|
|
3831
4156
|
sites = callsFromSource(file.content, parser, knownHosts);
|
|
@@ -3834,14 +4159,14 @@ async function addHttpCallEdges(graph, services) {
|
|
|
3834
4159
|
continue;
|
|
3835
4160
|
}
|
|
3836
4161
|
if (sites.length === 0) continue;
|
|
3837
|
-
const relFile = toPosix2(
|
|
4162
|
+
const relFile = toPosix2(import_node_path22.default.relative(service.dir, file.path));
|
|
3838
4163
|
for (const site of sites) {
|
|
3839
4164
|
const targetId = hostToNodeId.get(site.host);
|
|
3840
4165
|
if (!targetId || targetId === service.node.id) continue;
|
|
3841
4166
|
const dedupKey = `${relFile}|${targetId}`;
|
|
3842
4167
|
if (seen.has(dedupKey)) continue;
|
|
3843
4168
|
seen.add(dedupKey);
|
|
3844
|
-
const confidence = (0,
|
|
4169
|
+
const confidence = (0, import_types11.confidenceForExtracted)("hostname-shape-match");
|
|
3845
4170
|
const ev = {
|
|
3846
4171
|
file: relFile,
|
|
3847
4172
|
line: site.line,
|
|
@@ -3855,25 +4180,25 @@ async function addHttpCallEdges(graph, services) {
|
|
|
3855
4180
|
);
|
|
3856
4181
|
nodesAdded += n;
|
|
3857
4182
|
edgesAdded += e;
|
|
3858
|
-
if (!(0,
|
|
4183
|
+
if (!(0, import_types11.passesExtractedFloor)(confidence)) {
|
|
3859
4184
|
noteExtractedDropped({
|
|
3860
4185
|
source: fileNodeId,
|
|
3861
4186
|
target: targetId,
|
|
3862
|
-
type:
|
|
4187
|
+
type: import_types11.EdgeType.CALLS,
|
|
3863
4188
|
confidence,
|
|
3864
4189
|
confidenceKind: "hostname-shape-match",
|
|
3865
4190
|
evidence: ev
|
|
3866
4191
|
});
|
|
3867
4192
|
continue;
|
|
3868
4193
|
}
|
|
3869
|
-
const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, targetId,
|
|
4194
|
+
const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, targetId, import_types11.EdgeType.CALLS);
|
|
3870
4195
|
if (!graph.hasEdge(edgeId)) {
|
|
3871
4196
|
const edge = {
|
|
3872
4197
|
id: edgeId,
|
|
3873
4198
|
source: fileNodeId,
|
|
3874
4199
|
target: targetId,
|
|
3875
|
-
type:
|
|
3876
|
-
provenance:
|
|
4200
|
+
type: import_types11.EdgeType.CALLS,
|
|
4201
|
+
provenance: import_types11.Provenance.EXTRACTED,
|
|
3877
4202
|
confidence,
|
|
3878
4203
|
evidence: ev
|
|
3879
4204
|
};
|
|
@@ -3888,8 +4213,8 @@ async function addHttpCallEdges(graph, services) {
|
|
|
3888
4213
|
|
|
3889
4214
|
// src/extract/calls/kafka.ts
|
|
3890
4215
|
init_cjs_shims();
|
|
3891
|
-
var
|
|
3892
|
-
var
|
|
4216
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
4217
|
+
var import_types12 = require("@neat.is/types");
|
|
3893
4218
|
var PRODUCER_TOPIC_RE = /(?:producer|kafkaProducer)[\s\S]{0,40}?\.send\s*\(\s*\{[\s\S]{0,200}?topic\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
3894
4219
|
var CONSUMER_TOPIC_RE = /(?:consumer|kafkaConsumer)[\s\S]{0,40}?\.(?:subscribe|run)\s*\(\s*\{[\s\S]{0,200}?topic[s]?\s*:\s*(?:\[\s*)?['"`]([^'"`]+)['"`]/g;
|
|
3895
4220
|
function findAll(re, text) {
|
|
@@ -3910,7 +4235,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
3910
4235
|
seen.add(key);
|
|
3911
4236
|
const line = lineOf(file.content, topic);
|
|
3912
4237
|
out.push({
|
|
3913
|
-
infraId: (0,
|
|
4238
|
+
infraId: (0, import_types12.infraId)("kafka-topic", topic),
|
|
3914
4239
|
name: topic,
|
|
3915
4240
|
kind: "kafka-topic",
|
|
3916
4241
|
edgeType,
|
|
@@ -3919,7 +4244,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
3919
4244
|
// tier (ADR-066).
|
|
3920
4245
|
confidenceKind: "verified-call-site",
|
|
3921
4246
|
evidence: {
|
|
3922
|
-
file:
|
|
4247
|
+
file: import_node_path23.default.relative(serviceDir, file.path),
|
|
3923
4248
|
line,
|
|
3924
4249
|
snippet: snippet(file.content, line)
|
|
3925
4250
|
}
|
|
@@ -3932,8 +4257,8 @@ function kafkaEndpointsFromFile(file, serviceDir) {
|
|
|
3932
4257
|
|
|
3933
4258
|
// src/extract/calls/redis.ts
|
|
3934
4259
|
init_cjs_shims();
|
|
3935
|
-
var
|
|
3936
|
-
var
|
|
4260
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
4261
|
+
var import_types13 = require("@neat.is/types");
|
|
3937
4262
|
var REDIS_URL_RE = /redis(?:s)?:\/\/(?:[^@'"`\s]+@)?([^:/'"`\s]+)(?::(\d+))?/g;
|
|
3938
4263
|
function redisEndpointsFromFile(file, serviceDir) {
|
|
3939
4264
|
const out = [];
|
|
@@ -3946,7 +4271,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
3946
4271
|
seen.add(host);
|
|
3947
4272
|
const line = lineOf(file.content, host);
|
|
3948
4273
|
out.push({
|
|
3949
|
-
infraId: (0,
|
|
4274
|
+
infraId: (0, import_types13.infraId)("redis", host),
|
|
3950
4275
|
name: host,
|
|
3951
4276
|
kind: "redis",
|
|
3952
4277
|
edgeType: "CALLS",
|
|
@@ -3955,7 +4280,7 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
3955
4280
|
// support tier (ADR-066).
|
|
3956
4281
|
confidenceKind: "url-with-structural-support",
|
|
3957
4282
|
evidence: {
|
|
3958
|
-
file:
|
|
4283
|
+
file: import_node_path24.default.relative(serviceDir, file.path),
|
|
3959
4284
|
line,
|
|
3960
4285
|
snippet: snippet(file.content, line)
|
|
3961
4286
|
}
|
|
@@ -3966,8 +4291,8 @@ function redisEndpointsFromFile(file, serviceDir) {
|
|
|
3966
4291
|
|
|
3967
4292
|
// src/extract/calls/aws.ts
|
|
3968
4293
|
init_cjs_shims();
|
|
3969
|
-
var
|
|
3970
|
-
var
|
|
4294
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
4295
|
+
var import_types14 = require("@neat.is/types");
|
|
3971
4296
|
var S3_BUCKET_RE = /Bucket\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
3972
4297
|
var DYNAMO_TABLE_RE = /TableName\s*:\s*['"`]([^'"`]+)['"`]/g;
|
|
3973
4298
|
function hasMarker(text, markers) {
|
|
@@ -3991,7 +4316,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
3991
4316
|
seen.add(key);
|
|
3992
4317
|
const line = lineOf(file.content, name);
|
|
3993
4318
|
out.push({
|
|
3994
|
-
infraId: (0,
|
|
4319
|
+
infraId: (0, import_types14.infraId)(kind, name),
|
|
3995
4320
|
name,
|
|
3996
4321
|
kind,
|
|
3997
4322
|
edgeType: "CALLS",
|
|
@@ -4000,7 +4325,7 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
4000
4325
|
// (ADR-066).
|
|
4001
4326
|
confidenceKind: "verified-call-site",
|
|
4002
4327
|
evidence: {
|
|
4003
|
-
file:
|
|
4328
|
+
file: import_node_path25.default.relative(serviceDir, file.path),
|
|
4004
4329
|
line,
|
|
4005
4330
|
snippet: snippet(file.content, line)
|
|
4006
4331
|
}
|
|
@@ -4025,8 +4350,8 @@ function awsEndpointsFromFile(file, serviceDir) {
|
|
|
4025
4350
|
|
|
4026
4351
|
// src/extract/calls/grpc.ts
|
|
4027
4352
|
init_cjs_shims();
|
|
4028
|
-
var
|
|
4029
|
-
var
|
|
4353
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
4354
|
+
var import_types15 = require("@neat.is/types");
|
|
4030
4355
|
var GRPC_CLIENT_RE = /new\s+([A-Z][A-Za-z0-9_]*)Client\s*\(\s*['"`]?([^,'"`)]+)?/g;
|
|
4031
4356
|
var AWS_SDK_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@aws-sdk\/client-([a-z0-9-]+)['"`]/g;
|
|
4032
4357
|
var GRPC_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@grpc\/grpc-js['"`]|_grpc_pb['"`]/;
|
|
@@ -4075,7 +4400,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
4075
4400
|
const { kind } = classified;
|
|
4076
4401
|
const line = lineOf(file.content, m[0]);
|
|
4077
4402
|
out.push({
|
|
4078
|
-
infraId: (0,
|
|
4403
|
+
infraId: (0, import_types15.infraId)(kind, name),
|
|
4079
4404
|
name,
|
|
4080
4405
|
kind,
|
|
4081
4406
|
edgeType: "CALLS",
|
|
@@ -4084,7 +4409,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
4084
4409
|
// tier (ADR-066).
|
|
4085
4410
|
confidenceKind: "verified-call-site",
|
|
4086
4411
|
evidence: {
|
|
4087
|
-
file:
|
|
4412
|
+
file: import_node_path26.default.relative(serviceDir, file.path),
|
|
4088
4413
|
line,
|
|
4089
4414
|
snippet: snippet(file.content, line)
|
|
4090
4415
|
}
|
|
@@ -4097,11 +4422,11 @@ function grpcEndpointsFromFile(file, serviceDir) {
|
|
|
4097
4422
|
function edgeTypeFromEndpoint(ep) {
|
|
4098
4423
|
switch (ep.edgeType) {
|
|
4099
4424
|
case "PUBLISHES_TO":
|
|
4100
|
-
return
|
|
4425
|
+
return import_types16.EdgeType.PUBLISHES_TO;
|
|
4101
4426
|
case "CONSUMES_FROM":
|
|
4102
|
-
return
|
|
4427
|
+
return import_types16.EdgeType.CONSUMES_FROM;
|
|
4103
4428
|
default:
|
|
4104
|
-
return
|
|
4429
|
+
return import_types16.EdgeType.CALLS;
|
|
4105
4430
|
}
|
|
4106
4431
|
}
|
|
4107
4432
|
function isAwsKind(kind) {
|
|
@@ -4128,7 +4453,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
4128
4453
|
if (!graph.hasNode(ep.infraId)) {
|
|
4129
4454
|
const node = {
|
|
4130
4455
|
id: ep.infraId,
|
|
4131
|
-
type:
|
|
4456
|
+
type: import_types16.NodeType.InfraNode,
|
|
4132
4457
|
name: ep.name,
|
|
4133
4458
|
// #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
|
|
4134
4459
|
// aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
|
|
@@ -4140,7 +4465,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
4140
4465
|
nodesAdded++;
|
|
4141
4466
|
}
|
|
4142
4467
|
const edgeType = edgeTypeFromEndpoint(ep);
|
|
4143
|
-
const confidence = (0,
|
|
4468
|
+
const confidence = (0, import_types16.confidenceForExtracted)(ep.confidenceKind);
|
|
4144
4469
|
const relFile = toPosix2(ep.evidence.file);
|
|
4145
4470
|
const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
4146
4471
|
graph,
|
|
@@ -4150,7 +4475,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
4150
4475
|
);
|
|
4151
4476
|
nodesAdded += n;
|
|
4152
4477
|
edgesAdded += e;
|
|
4153
|
-
if (!(0,
|
|
4478
|
+
if (!(0, import_types16.passesExtractedFloor)(confidence)) {
|
|
4154
4479
|
noteExtractedDropped({
|
|
4155
4480
|
source: fileNodeId,
|
|
4156
4481
|
target: ep.infraId,
|
|
@@ -4170,7 +4495,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
4170
4495
|
source: fileNodeId,
|
|
4171
4496
|
target: ep.infraId,
|
|
4172
4497
|
type: edgeType,
|
|
4173
|
-
provenance:
|
|
4498
|
+
provenance: import_types16.Provenance.EXTRACTED,
|
|
4174
4499
|
confidence,
|
|
4175
4500
|
evidence: ep.evidence
|
|
4176
4501
|
};
|
|
@@ -4195,16 +4520,16 @@ init_cjs_shims();
|
|
|
4195
4520
|
|
|
4196
4521
|
// src/extract/infra/docker-compose.ts
|
|
4197
4522
|
init_cjs_shims();
|
|
4198
|
-
var
|
|
4199
|
-
var
|
|
4523
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
4524
|
+
var import_types18 = require("@neat.is/types");
|
|
4200
4525
|
|
|
4201
4526
|
// src/extract/infra/shared.ts
|
|
4202
4527
|
init_cjs_shims();
|
|
4203
|
-
var
|
|
4528
|
+
var import_types17 = require("@neat.is/types");
|
|
4204
4529
|
function makeInfraNode(kind, name, provider = "self", extras) {
|
|
4205
4530
|
return {
|
|
4206
|
-
id: (0,
|
|
4207
|
-
type:
|
|
4531
|
+
id: (0, import_types17.infraId)(kind, name),
|
|
4532
|
+
type: import_types17.NodeType.InfraNode,
|
|
4208
4533
|
name,
|
|
4209
4534
|
provider,
|
|
4210
4535
|
kind,
|
|
@@ -4233,7 +4558,7 @@ function dependsOnList(value) {
|
|
|
4233
4558
|
}
|
|
4234
4559
|
function serviceNameToServiceNode(name, services) {
|
|
4235
4560
|
for (const s of services) {
|
|
4236
|
-
if (s.node.name === name ||
|
|
4561
|
+
if (s.node.name === name || import_node_path27.default.basename(s.dir) === name) return s.node.id;
|
|
4237
4562
|
}
|
|
4238
4563
|
return null;
|
|
4239
4564
|
}
|
|
@@ -4242,7 +4567,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
4242
4567
|
let edgesAdded = 0;
|
|
4243
4568
|
let composePath = null;
|
|
4244
4569
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
4245
|
-
const abs =
|
|
4570
|
+
const abs = import_node_path27.default.join(scanPath, name);
|
|
4246
4571
|
if (await exists(abs)) {
|
|
4247
4572
|
composePath = abs;
|
|
4248
4573
|
break;
|
|
@@ -4255,13 +4580,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
4255
4580
|
} catch (err) {
|
|
4256
4581
|
recordExtractionError(
|
|
4257
4582
|
"infra docker-compose",
|
|
4258
|
-
|
|
4583
|
+
import_node_path27.default.relative(scanPath, composePath),
|
|
4259
4584
|
err
|
|
4260
4585
|
);
|
|
4261
4586
|
return { nodesAdded, edgesAdded };
|
|
4262
4587
|
}
|
|
4263
4588
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
4264
|
-
const evidenceFile =
|
|
4589
|
+
const evidenceFile = import_node_path27.default.relative(scanPath, composePath).split(import_node_path27.default.sep).join("/");
|
|
4265
4590
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
4266
4591
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
4267
4592
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -4283,15 +4608,15 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
4283
4608
|
for (const dep of dependsOnList(svc.depends_on)) {
|
|
4284
4609
|
const targetId = composeNameToNodeId.get(dep);
|
|
4285
4610
|
if (!targetId) continue;
|
|
4286
|
-
const edgeId = (0, import_types4.extractedEdgeId)(sourceId, targetId,
|
|
4611
|
+
const edgeId = (0, import_types4.extractedEdgeId)(sourceId, targetId, import_types18.EdgeType.DEPENDS_ON);
|
|
4287
4612
|
if (graph.hasEdge(edgeId)) continue;
|
|
4288
4613
|
const edge = {
|
|
4289
4614
|
id: edgeId,
|
|
4290
4615
|
source: sourceId,
|
|
4291
4616
|
target: targetId,
|
|
4292
|
-
type:
|
|
4293
|
-
provenance:
|
|
4294
|
-
confidence: (0,
|
|
4617
|
+
type: import_types18.EdgeType.DEPENDS_ON,
|
|
4618
|
+
provenance: import_types18.Provenance.EXTRACTED,
|
|
4619
|
+
confidence: (0, import_types18.confidenceForExtracted)("structural"),
|
|
4295
4620
|
evidence: { file: evidenceFile }
|
|
4296
4621
|
};
|
|
4297
4622
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -4303,9 +4628,9 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
4303
4628
|
|
|
4304
4629
|
// src/extract/infra/dockerfile.ts
|
|
4305
4630
|
init_cjs_shims();
|
|
4306
|
-
var
|
|
4307
|
-
var
|
|
4308
|
-
var
|
|
4631
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
4632
|
+
var import_node_fs15 = require("fs");
|
|
4633
|
+
var import_types19 = require("@neat.is/types");
|
|
4309
4634
|
function runtimeImage(content) {
|
|
4310
4635
|
const lines = content.split("\n");
|
|
4311
4636
|
let last = null;
|
|
@@ -4324,15 +4649,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
4324
4649
|
let nodesAdded = 0;
|
|
4325
4650
|
let edgesAdded = 0;
|
|
4326
4651
|
for (const service of services) {
|
|
4327
|
-
const dockerfilePath =
|
|
4652
|
+
const dockerfilePath = import_node_path28.default.join(service.dir, "Dockerfile");
|
|
4328
4653
|
if (!await exists(dockerfilePath)) continue;
|
|
4329
4654
|
let content;
|
|
4330
4655
|
try {
|
|
4331
|
-
content = await
|
|
4656
|
+
content = await import_node_fs15.promises.readFile(dockerfilePath, "utf8");
|
|
4332
4657
|
} catch (err) {
|
|
4333
4658
|
recordExtractionError(
|
|
4334
4659
|
"infra dockerfile",
|
|
4335
|
-
|
|
4660
|
+
import_node_path28.default.relative(scanPath, dockerfilePath),
|
|
4336
4661
|
err
|
|
4337
4662
|
);
|
|
4338
4663
|
continue;
|
|
@@ -4344,7 +4669,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
4344
4669
|
graph.addNode(node.id, node);
|
|
4345
4670
|
nodesAdded++;
|
|
4346
4671
|
}
|
|
4347
|
-
const relDockerfile = toPosix2(
|
|
4672
|
+
const relDockerfile = toPosix2(import_node_path28.default.relative(service.dir, dockerfilePath));
|
|
4348
4673
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
4349
4674
|
graph,
|
|
4350
4675
|
service.pkg.name,
|
|
@@ -4353,17 +4678,17 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
4353
4678
|
);
|
|
4354
4679
|
nodesAdded += fn;
|
|
4355
4680
|
edgesAdded += fe;
|
|
4356
|
-
const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, node.id,
|
|
4681
|
+
const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, node.id, import_types19.EdgeType.RUNS_ON);
|
|
4357
4682
|
if (!graph.hasEdge(edgeId)) {
|
|
4358
4683
|
const edge = {
|
|
4359
4684
|
id: edgeId,
|
|
4360
4685
|
source: fileNodeId,
|
|
4361
4686
|
target: node.id,
|
|
4362
|
-
type:
|
|
4363
|
-
provenance:
|
|
4364
|
-
confidence: (0,
|
|
4687
|
+
type: import_types19.EdgeType.RUNS_ON,
|
|
4688
|
+
provenance: import_types19.Provenance.EXTRACTED,
|
|
4689
|
+
confidence: (0, import_types19.confidenceForExtracted)("structural"),
|
|
4365
4690
|
evidence: {
|
|
4366
|
-
file: toPosix2(
|
|
4691
|
+
file: toPosix2(import_node_path28.default.relative(scanPath, dockerfilePath))
|
|
4367
4692
|
}
|
|
4368
4693
|
};
|
|
4369
4694
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -4375,21 +4700,21 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
4375
4700
|
|
|
4376
4701
|
// src/extract/infra/terraform.ts
|
|
4377
4702
|
init_cjs_shims();
|
|
4378
|
-
var
|
|
4379
|
-
var
|
|
4703
|
+
var import_node_fs16 = require("fs");
|
|
4704
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
4380
4705
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
4381
4706
|
async function walkTfFiles(start, depth = 0, max = 5) {
|
|
4382
4707
|
if (depth > max) return [];
|
|
4383
4708
|
const out = [];
|
|
4384
|
-
const entries = await
|
|
4709
|
+
const entries = await import_node_fs16.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
4385
4710
|
for (const entry2 of entries) {
|
|
4386
4711
|
if (entry2.isDirectory()) {
|
|
4387
4712
|
if (IGNORED_DIRS.has(entry2.name) || entry2.name === ".terraform") continue;
|
|
4388
|
-
const child =
|
|
4713
|
+
const child = import_node_path29.default.join(start, entry2.name);
|
|
4389
4714
|
if (await isPythonVenvDir(child)) continue;
|
|
4390
4715
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
4391
4716
|
} else if (entry2.isFile() && entry2.name.endsWith(".tf")) {
|
|
4392
|
-
out.push(
|
|
4717
|
+
out.push(import_node_path29.default.join(start, entry2.name));
|
|
4393
4718
|
}
|
|
4394
4719
|
}
|
|
4395
4720
|
return out;
|
|
@@ -4398,7 +4723,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
4398
4723
|
let nodesAdded = 0;
|
|
4399
4724
|
const files = await walkTfFiles(scanPath);
|
|
4400
4725
|
for (const file of files) {
|
|
4401
|
-
const content = await
|
|
4726
|
+
const content = await import_node_fs16.promises.readFile(file, "utf8");
|
|
4402
4727
|
RESOURCE_RE.lastIndex = 0;
|
|
4403
4728
|
let m;
|
|
4404
4729
|
while ((m = RESOURCE_RE.exec(content)) !== null) {
|
|
@@ -4416,8 +4741,8 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
4416
4741
|
|
|
4417
4742
|
// src/extract/infra/k8s.ts
|
|
4418
4743
|
init_cjs_shims();
|
|
4419
|
-
var
|
|
4420
|
-
var
|
|
4744
|
+
var import_node_fs17 = require("fs");
|
|
4745
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
4421
4746
|
var import_yaml3 = require("yaml");
|
|
4422
4747
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
4423
4748
|
Service: "k8s-service",
|
|
@@ -4431,15 +4756,15 @@ var K8S_KIND_TO_INFRA_KIND = {
|
|
|
4431
4756
|
async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
4432
4757
|
if (depth > max) return [];
|
|
4433
4758
|
const out = [];
|
|
4434
|
-
const entries = await
|
|
4759
|
+
const entries = await import_node_fs17.promises.readdir(start, { withFileTypes: true }).catch(() => []);
|
|
4435
4760
|
for (const entry2 of entries) {
|
|
4436
4761
|
if (entry2.isDirectory()) {
|
|
4437
4762
|
if (IGNORED_DIRS.has(entry2.name)) continue;
|
|
4438
|
-
const child =
|
|
4763
|
+
const child = import_node_path30.default.join(start, entry2.name);
|
|
4439
4764
|
if (await isPythonVenvDir(child)) continue;
|
|
4440
4765
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
4441
|
-
} else if (entry2.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
4442
|
-
out.push(
|
|
4766
|
+
} else if (entry2.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path30.default.extname(entry2.name))) {
|
|
4767
|
+
out.push(import_node_path30.default.join(start, entry2.name));
|
|
4443
4768
|
}
|
|
4444
4769
|
}
|
|
4445
4770
|
return out;
|
|
@@ -4448,7 +4773,7 @@ async function addK8sResources(graph, scanPath) {
|
|
|
4448
4773
|
let nodesAdded = 0;
|
|
4449
4774
|
const files = await walkYamlFiles2(scanPath);
|
|
4450
4775
|
for (const file of files) {
|
|
4451
|
-
const content = await
|
|
4776
|
+
const content = await import_node_fs17.promises.readFile(file, "utf8");
|
|
4452
4777
|
let docs;
|
|
4453
4778
|
try {
|
|
4454
4779
|
docs = (0, import_yaml3.parseAllDocuments)(content).map((d) => d.toJSON());
|
|
@@ -4483,17 +4808,17 @@ async function addInfra(graph, scanPath, services) {
|
|
|
4483
4808
|
}
|
|
4484
4809
|
|
|
4485
4810
|
// src/extract/index.ts
|
|
4486
|
-
var
|
|
4811
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
4487
4812
|
|
|
4488
4813
|
// src/extract/retire.ts
|
|
4489
4814
|
init_cjs_shims();
|
|
4490
|
-
var
|
|
4491
|
-
var
|
|
4492
|
-
var
|
|
4815
|
+
var import_node_fs18 = require("fs");
|
|
4816
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
4817
|
+
var import_types20 = require("@neat.is/types");
|
|
4493
4818
|
function dropOrphanedFileNodes(graph) {
|
|
4494
4819
|
const orphans = [];
|
|
4495
4820
|
graph.forEachNode((id, attrs) => {
|
|
4496
|
-
if (attrs.type !==
|
|
4821
|
+
if (attrs.type !== import_types20.NodeType.FileNode) return;
|
|
4497
4822
|
if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
|
|
4498
4823
|
orphans.push(id);
|
|
4499
4824
|
}
|
|
@@ -4506,14 +4831,14 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
4506
4831
|
const bases = [scanPath, ...serviceDirs];
|
|
4507
4832
|
graph.forEachEdge((id, attrs) => {
|
|
4508
4833
|
const edge = attrs;
|
|
4509
|
-
if (edge.provenance !==
|
|
4834
|
+
if (edge.provenance !== import_types20.Provenance.EXTRACTED) return;
|
|
4510
4835
|
const evidenceFile = edge.evidence?.file;
|
|
4511
4836
|
if (!evidenceFile) return;
|
|
4512
|
-
if (
|
|
4513
|
-
if (!(0,
|
|
4837
|
+
if (import_node_path31.default.isAbsolute(evidenceFile)) {
|
|
4838
|
+
if (!(0, import_node_fs18.existsSync)(evidenceFile)) toDrop.push(id);
|
|
4514
4839
|
return;
|
|
4515
4840
|
}
|
|
4516
|
-
const found = bases.some((base) => (0,
|
|
4841
|
+
const found = bases.some((base) => (0, import_node_fs18.existsSync)(import_node_path31.default.join(base, evidenceFile)));
|
|
4517
4842
|
if (!found) toDrop.push(id);
|
|
4518
4843
|
});
|
|
4519
4844
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -4528,6 +4853,8 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
4528
4853
|
const services = await discoverServices(scanPath);
|
|
4529
4854
|
const phase1Nodes = addServiceNodes(graph, services);
|
|
4530
4855
|
await addServiceAliases(graph, scanPath, services);
|
|
4856
|
+
const fileEnum = await addFiles(graph, services);
|
|
4857
|
+
const importGraph = await addImports(graph, services);
|
|
4531
4858
|
const phase2 = await addDatabasesAndCompat(graph, services, scanPath);
|
|
4532
4859
|
const phase3 = await addConfigNodes(graph, services, scanPath);
|
|
4533
4860
|
const phase4 = await addCallEdges(graph, services);
|
|
@@ -4551,7 +4878,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
4551
4878
|
}
|
|
4552
4879
|
const droppedEntries = drainDroppedExtracted();
|
|
4553
4880
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
4554
|
-
const rejectedPath =
|
|
4881
|
+
const rejectedPath = import_node_path32.default.join(import_node_path32.default.dirname(opts.errorsPath), "rejected.ndjson");
|
|
4555
4882
|
try {
|
|
4556
4883
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
4557
4884
|
} catch (err) {
|
|
@@ -4561,8 +4888,8 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
4561
4888
|
}
|
|
4562
4889
|
}
|
|
4563
4890
|
const result = {
|
|
4564
|
-
nodesAdded: phase1Nodes + phase2.nodesAdded + phase3.nodesAdded + phase4.nodesAdded + phase5.nodesAdded,
|
|
4565
|
-
edgesAdded: phase2.edgesAdded + phase3.edgesAdded + phase4.edgesAdded + phase5.edgesAdded,
|
|
4891
|
+
nodesAdded: phase1Nodes + fileEnum.nodesAdded + importGraph.nodesAdded + phase2.nodesAdded + phase3.nodesAdded + phase4.nodesAdded + phase5.nodesAdded,
|
|
4892
|
+
edgesAdded: fileEnum.edgesAdded + importGraph.edgesAdded + phase2.edgesAdded + phase3.edgesAdded + phase4.edgesAdded + phase5.edgesAdded,
|
|
4566
4893
|
frontiersPromoted,
|
|
4567
4894
|
extractionErrors: errorEntries.length,
|
|
4568
4895
|
errorEntries,
|
|
@@ -4585,9 +4912,9 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
4585
4912
|
|
|
4586
4913
|
// src/persist.ts
|
|
4587
4914
|
init_cjs_shims();
|
|
4588
|
-
var
|
|
4589
|
-
var
|
|
4590
|
-
var
|
|
4915
|
+
var import_node_fs19 = require("fs");
|
|
4916
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
4917
|
+
var import_types21 = require("@neat.is/types");
|
|
4591
4918
|
var SCHEMA_VERSION = 4;
|
|
4592
4919
|
function migrateV1ToV2(payload) {
|
|
4593
4920
|
const nodes = payload.graph.nodes;
|
|
@@ -4609,12 +4936,12 @@ function migrateV2ToV3(payload) {
|
|
|
4609
4936
|
for (const edge of edges) {
|
|
4610
4937
|
const attrs = edge.attributes;
|
|
4611
4938
|
if (!attrs || attrs.provenance !== "FRONTIER") continue;
|
|
4612
|
-
attrs.provenance =
|
|
4939
|
+
attrs.provenance = import_types21.Provenance.OBSERVED;
|
|
4613
4940
|
const type = typeof attrs.type === "string" ? attrs.type : void 0;
|
|
4614
4941
|
const source = typeof attrs.source === "string" ? attrs.source : void 0;
|
|
4615
4942
|
const target = typeof attrs.target === "string" ? attrs.target : void 0;
|
|
4616
4943
|
if (type && source && target) {
|
|
4617
|
-
const newId = (0,
|
|
4944
|
+
const newId = (0, import_types21.observedEdgeId)(source, target, type);
|
|
4618
4945
|
attrs.id = newId;
|
|
4619
4946
|
if (edge.key) edge.key = newId;
|
|
4620
4947
|
}
|
|
@@ -4623,7 +4950,7 @@ function migrateV2ToV3(payload) {
|
|
|
4623
4950
|
return { ...payload, schemaVersion: 3 };
|
|
4624
4951
|
}
|
|
4625
4952
|
async function ensureDir(filePath) {
|
|
4626
|
-
await
|
|
4953
|
+
await import_node_fs19.promises.mkdir(import_node_path33.default.dirname(filePath), { recursive: true });
|
|
4627
4954
|
}
|
|
4628
4955
|
async function saveGraphToDisk(graph, outPath) {
|
|
4629
4956
|
await ensureDir(outPath);
|
|
@@ -4633,13 +4960,13 @@ async function saveGraphToDisk(graph, outPath) {
|
|
|
4633
4960
|
graph: graph.export()
|
|
4634
4961
|
};
|
|
4635
4962
|
const tmp = `${outPath}.tmp`;
|
|
4636
|
-
await
|
|
4637
|
-
await
|
|
4963
|
+
await import_node_fs19.promises.writeFile(tmp, JSON.stringify(payload), "utf8");
|
|
4964
|
+
await import_node_fs19.promises.rename(tmp, outPath);
|
|
4638
4965
|
}
|
|
4639
4966
|
async function loadGraphFromDisk(graph, outPath) {
|
|
4640
4967
|
let raw;
|
|
4641
4968
|
try {
|
|
4642
|
-
raw = await
|
|
4969
|
+
raw = await import_node_fs19.promises.readFile(outPath, "utf8");
|
|
4643
4970
|
} catch (err) {
|
|
4644
4971
|
if (err.code === "ENOENT") return;
|
|
4645
4972
|
throw err;
|
|
@@ -4698,23 +5025,23 @@ function startPersistLoop(graph, outPath, intervalMs = 6e4) {
|
|
|
4698
5025
|
|
|
4699
5026
|
// src/projects.ts
|
|
4700
5027
|
init_cjs_shims();
|
|
4701
|
-
var
|
|
5028
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
4702
5029
|
function pathsForProject(project, baseDir) {
|
|
4703
5030
|
if (project === DEFAULT_PROJECT) {
|
|
4704
5031
|
return {
|
|
4705
|
-
snapshotPath:
|
|
4706
|
-
errorsPath:
|
|
4707
|
-
staleEventsPath:
|
|
4708
|
-
embeddingsCachePath:
|
|
4709
|
-
policyViolationsPath:
|
|
5032
|
+
snapshotPath: import_node_path34.default.join(baseDir, "graph.json"),
|
|
5033
|
+
errorsPath: import_node_path34.default.join(baseDir, "errors.ndjson"),
|
|
5034
|
+
staleEventsPath: import_node_path34.default.join(baseDir, "stale-events.ndjson"),
|
|
5035
|
+
embeddingsCachePath: import_node_path34.default.join(baseDir, "embeddings.json"),
|
|
5036
|
+
policyViolationsPath: import_node_path34.default.join(baseDir, "policy-violations.ndjson")
|
|
4710
5037
|
};
|
|
4711
5038
|
}
|
|
4712
5039
|
return {
|
|
4713
|
-
snapshotPath:
|
|
4714
|
-
errorsPath:
|
|
4715
|
-
staleEventsPath:
|
|
4716
|
-
embeddingsCachePath:
|
|
4717
|
-
policyViolationsPath:
|
|
5040
|
+
snapshotPath: import_node_path34.default.join(baseDir, `${project}.json`),
|
|
5041
|
+
errorsPath: import_node_path34.default.join(baseDir, `errors.${project}.ndjson`),
|
|
5042
|
+
staleEventsPath: import_node_path34.default.join(baseDir, `stale-events.${project}.ndjson`),
|
|
5043
|
+
embeddingsCachePath: import_node_path34.default.join(baseDir, `embeddings.${project}.json`),
|
|
5044
|
+
policyViolationsPath: import_node_path34.default.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
4718
5045
|
};
|
|
4719
5046
|
}
|
|
4720
5047
|
var Projects = class {
|
|
@@ -4752,19 +5079,19 @@ var Projects = class {
|
|
|
4752
5079
|
init_cjs_shims();
|
|
4753
5080
|
var import_fastify = __toESM(require("fastify"), 1);
|
|
4754
5081
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
4755
|
-
var
|
|
5082
|
+
var import_types24 = require("@neat.is/types");
|
|
4756
5083
|
|
|
4757
5084
|
// src/extend/index.ts
|
|
4758
5085
|
init_cjs_shims();
|
|
4759
|
-
var
|
|
4760
|
-
var
|
|
5086
|
+
var import_node_fs21 = require("fs");
|
|
5087
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
4761
5088
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
4762
5089
|
var import_instrumentation_registry = require("@neat.is/instrumentation-registry");
|
|
4763
5090
|
|
|
4764
5091
|
// src/installers/package-manager.ts
|
|
4765
5092
|
init_cjs_shims();
|
|
4766
|
-
var
|
|
4767
|
-
var
|
|
5093
|
+
var import_node_fs20 = require("fs");
|
|
5094
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
4768
5095
|
var import_node_child_process = require("child_process");
|
|
4769
5096
|
var LOCKFILE_PRIORITY = [
|
|
4770
5097
|
{ lockfile: "bun.lockb", pm: "bun", args: ["install", "--no-summary"] },
|
|
@@ -4779,29 +5106,29 @@ var LOCKFILE_PRIORITY = [
|
|
|
4779
5106
|
var NPM_FALLBACK_ARGS = ["install", "--no-audit", "--no-fund", "--prefer-offline"];
|
|
4780
5107
|
async function exists2(p) {
|
|
4781
5108
|
try {
|
|
4782
|
-
await
|
|
5109
|
+
await import_node_fs20.promises.access(p);
|
|
4783
5110
|
return true;
|
|
4784
5111
|
} catch {
|
|
4785
5112
|
return false;
|
|
4786
5113
|
}
|
|
4787
5114
|
}
|
|
4788
5115
|
async function detectPackageManager(serviceDir) {
|
|
4789
|
-
let dir =
|
|
5116
|
+
let dir = import_node_path35.default.resolve(serviceDir);
|
|
4790
5117
|
const stops = /* @__PURE__ */ new Set();
|
|
4791
5118
|
for (let i = 0; i < 64; i++) {
|
|
4792
5119
|
if (stops.has(dir)) break;
|
|
4793
5120
|
stops.add(dir);
|
|
4794
5121
|
for (const candidate of LOCKFILE_PRIORITY) {
|
|
4795
|
-
const lockPath =
|
|
5122
|
+
const lockPath = import_node_path35.default.join(dir, candidate.lockfile);
|
|
4796
5123
|
if (await exists2(lockPath)) {
|
|
4797
5124
|
return { pm: candidate.pm, cwd: dir, args: [...candidate.args] };
|
|
4798
5125
|
}
|
|
4799
5126
|
}
|
|
4800
|
-
const parent =
|
|
5127
|
+
const parent = import_node_path35.default.dirname(dir);
|
|
4801
5128
|
if (parent === dir) break;
|
|
4802
5129
|
dir = parent;
|
|
4803
5130
|
}
|
|
4804
|
-
return { pm: "npm", cwd:
|
|
5131
|
+
return { pm: "npm", cwd: import_node_path35.default.resolve(serviceDir), args: [...NPM_FALLBACK_ARGS] };
|
|
4805
5132
|
}
|
|
4806
5133
|
async function runPackageManagerInstall(cmd) {
|
|
4807
5134
|
return new Promise((resolve) => {
|
|
@@ -4841,32 +5168,32 @@ ${err.message}`
|
|
|
4841
5168
|
}
|
|
4842
5169
|
|
|
4843
5170
|
// src/extend/index.ts
|
|
4844
|
-
async function
|
|
5171
|
+
async function fileExists2(p) {
|
|
4845
5172
|
try {
|
|
4846
|
-
await
|
|
5173
|
+
await import_node_fs21.promises.access(p);
|
|
4847
5174
|
return true;
|
|
4848
5175
|
} catch {
|
|
4849
5176
|
return false;
|
|
4850
5177
|
}
|
|
4851
5178
|
}
|
|
4852
5179
|
async function readPackageJson(scanPath) {
|
|
4853
|
-
const pkgPath =
|
|
4854
|
-
const raw = await
|
|
5180
|
+
const pkgPath = import_node_path36.default.join(scanPath, "package.json");
|
|
5181
|
+
const raw = await import_node_fs21.promises.readFile(pkgPath, "utf8");
|
|
4855
5182
|
return JSON.parse(raw);
|
|
4856
5183
|
}
|
|
4857
5184
|
async function findHookFiles(scanPath) {
|
|
4858
|
-
const entries = await
|
|
5185
|
+
const entries = await import_node_fs21.promises.readdir(scanPath);
|
|
4859
5186
|
return entries.filter(
|
|
4860
5187
|
(e) => (e.startsWith("instrumentation") || e.startsWith("otel-init")) && /\.(ts|js)$/.test(e)
|
|
4861
5188
|
).sort();
|
|
4862
5189
|
}
|
|
4863
5190
|
function extendLogPath() {
|
|
4864
|
-
return process.env.NEAT_EXTEND_LOG ??
|
|
5191
|
+
return process.env.NEAT_EXTEND_LOG ?? import_node_path36.default.join(import_node_os2.default.homedir(), ".neat", "extend-log.ndjson");
|
|
4865
5192
|
}
|
|
4866
5193
|
async function appendExtendLog(entry2) {
|
|
4867
5194
|
const logPath = extendLogPath();
|
|
4868
|
-
await
|
|
4869
|
-
await
|
|
5195
|
+
await import_node_fs21.promises.mkdir(import_node_path36.default.dirname(logPath), { recursive: true });
|
|
5196
|
+
await import_node_fs21.promises.appendFile(logPath, JSON.stringify(entry2) + "\n", "utf8");
|
|
4870
5197
|
}
|
|
4871
5198
|
function splicedContent(fileContent, snippet2) {
|
|
4872
5199
|
if (fileContent.includes("__INSTRUMENTATION_BLOCK__")) {
|
|
@@ -4924,7 +5251,7 @@ function lookupInstrumentation(library, installedVersion) {
|
|
|
4924
5251
|
}
|
|
4925
5252
|
async function describeProjectInstrumentation(ctx) {
|
|
4926
5253
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
4927
|
-
const envNeat = await
|
|
5254
|
+
const envNeat = await fileExists2(import_node_path36.default.join(ctx.scanPath, ".env.neat"));
|
|
4928
5255
|
const registryInstrPackages = new Set(
|
|
4929
5256
|
(0, import_instrumentation_registry.list)().map((e) => e.instrumentation_package).filter((p) => !!p)
|
|
4930
5257
|
);
|
|
@@ -4946,31 +5273,31 @@ async function applyExtension(ctx, args, options) {
|
|
|
4946
5273
|
);
|
|
4947
5274
|
}
|
|
4948
5275
|
for (const file of hookFiles) {
|
|
4949
|
-
const content = await
|
|
5276
|
+
const content = await import_node_fs21.promises.readFile(import_node_path36.default.join(ctx.scanPath, file), "utf8");
|
|
4950
5277
|
if (content.includes(args.registration_snippet)) {
|
|
4951
5278
|
return { library: args.library, filesTouched: [], depsAdded: [], installOutput: "", alreadyApplied: true };
|
|
4952
5279
|
}
|
|
4953
5280
|
}
|
|
4954
5281
|
const primaryFile = hookFiles[0];
|
|
4955
|
-
const primaryPath =
|
|
5282
|
+
const primaryPath = import_node_path36.default.join(ctx.scanPath, primaryFile);
|
|
4956
5283
|
const filesTouched = [];
|
|
4957
5284
|
const depsAdded = [];
|
|
4958
|
-
const pkgPath =
|
|
5285
|
+
const pkgPath = import_node_path36.default.join(ctx.scanPath, "package.json");
|
|
4959
5286
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
4960
5287
|
if (!(pkg.dependencies ?? {})[args.instrumentation_package]) {
|
|
4961
5288
|
pkg.dependencies = { ...pkg.dependencies ?? {}, [args.instrumentation_package]: args.version };
|
|
4962
|
-
await
|
|
5289
|
+
await import_node_fs21.promises.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
4963
5290
|
filesTouched.push("package.json");
|
|
4964
5291
|
depsAdded.push(`${args.instrumentation_package}@${args.version}`);
|
|
4965
5292
|
}
|
|
4966
|
-
const hookContent = await
|
|
5293
|
+
const hookContent = await import_node_fs21.promises.readFile(primaryPath, "utf8");
|
|
4967
5294
|
const patched = splicedContent(hookContent, args.registration_snippet);
|
|
4968
5295
|
if (!patched) {
|
|
4969
5296
|
throw new Error(
|
|
4970
5297
|
`Could not find instrumentation insertion point in ${primaryFile}. Expected __INSTRUMENTATION_BLOCK__, instrumentations.push(, or new NodeSDK(.`
|
|
4971
5298
|
);
|
|
4972
5299
|
}
|
|
4973
|
-
await
|
|
5300
|
+
await import_node_fs21.promises.writeFile(primaryPath, patched, "utf8");
|
|
4974
5301
|
filesTouched.push(primaryFile);
|
|
4975
5302
|
const cmd = await detectPackageManager(ctx.scanPath);
|
|
4976
5303
|
const installer = options?.runInstall ?? runPackageManagerInstall;
|
|
@@ -5001,7 +5328,7 @@ async function dryRunExtension(ctx, args) {
|
|
|
5001
5328
|
};
|
|
5002
5329
|
}
|
|
5003
5330
|
for (const file of hookFiles) {
|
|
5004
|
-
const content = await
|
|
5331
|
+
const content = await import_node_fs21.promises.readFile(import_node_path36.default.join(ctx.scanPath, file), "utf8");
|
|
5005
5332
|
if (content.includes(args.registration_snippet)) {
|
|
5006
5333
|
return {
|
|
5007
5334
|
library: args.library,
|
|
@@ -5023,7 +5350,7 @@ async function dryRunExtension(ctx, args) {
|
|
|
5023
5350
|
depsToAdd.push(`${args.instrumentation_package}@${args.version}`);
|
|
5024
5351
|
filesTouched.push("package.json");
|
|
5025
5352
|
}
|
|
5026
|
-
const hookContent = await
|
|
5353
|
+
const hookContent = await import_node_fs21.promises.readFile(import_node_path36.default.join(ctx.scanPath, primaryFile), "utf8");
|
|
5027
5354
|
const patched = splicedContent(hookContent, args.registration_snippet);
|
|
5028
5355
|
if (patched) {
|
|
5029
5356
|
filesTouched.push(primaryFile);
|
|
@@ -5035,31 +5362,31 @@ async function dryRunExtension(ctx, args) {
|
|
|
5035
5362
|
}
|
|
5036
5363
|
async function rollbackExtension(ctx, args) {
|
|
5037
5364
|
const logPath = extendLogPath();
|
|
5038
|
-
if (!await
|
|
5365
|
+
if (!await fileExists2(logPath)) {
|
|
5039
5366
|
return { undone: false, message: "no apply found for library" };
|
|
5040
5367
|
}
|
|
5041
|
-
const raw = await
|
|
5368
|
+
const raw = await import_node_fs21.promises.readFile(logPath, "utf8");
|
|
5042
5369
|
const entries = raw.trim().split("\n").filter(Boolean).map((line) => JSON.parse(line));
|
|
5043
5370
|
const match = [...entries].reverse().find((e) => e.project === ctx.project && e.library === args.library);
|
|
5044
5371
|
if (!match) {
|
|
5045
5372
|
return { undone: false, message: "no apply found for library" };
|
|
5046
5373
|
}
|
|
5047
|
-
const pkgPath =
|
|
5048
|
-
if (await
|
|
5374
|
+
const pkgPath = import_node_path36.default.join(ctx.scanPath, "package.json");
|
|
5375
|
+
if (await fileExists2(pkgPath)) {
|
|
5049
5376
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
5050
5377
|
if (pkg.dependencies?.[match.instrumentation_package]) {
|
|
5051
5378
|
const { [match.instrumentation_package]: _removed, ...rest } = pkg.dependencies;
|
|
5052
5379
|
pkg.dependencies = rest;
|
|
5053
|
-
await
|
|
5380
|
+
await import_node_fs21.promises.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
5054
5381
|
}
|
|
5055
5382
|
}
|
|
5056
5383
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
5057
5384
|
for (const file of hookFiles) {
|
|
5058
|
-
const filePath =
|
|
5059
|
-
const content = await
|
|
5385
|
+
const filePath = import_node_path36.default.join(ctx.scanPath, file);
|
|
5386
|
+
const content = await import_node_fs21.promises.readFile(filePath, "utf8");
|
|
5060
5387
|
if (content.includes(match.registration_snippet)) {
|
|
5061
5388
|
const filtered = content.split("\n").filter((line) => !line.includes(match.registration_snippet)).join("\n");
|
|
5062
|
-
await
|
|
5389
|
+
await import_node_fs21.promises.writeFile(filePath, filtered, "utf8");
|
|
5063
5390
|
break;
|
|
5064
5391
|
}
|
|
5065
5392
|
}
|
|
@@ -5071,7 +5398,7 @@ async function rollbackExtension(ctx, args) {
|
|
|
5071
5398
|
|
|
5072
5399
|
// src/divergences.ts
|
|
5073
5400
|
init_cjs_shims();
|
|
5074
|
-
var
|
|
5401
|
+
var import_types22 = require("@neat.is/types");
|
|
5075
5402
|
function bucketKey(source, target, type) {
|
|
5076
5403
|
return `${type}|${source}|${target}`;
|
|
5077
5404
|
}
|
|
@@ -5079,22 +5406,22 @@ function bucketEdges(graph) {
|
|
|
5079
5406
|
const buckets = /* @__PURE__ */ new Map();
|
|
5080
5407
|
graph.forEachEdge((id, attrs) => {
|
|
5081
5408
|
const e = attrs;
|
|
5082
|
-
const parsed = (0,
|
|
5409
|
+
const parsed = (0, import_types22.parseEdgeId)(id);
|
|
5083
5410
|
const provenance = parsed?.provenance ?? e.provenance;
|
|
5084
5411
|
const key = bucketKey(e.source, e.target, e.type);
|
|
5085
5412
|
const cur = buckets.get(key) ?? { source: e.source, target: e.target, type: e.type };
|
|
5086
5413
|
switch (provenance) {
|
|
5087
|
-
case
|
|
5414
|
+
case import_types22.Provenance.EXTRACTED:
|
|
5088
5415
|
cur.extracted = e;
|
|
5089
5416
|
break;
|
|
5090
|
-
case
|
|
5417
|
+
case import_types22.Provenance.OBSERVED:
|
|
5091
5418
|
cur.observed = e;
|
|
5092
5419
|
break;
|
|
5093
|
-
case
|
|
5420
|
+
case import_types22.Provenance.INFERRED:
|
|
5094
5421
|
cur.inferred = e;
|
|
5095
5422
|
break;
|
|
5096
5423
|
default:
|
|
5097
|
-
if (e.provenance ===
|
|
5424
|
+
if (e.provenance === import_types22.Provenance.STALE) cur.stale = e;
|
|
5098
5425
|
}
|
|
5099
5426
|
buckets.set(key, cur);
|
|
5100
5427
|
});
|
|
@@ -5103,7 +5430,7 @@ function bucketEdges(graph) {
|
|
|
5103
5430
|
function nodeIsFrontier(graph, nodeId) {
|
|
5104
5431
|
if (!graph.hasNode(nodeId)) return false;
|
|
5105
5432
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
5106
|
-
return attrs.type ===
|
|
5433
|
+
return attrs.type === import_types22.NodeType.FrontierNode;
|
|
5107
5434
|
}
|
|
5108
5435
|
function clampConfidence(n) {
|
|
5109
5436
|
if (!Number.isFinite(n)) return 0;
|
|
@@ -5124,7 +5451,7 @@ function gradedConfidence(edge) {
|
|
|
5124
5451
|
}
|
|
5125
5452
|
function detectMissingDivergences(graph, bucket) {
|
|
5126
5453
|
const out = [];
|
|
5127
|
-
if (bucket.type ===
|
|
5454
|
+
if (bucket.type === import_types22.EdgeType.CONTAINS) return out;
|
|
5128
5455
|
if (bucket.extracted && !bucket.observed) {
|
|
5129
5456
|
if (!nodeIsFrontier(graph, bucket.target)) {
|
|
5130
5457
|
out.push({
|
|
@@ -5165,7 +5492,7 @@ function declaredHostFor(svc) {
|
|
|
5165
5492
|
function hasExtractedConfiguredBy(graph, svcId) {
|
|
5166
5493
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
5167
5494
|
const e = graph.getEdgeAttributes(edgeId);
|
|
5168
|
-
if (e.type ===
|
|
5495
|
+
if (e.type === import_types22.EdgeType.CONFIGURED_BY && e.provenance === import_types22.Provenance.EXTRACTED) {
|
|
5169
5496
|
return true;
|
|
5170
5497
|
}
|
|
5171
5498
|
}
|
|
@@ -5178,10 +5505,10 @@ function detectHostMismatch(graph, svcId, svc) {
|
|
|
5178
5505
|
const out = [];
|
|
5179
5506
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
5180
5507
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
5181
|
-
if (edge.type !==
|
|
5182
|
-
if (edge.provenance !==
|
|
5508
|
+
if (edge.type !== import_types22.EdgeType.CONNECTS_TO) continue;
|
|
5509
|
+
if (edge.provenance !== import_types22.Provenance.OBSERVED) continue;
|
|
5183
5510
|
const target = graph.getNodeAttributes(edge.target);
|
|
5184
|
-
if (target.type !==
|
|
5511
|
+
if (target.type !== import_types22.NodeType.DatabaseNode) continue;
|
|
5185
5512
|
const observedHost = target.host?.trim();
|
|
5186
5513
|
if (!observedHost) continue;
|
|
5187
5514
|
if (observedHost === declaredHost) continue;
|
|
@@ -5203,10 +5530,10 @@ function detectCompatDivergences(graph, svcId, svc) {
|
|
|
5203
5530
|
const deps = svc.dependencies ?? {};
|
|
5204
5531
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
5205
5532
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
5206
|
-
if (edge.type !==
|
|
5207
|
-
if (edge.provenance !==
|
|
5533
|
+
if (edge.type !== import_types22.EdgeType.CONNECTS_TO) continue;
|
|
5534
|
+
if (edge.provenance !== import_types22.Provenance.OBSERVED) continue;
|
|
5208
5535
|
const target = graph.getNodeAttributes(edge.target);
|
|
5209
|
-
if (target.type !==
|
|
5536
|
+
if (target.type !== import_types22.NodeType.DatabaseNode) continue;
|
|
5210
5537
|
for (const pair of compatPairs()) {
|
|
5211
5538
|
if (pair.engine !== target.engine) continue;
|
|
5212
5539
|
const declared = deps[pair.driver];
|
|
@@ -5267,7 +5594,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
5267
5594
|
}
|
|
5268
5595
|
graph.forEachNode((nodeId, attrs) => {
|
|
5269
5596
|
const n = attrs;
|
|
5270
|
-
if (n.type !==
|
|
5597
|
+
if (n.type !== import_types22.NodeType.ServiceNode) return;
|
|
5271
5598
|
const svc = n;
|
|
5272
5599
|
for (const d of detectHostMismatch(graph, nodeId, svc)) all.push(d);
|
|
5273
5600
|
for (const d of detectCompatDivergences(graph, nodeId, svc)) all.push(d);
|
|
@@ -5300,7 +5627,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
5300
5627
|
if (a.source !== b.source) return a.source.localeCompare(b.source);
|
|
5301
5628
|
return a.target.localeCompare(b.target);
|
|
5302
5629
|
});
|
|
5303
|
-
return
|
|
5630
|
+
return import_types22.DivergenceResultSchema.parse({
|
|
5304
5631
|
divergences: filtered,
|
|
5305
5632
|
totalAffected: filtered.length,
|
|
5306
5633
|
computedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -5309,7 +5636,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
5309
5636
|
|
|
5310
5637
|
// src/diff.ts
|
|
5311
5638
|
init_cjs_shims();
|
|
5312
|
-
var
|
|
5639
|
+
var import_node_fs22 = require("fs");
|
|
5313
5640
|
async function loadSnapshotForDiff(target) {
|
|
5314
5641
|
if (/^https?:\/\//i.test(target)) {
|
|
5315
5642
|
const res = await fetch(target);
|
|
@@ -5318,7 +5645,7 @@ async function loadSnapshotForDiff(target) {
|
|
|
5318
5645
|
}
|
|
5319
5646
|
return await res.json();
|
|
5320
5647
|
}
|
|
5321
|
-
const raw = await
|
|
5648
|
+
const raw = await import_node_fs22.promises.readFile(target, "utf8");
|
|
5322
5649
|
return JSON.parse(raw);
|
|
5323
5650
|
}
|
|
5324
5651
|
function indexEntries(entries) {
|
|
@@ -5386,25 +5713,25 @@ function canonicalJson(value) {
|
|
|
5386
5713
|
|
|
5387
5714
|
// src/registry.ts
|
|
5388
5715
|
init_cjs_shims();
|
|
5389
|
-
var
|
|
5716
|
+
var import_node_fs23 = require("fs");
|
|
5390
5717
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
5391
|
-
var
|
|
5392
|
-
var
|
|
5718
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
5719
|
+
var import_types23 = require("@neat.is/types");
|
|
5393
5720
|
var LOCK_TIMEOUT_MS = 5e3;
|
|
5394
5721
|
var LOCK_RETRY_MS = 50;
|
|
5395
5722
|
function neatHome() {
|
|
5396
5723
|
const override = process.env.NEAT_HOME;
|
|
5397
|
-
if (override && override.length > 0) return
|
|
5398
|
-
return
|
|
5724
|
+
if (override && override.length > 0) return import_node_path37.default.resolve(override);
|
|
5725
|
+
return import_node_path37.default.join(import_node_os3.default.homedir(), ".neat");
|
|
5399
5726
|
}
|
|
5400
5727
|
function registryPath() {
|
|
5401
|
-
return
|
|
5728
|
+
return import_node_path37.default.join(neatHome(), "projects.json");
|
|
5402
5729
|
}
|
|
5403
5730
|
function registryLockPath() {
|
|
5404
|
-
return
|
|
5731
|
+
return import_node_path37.default.join(neatHome(), "projects.json.lock");
|
|
5405
5732
|
}
|
|
5406
5733
|
function daemonPidPath() {
|
|
5407
|
-
return
|
|
5734
|
+
return import_node_path37.default.join(neatHome(), "neatd.pid");
|
|
5408
5735
|
}
|
|
5409
5736
|
function isPidAliveDefault(pid) {
|
|
5410
5737
|
try {
|
|
@@ -5416,7 +5743,7 @@ function isPidAliveDefault(pid) {
|
|
|
5416
5743
|
}
|
|
5417
5744
|
async function readPidFile(file) {
|
|
5418
5745
|
try {
|
|
5419
|
-
const raw = await
|
|
5746
|
+
const raw = await import_node_fs23.promises.readFile(file, "utf8");
|
|
5420
5747
|
const pid = Number.parseInt(raw.trim(), 10);
|
|
5421
5748
|
return Number.isInteger(pid) && pid > 0 ? pid : void 0;
|
|
5422
5749
|
} catch {
|
|
@@ -5464,24 +5791,24 @@ function lockHolderMessage(holder, lockPath, timeoutMs) {
|
|
|
5464
5791
|
}
|
|
5465
5792
|
}
|
|
5466
5793
|
async function writeAtomically(target, contents) {
|
|
5467
|
-
await
|
|
5794
|
+
await import_node_fs23.promises.mkdir(import_node_path37.default.dirname(target), { recursive: true });
|
|
5468
5795
|
const tmp = `${target}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
5469
|
-
const fd = await
|
|
5796
|
+
const fd = await import_node_fs23.promises.open(tmp, "w");
|
|
5470
5797
|
try {
|
|
5471
5798
|
await fd.writeFile(contents, "utf8");
|
|
5472
5799
|
await fd.sync();
|
|
5473
5800
|
} finally {
|
|
5474
5801
|
await fd.close();
|
|
5475
5802
|
}
|
|
5476
|
-
await
|
|
5803
|
+
await import_node_fs23.promises.rename(tmp, target);
|
|
5477
5804
|
}
|
|
5478
5805
|
async function acquireLock(lockPath, timeoutMs = LOCK_TIMEOUT_MS, probe = defaultLockHolderProbe) {
|
|
5479
5806
|
const deadline = Date.now() + timeoutMs;
|
|
5480
|
-
await
|
|
5807
|
+
await import_node_fs23.promises.mkdir(import_node_path37.default.dirname(lockPath), { recursive: true });
|
|
5481
5808
|
let probedHolder = false;
|
|
5482
5809
|
while (true) {
|
|
5483
5810
|
try {
|
|
5484
|
-
const fd = await
|
|
5811
|
+
const fd = await import_node_fs23.promises.open(lockPath, "wx");
|
|
5485
5812
|
try {
|
|
5486
5813
|
await fd.writeFile(`${process.pid}
|
|
5487
5814
|
`, "utf8");
|
|
@@ -5506,7 +5833,7 @@ async function acquireLock(lockPath, timeoutMs = LOCK_TIMEOUT_MS, probe = defaul
|
|
|
5506
5833
|
}
|
|
5507
5834
|
}
|
|
5508
5835
|
async function releaseLock(lockPath) {
|
|
5509
|
-
await
|
|
5836
|
+
await import_node_fs23.promises.unlink(lockPath).catch(() => {
|
|
5510
5837
|
});
|
|
5511
5838
|
}
|
|
5512
5839
|
async function withLock(fn) {
|
|
@@ -5522,7 +5849,7 @@ async function readRegistry() {
|
|
|
5522
5849
|
const file = registryPath();
|
|
5523
5850
|
let raw;
|
|
5524
5851
|
try {
|
|
5525
|
-
raw = await
|
|
5852
|
+
raw = await import_node_fs23.promises.readFile(file, "utf8");
|
|
5526
5853
|
} catch (err) {
|
|
5527
5854
|
if (err.code === "ENOENT") {
|
|
5528
5855
|
return { version: 1, projects: [] };
|
|
@@ -5530,10 +5857,10 @@ async function readRegistry() {
|
|
|
5530
5857
|
throw err;
|
|
5531
5858
|
}
|
|
5532
5859
|
const parsed = JSON.parse(raw);
|
|
5533
|
-
return
|
|
5860
|
+
return import_types23.RegistryFileSchema.parse(parsed);
|
|
5534
5861
|
}
|
|
5535
5862
|
async function writeRegistry(reg) {
|
|
5536
|
-
const validated =
|
|
5863
|
+
const validated = import_types23.RegistryFileSchema.parse(reg);
|
|
5537
5864
|
await writeAtomically(registryPath(), JSON.stringify(validated, null, 2) + "\n");
|
|
5538
5865
|
}
|
|
5539
5866
|
async function getProject(name) {
|
|
@@ -5755,11 +6082,11 @@ function registerRoutes(scope, ctx) {
|
|
|
5755
6082
|
const candidates = req2.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
5756
6083
|
const parsed = [];
|
|
5757
6084
|
for (const c of candidates) {
|
|
5758
|
-
const r =
|
|
6085
|
+
const r = import_types24.DivergenceTypeSchema.safeParse(c);
|
|
5759
6086
|
if (!r.success) {
|
|
5760
6087
|
return reply.code(400).send({
|
|
5761
6088
|
error: `unknown divergence type "${c}"`,
|
|
5762
|
-
allowed:
|
|
6089
|
+
allowed: import_types24.DivergenceTypeSchema.options
|
|
5763
6090
|
});
|
|
5764
6091
|
}
|
|
5765
6092
|
parsed.push(r.data);
|
|
@@ -5972,7 +6299,7 @@ function registerRoutes(scope, ctx) {
|
|
|
5972
6299
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
5973
6300
|
let violations = await log.readAll();
|
|
5974
6301
|
if (req2.query.severity) {
|
|
5975
|
-
const sev =
|
|
6302
|
+
const sev = import_types24.PolicySeveritySchema.safeParse(req2.query.severity);
|
|
5976
6303
|
if (!sev.success) {
|
|
5977
6304
|
return reply.code(400).send({
|
|
5978
6305
|
error: "invalid severity",
|
|
@@ -5989,7 +6316,7 @@ function registerRoutes(scope, ctx) {
|
|
|
5989
6316
|
scope.post("/policies/check", async (req2, reply) => {
|
|
5990
6317
|
const proj = resolveProject(registry, req2, reply, ctx.bootstrap);
|
|
5991
6318
|
if (!proj) return;
|
|
5992
|
-
const parsed =
|
|
6319
|
+
const parsed = import_types24.PoliciesCheckBodySchema.safeParse(req2.body ?? {});
|
|
5993
6320
|
if (!parsed.success) {
|
|
5994
6321
|
return reply.code(400).send({
|
|
5995
6322
|
error: "invalid /policies/check body",
|
|
@@ -6231,8 +6558,8 @@ init_auth();
|
|
|
6231
6558
|
|
|
6232
6559
|
// src/unrouted.ts
|
|
6233
6560
|
init_cjs_shims();
|
|
6234
|
-
var
|
|
6235
|
-
var
|
|
6561
|
+
var import_node_fs24 = require("fs");
|
|
6562
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
6236
6563
|
function buildUnroutedSpanRecord(serviceName, traceId, now = /* @__PURE__ */ new Date()) {
|
|
6237
6564
|
return {
|
|
6238
6565
|
timestamp: now.toISOString(),
|
|
@@ -6242,21 +6569,21 @@ function buildUnroutedSpanRecord(serviceName, traceId, now = /* @__PURE__ */ new
|
|
|
6242
6569
|
};
|
|
6243
6570
|
}
|
|
6244
6571
|
async function appendUnroutedSpan(neatHome3, record) {
|
|
6245
|
-
const target =
|
|
6246
|
-
await
|
|
6247
|
-
await
|
|
6572
|
+
const target = import_node_path40.default.join(neatHome3, "errors.ndjson");
|
|
6573
|
+
await import_node_fs24.promises.mkdir(neatHome3, { recursive: true });
|
|
6574
|
+
await import_node_fs24.promises.appendFile(target, JSON.stringify(record) + "\n", "utf8");
|
|
6248
6575
|
}
|
|
6249
6576
|
function unroutedErrorsPath(neatHome3) {
|
|
6250
|
-
return
|
|
6577
|
+
return import_node_path40.default.join(neatHome3, "errors.ndjson");
|
|
6251
6578
|
}
|
|
6252
6579
|
|
|
6253
6580
|
// src/daemon.ts
|
|
6254
6581
|
function neatHomeFor(opts) {
|
|
6255
|
-
if (opts.neatHome && opts.neatHome.length > 0) return
|
|
6582
|
+
if (opts.neatHome && opts.neatHome.length > 0) return import_node_path41.default.resolve(opts.neatHome);
|
|
6256
6583
|
const env = process.env.NEAT_HOME;
|
|
6257
|
-
if (env && env.length > 0) return
|
|
6584
|
+
if (env && env.length > 0) return import_node_path41.default.resolve(env);
|
|
6258
6585
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
6259
|
-
return
|
|
6586
|
+
return import_node_path41.default.join(home, ".neat");
|
|
6260
6587
|
}
|
|
6261
6588
|
function routeSpanToProject(serviceName, projects) {
|
|
6262
6589
|
if (!serviceName) return DEFAULT_PROJECT;
|
|
@@ -6291,9 +6618,9 @@ function isTokenContained(needle, haystack) {
|
|
|
6291
6618
|
return tokens.includes(needle);
|
|
6292
6619
|
}
|
|
6293
6620
|
async function bootstrapProject(entry2) {
|
|
6294
|
-
const paths = pathsForProject(entry2.name,
|
|
6621
|
+
const paths = pathsForProject(entry2.name, import_node_path41.default.join(entry2.path, "neat-out"));
|
|
6295
6622
|
try {
|
|
6296
|
-
const stat = await
|
|
6623
|
+
const stat = await import_node_fs25.promises.stat(entry2.path);
|
|
6297
6624
|
if (!stat.isDirectory()) {
|
|
6298
6625
|
throw new Error(`registered path ${entry2.path} is not a directory`);
|
|
6299
6626
|
}
|
|
@@ -6359,13 +6686,13 @@ async function startDaemon(opts = {}) {
|
|
|
6359
6686
|
const home = neatHomeFor(opts);
|
|
6360
6687
|
const regPath = registryPath();
|
|
6361
6688
|
try {
|
|
6362
|
-
await
|
|
6689
|
+
await import_node_fs25.promises.access(regPath);
|
|
6363
6690
|
} catch {
|
|
6364
6691
|
throw new Error(
|
|
6365
6692
|
`neatd: registry not found at ${regPath}. Run \`neat init <path>\` to register a project before starting the daemon.`
|
|
6366
6693
|
);
|
|
6367
6694
|
}
|
|
6368
|
-
const pidPath =
|
|
6695
|
+
const pidPath = import_node_path41.default.join(home, "neatd.pid");
|
|
6369
6696
|
await writeAtomically(pidPath, `${process.pid}
|
|
6370
6697
|
`);
|
|
6371
6698
|
const slots = /* @__PURE__ */ new Map();
|
|
@@ -6523,7 +6850,7 @@ async function startDaemon(opts = {}) {
|
|
|
6523
6850
|
}
|
|
6524
6851
|
if (restApp) await restApp.close().catch(() => {
|
|
6525
6852
|
});
|
|
6526
|
-
await
|
|
6853
|
+
await import_node_fs25.promises.unlink(pidPath).catch(() => {
|
|
6527
6854
|
});
|
|
6528
6855
|
throw new Error(
|
|
6529
6856
|
`neatd: failed to bind REST on port ${restPort} \u2014 ${err.message}`
|
|
@@ -6629,7 +6956,7 @@ async function startDaemon(opts = {}) {
|
|
|
6629
6956
|
});
|
|
6630
6957
|
if (otlpApp) await otlpApp.close().catch(() => {
|
|
6631
6958
|
});
|
|
6632
|
-
await
|
|
6959
|
+
await import_node_fs25.promises.unlink(pidPath).catch(() => {
|
|
6633
6960
|
});
|
|
6634
6961
|
throw new Error(
|
|
6635
6962
|
`neatd: failed to bind OTLP on port ${otlpPort} \u2014 ${err.message}`
|
|
@@ -6675,9 +7002,9 @@ async function startDaemon(opts = {}) {
|
|
|
6675
7002
|
let registryWatcher = null;
|
|
6676
7003
|
let reloadTimer = null;
|
|
6677
7004
|
try {
|
|
6678
|
-
const regDir =
|
|
6679
|
-
const regBase =
|
|
6680
|
-
registryWatcher = (0,
|
|
7005
|
+
const regDir = import_node_path41.default.dirname(regPath);
|
|
7006
|
+
const regBase = import_node_path41.default.basename(regPath);
|
|
7007
|
+
registryWatcher = (0, import_node_fs25.watch)(regDir, (_eventType, filename) => {
|
|
6681
7008
|
if (filename !== null && filename !== regBase) return;
|
|
6682
7009
|
if (reloadTimer) clearTimeout(reloadTimer);
|
|
6683
7010
|
reloadTimer = setTimeout(() => {
|
|
@@ -6720,7 +7047,7 @@ async function startDaemon(opts = {}) {
|
|
|
6720
7047
|
} catch {
|
|
6721
7048
|
}
|
|
6722
7049
|
}
|
|
6723
|
-
await
|
|
7050
|
+
await import_node_fs25.promises.unlink(pidPath).catch(() => {
|
|
6724
7051
|
});
|
|
6725
7052
|
};
|
|
6726
7053
|
return {
|
|
@@ -6742,7 +7069,7 @@ init_auth();
|
|
|
6742
7069
|
init_cjs_shims();
|
|
6743
7070
|
var import_node_child_process2 = require("child_process");
|
|
6744
7071
|
var import_node_net = __toESM(require("net"), 1);
|
|
6745
|
-
var
|
|
7072
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
6746
7073
|
var DEFAULT_WEB_PORT = 6328;
|
|
6747
7074
|
async function assertPortFree(port) {
|
|
6748
7075
|
await new Promise((resolve, reject) => {
|
|
@@ -6770,10 +7097,10 @@ function resolveWebPackageDir() {
|
|
|
6770
7097
|
eval("require")
|
|
6771
7098
|
);
|
|
6772
7099
|
const pkgJsonPath = req.resolve("@neat.is/web/package.json");
|
|
6773
|
-
return
|
|
7100
|
+
return import_node_path42.default.dirname(pkgJsonPath);
|
|
6774
7101
|
}
|
|
6775
7102
|
function resolveStandaloneServerEntry(webDir) {
|
|
6776
|
-
return
|
|
7103
|
+
return import_node_path42.default.join(webDir, ".next/standalone/packages/web/server.js");
|
|
6777
7104
|
}
|
|
6778
7105
|
async function spawnWebUI(restPort) {
|
|
6779
7106
|
const portRaw = process.env.NEAT_WEB_PORT;
|
|
@@ -6798,7 +7125,7 @@ async function spawnWebUI(restPort) {
|
|
|
6798
7125
|
NEAT_API_URL: process.env.NEAT_API_URL ?? `http://localhost:${restPort}`
|
|
6799
7126
|
};
|
|
6800
7127
|
const child = (0, import_node_child_process2.spawn)(process.execPath, [serverEntry], {
|
|
6801
|
-
cwd:
|
|
7128
|
+
cwd: import_node_path42.default.dirname(serverEntry),
|
|
6802
7129
|
env,
|
|
6803
7130
|
stdio: ["ignore", "inherit", "inherit"],
|
|
6804
7131
|
detached: false
|
|
@@ -6911,14 +7238,14 @@ function localVersion() {
|
|
|
6911
7238
|
}
|
|
6912
7239
|
function neatHome2() {
|
|
6913
7240
|
if (process.env.NEAT_HOME && process.env.NEAT_HOME.length > 0) {
|
|
6914
|
-
return
|
|
7241
|
+
return import_node_path43.default.resolve(process.env.NEAT_HOME);
|
|
6915
7242
|
}
|
|
6916
7243
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
6917
|
-
return
|
|
7244
|
+
return import_node_path43.default.join(home, ".neat");
|
|
6918
7245
|
}
|
|
6919
7246
|
async function readPid() {
|
|
6920
7247
|
try {
|
|
6921
|
-
const raw = await
|
|
7248
|
+
const raw = await import_node_fs26.promises.readFile(import_node_path43.default.join(neatHome2(), "neatd.pid"), "utf8");
|
|
6922
7249
|
const n = Number.parseInt(raw.trim(), 10);
|
|
6923
7250
|
return Number.isFinite(n) ? n : null;
|
|
6924
7251
|
} catch {
|