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