@neat.is/core 0.7.6 → 0.7.8
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-6H757ZNM.js → chunk-4GCV46AP.js} +2 -2
- package/dist/{chunk-XT4NNFH6.js → chunk-LN75Z624.js} +866 -216
- package/dist/chunk-LN75Z624.js.map +1 -0
- package/dist/{chunk-XHSK4BGL.js → chunk-OVRVDSUO.js} +3 -3
- package/dist/{chunk-P2ZEKJ35.js → chunk-Y43UCVZS.js} +9 -6
- package/dist/chunk-Y43UCVZS.js.map +1 -0
- package/dist/cli.cjs +1244 -590
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +4 -4
- package/dist/index.cjs +1046 -392
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +1055 -401
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-APVZSB6W.js → otel-grpc-DPSAGRUU.js} +3 -3
- package/dist/server.cjs +978 -324
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-P2ZEKJ35.js.map +0 -1
- package/dist/chunk-XT4NNFH6.js.map +0 -1
- /package/dist/{chunk-6H757ZNM.js.map → chunk-4GCV46AP.js.map} +0 -0
- /package/dist/{chunk-XHSK4BGL.js.map → chunk-OVRVDSUO.js.map} +0 -0
- /package/dist/{otel-grpc-APVZSB6W.js.map → otel-grpc-DPSAGRUU.js.map} +0 -0
package/dist/server.cjs
CHANGED
|
@@ -59,8 +59,8 @@ function mountBearerAuth(app, opts) {
|
|
|
59
59
|
]);
|
|
60
60
|
const publicRead = opts.publicRead === true;
|
|
61
61
|
app.addHook("preHandler", (req, reply, done) => {
|
|
62
|
-
const
|
|
63
|
-
if (exactUnauthPaths.has(
|
|
62
|
+
const path68 = (req.url.split("?")[0] ?? "").replace(/\/+$/, "");
|
|
63
|
+
if (exactUnauthPaths.has(path68) || PROJECT_SCOPED_UNAUTH_PATTERN.test(path68)) {
|
|
64
64
|
done();
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
@@ -341,7 +341,7 @@ function pickEnv(spanAttrs, resourceAttrs) {
|
|
|
341
341
|
return ENV_FALLBACK;
|
|
342
342
|
}
|
|
343
343
|
function normalizeDbSystem(attrs) {
|
|
344
|
-
const raw = attrs["db.system"];
|
|
344
|
+
const raw = attrs["db.system"] ?? attrs["db.system.name"];
|
|
345
345
|
if (typeof raw !== "string") return void 0;
|
|
346
346
|
return raw === "mongoose" ? "mongodb" : raw;
|
|
347
347
|
}
|
|
@@ -413,8 +413,8 @@ function websocketChannelPathOf(attrs) {
|
|
|
413
413
|
const v = attrs[key];
|
|
414
414
|
if (typeof v === "string" && v.length > 0) {
|
|
415
415
|
const q = v.indexOf("?");
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
416
|
+
const path68 = q === -1 ? v : v.slice(0, q);
|
|
417
|
+
if (path68.length > 0) return path68;
|
|
418
418
|
}
|
|
419
419
|
}
|
|
420
420
|
return void 0;
|
|
@@ -433,6 +433,9 @@ function parseOtlpRequest(body) {
|
|
|
433
433
|
for (const ss of rs.scopeSpans ?? []) {
|
|
434
434
|
for (const span of ss.spans ?? []) {
|
|
435
435
|
const attrs = attrsToRecord(span.attributes);
|
|
436
|
+
const dbSqlText = typeof attrs["db.statement"] === "string" ? attrs["db.statement"] : typeof attrs["db.query.text"] === "string" ? attrs["db.query.text"] : void 0;
|
|
437
|
+
const dbSystemName = normalizeDbSystem(attrs);
|
|
438
|
+
const directDbTable = typeof attrs["db.sql.table"] === "string" ? attrs["db.sql.table"] : dbSystemName !== "mongodb" && typeof attrs["db.collection.name"] === "string" ? attrs["db.collection.name"] : void 0;
|
|
436
439
|
const parsed = {
|
|
437
440
|
service,
|
|
438
441
|
resourceServiceNamePresent,
|
|
@@ -447,11 +450,11 @@ function parseOtlpRequest(body) {
|
|
|
447
450
|
durationNanos: durationNanos(span.startTimeUnixNano, span.endTimeUnixNano),
|
|
448
451
|
env: pickEnv(attrs, resourceAttrs),
|
|
449
452
|
attributes: attrs,
|
|
450
|
-
dbSystem:
|
|
453
|
+
dbSystem: dbSystemName,
|
|
451
454
|
dbName: typeof attrs["db.name"] === "string" ? attrs["db.name"] : void 0,
|
|
452
455
|
dbCollection: typeof attrs["db.collection.name"] === "string" ? attrs["db.collection.name"] : typeof attrs["db.mongodb.collection"] === "string" ? attrs["db.mongodb.collection"] : void 0,
|
|
453
|
-
dbTable:
|
|
454
|
-
dbColumns:
|
|
456
|
+
dbTable: directDbTable ?? (dbSqlText ? tableFromSqlStatement(dbSqlText) ?? void 0 : void 0),
|
|
457
|
+
dbColumns: dbSqlText ? columnsFromSqlStatement(dbSqlText) : void 0,
|
|
455
458
|
httpRoute: typeof attrs["http.route"] === "string" ? attrs["http.route"] : void 0,
|
|
456
459
|
httpMethod: typeof attrs["http.request.method"] === "string" ? attrs["http.request.method"] : typeof attrs["http.method"] === "string" ? attrs["http.method"] : void 0,
|
|
457
460
|
messagingSystem: typeof attrs["messaging.system"] === "string" ? attrs["messaging.system"] : void 0,
|
|
@@ -712,7 +715,7 @@ var init_otel = __esm({
|
|
|
712
715
|
|
|
713
716
|
// src/server.ts
|
|
714
717
|
init_cjs_shims();
|
|
715
|
-
var
|
|
718
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
716
719
|
|
|
717
720
|
// src/graph.ts
|
|
718
721
|
init_cjs_shims();
|
|
@@ -736,7 +739,7 @@ function getGraph(project = DEFAULT_PROJECT) {
|
|
|
736
739
|
init_cjs_shims();
|
|
737
740
|
var import_fastify2 = __toESM(require("fastify"), 1);
|
|
738
741
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
739
|
-
var
|
|
742
|
+
var import_types80 = require("@neat.is/types");
|
|
740
743
|
|
|
741
744
|
// src/extend/index.ts
|
|
742
745
|
init_cjs_shims();
|
|
@@ -848,12 +851,12 @@ var HOOK_WALK_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
848
851
|
]);
|
|
849
852
|
async function findHookFiles(scanPath) {
|
|
850
853
|
const found = [];
|
|
851
|
-
const
|
|
854
|
+
const walk9 = async (dir) => {
|
|
852
855
|
const entries = await import_node_fs2.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
853
856
|
for (const entry of entries) {
|
|
854
857
|
if (entry.isDirectory()) {
|
|
855
858
|
if (entry.name.startsWith(".") || HOOK_WALK_SKIP_DIRS.has(entry.name)) continue;
|
|
856
|
-
await
|
|
859
|
+
await walk9(import_node_path2.default.join(dir, entry.name));
|
|
857
860
|
} else if (entry.isFile()) {
|
|
858
861
|
if ((entry.name.startsWith("instrumentation") || entry.name.startsWith("otel-init")) && /\.(ts|js|cjs|mjs)$/.test(entry.name)) {
|
|
859
862
|
const rel = import_node_path2.default.relative(scanPath, import_node_path2.default.join(dir, entry.name));
|
|
@@ -862,7 +865,7 @@ async function findHookFiles(scanPath) {
|
|
|
862
865
|
}
|
|
863
866
|
}
|
|
864
867
|
};
|
|
865
|
-
await
|
|
868
|
+
await walk9(scanPath);
|
|
866
869
|
return found.sort();
|
|
867
870
|
}
|
|
868
871
|
async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
|
|
@@ -2265,14 +2268,14 @@ function buildServiceHostIndex(services) {
|
|
|
2265
2268
|
}
|
|
2266
2269
|
async function walkSourceFiles(dir) {
|
|
2267
2270
|
const out = [];
|
|
2268
|
-
async function
|
|
2271
|
+
async function walk9(current) {
|
|
2269
2272
|
const entries = await import_node_fs7.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
2270
2273
|
for (const entry of entries) {
|
|
2271
2274
|
const full = import_node_path7.default.join(current, entry.name);
|
|
2272
2275
|
if (entry.isDirectory()) {
|
|
2273
2276
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
2274
2277
|
if (await isPythonVenvDir(full)) continue;
|
|
2275
|
-
await
|
|
2278
|
+
await walk9(full);
|
|
2276
2279
|
} else if (entry.isFile() && SERVICE_FILE_EXTENSIONS.has(import_node_path7.default.extname(entry.name)) && // Skip NEAT's own generated `otel-init.*` bootstrap — extracting it
|
|
2277
2280
|
// would attribute our instrumentation imports to the user's service.
|
|
2278
2281
|
!isNeatAuthoredSourceFile(entry.name)) {
|
|
@@ -2280,7 +2283,7 @@ async function walkSourceFiles(dir) {
|
|
|
2280
2283
|
}
|
|
2281
2284
|
}
|
|
2282
2285
|
}
|
|
2283
|
-
await
|
|
2286
|
+
await walk9(dir);
|
|
2284
2287
|
return out;
|
|
2285
2288
|
}
|
|
2286
2289
|
async function loadSourceFiles(dir) {
|
|
@@ -2793,8 +2796,9 @@ var ROUTER_METHODS = /* @__PURE__ */ new Set([
|
|
|
2793
2796
|
"all"
|
|
2794
2797
|
]);
|
|
2795
2798
|
var NEXT_APP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
2799
|
+
var NET_HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
2796
2800
|
var JS_ROUTE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx"]);
|
|
2797
|
-
function
|
|
2801
|
+
function goRouterRoutesFromSource(source, parser, framework) {
|
|
2798
2802
|
const tree = parseSource2(parser, source);
|
|
2799
2803
|
const prefixes = /* @__PURE__ */ new Map();
|
|
2800
2804
|
const out = [];
|
|
@@ -2804,10 +2808,12 @@ function ginRoutesFromSource(source, parser) {
|
|
|
2804
2808
|
const value = node.childForFieldName("right")?.namedChild(0) ?? node.childForFieldName("value");
|
|
2805
2809
|
if (name && value?.type === "call_expression") {
|
|
2806
2810
|
const fn2 = value.childForFieldName("function");
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
+
if (fn2?.childForFieldName("field")?.text === "Group") {
|
|
2812
|
+
const leaf2 = goStringLiteral(value.childForFieldName("arguments")?.namedChild(0));
|
|
2813
|
+
if (leaf2 !== null) {
|
|
2814
|
+
const parent = fn2.childForFieldName("operand")?.text ?? "";
|
|
2815
|
+
prefixes.set(name, (prefixes.get(parent) ?? "") + leaf2);
|
|
2816
|
+
}
|
|
2811
2817
|
}
|
|
2812
2818
|
}
|
|
2813
2819
|
return;
|
|
@@ -2818,18 +2824,127 @@ function ginRoutesFromSource(source, parser) {
|
|
|
2818
2824
|
const method = fn.childForFieldName("field")?.text?.toUpperCase();
|
|
2819
2825
|
if (!method || !ROUTER_METHODS.has(method.toLowerCase())) return;
|
|
2820
2826
|
const receiver = fn.childForFieldName("operand")?.text ?? "";
|
|
2821
|
-
const
|
|
2822
|
-
if (
|
|
2823
|
-
const leaf = first.text.slice(1, -1);
|
|
2827
|
+
const leaf = goStringLiteral(node.childForFieldName("arguments")?.namedChild(0));
|
|
2828
|
+
if (leaf === null) return;
|
|
2824
2829
|
out.push({
|
|
2825
|
-
method
|
|
2830
|
+
method,
|
|
2826
2831
|
pathTemplate: canonicalizeTemplate((prefixes.get(receiver) ?? "") + leaf),
|
|
2827
2832
|
line: node.startPosition.row + 1,
|
|
2828
|
-
framework
|
|
2833
|
+
framework
|
|
2829
2834
|
});
|
|
2830
2835
|
});
|
|
2831
2836
|
return out;
|
|
2832
2837
|
}
|
|
2838
|
+
function goStringLiteral(node) {
|
|
2839
|
+
if (node?.type === "interpreted_string_literal" || node?.type === "raw_string_literal") {
|
|
2840
|
+
return node.text.slice(1, -1);
|
|
2841
|
+
}
|
|
2842
|
+
return null;
|
|
2843
|
+
}
|
|
2844
|
+
function ginRoutesFromSource(source, parser) {
|
|
2845
|
+
return goRouterRoutesFromSource(source, parser, "gin");
|
|
2846
|
+
}
|
|
2847
|
+
function echoRoutesFromSource(source, parser) {
|
|
2848
|
+
return goRouterRoutesFromSource(source, parser, "echo");
|
|
2849
|
+
}
|
|
2850
|
+
function fiberRoutesFromSource(source, parser) {
|
|
2851
|
+
return goRouterRoutesFromSource(source, parser, "fiber");
|
|
2852
|
+
}
|
|
2853
|
+
function chiRoutesFromSource(source, parser) {
|
|
2854
|
+
const tree = parseSource2(parser, source);
|
|
2855
|
+
const out = [];
|
|
2856
|
+
chiWalk(tree.rootNode, "", out);
|
|
2857
|
+
return out;
|
|
2858
|
+
}
|
|
2859
|
+
function stripChiRegex(path68) {
|
|
2860
|
+
return path68.replace(/\{([^{}:]+):[^{}]*\}/g, "{$1}");
|
|
2861
|
+
}
|
|
2862
|
+
function chiWalk(node, prefix, out) {
|
|
2863
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
2864
|
+
const child = node.namedChild(i);
|
|
2865
|
+
if (child) chiHandle(child, prefix, out);
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
function chiHandle(node, prefix, out) {
|
|
2869
|
+
if (node.type === "call_expression") {
|
|
2870
|
+
const fn = node.childForFieldName("function");
|
|
2871
|
+
if (fn?.type === "selector_expression") {
|
|
2872
|
+
const field = fn.childForFieldName("field")?.text;
|
|
2873
|
+
const args = node.childForFieldName("arguments");
|
|
2874
|
+
if (field === "Route") {
|
|
2875
|
+
const leaf = goStringLiteral(args?.namedChild(0));
|
|
2876
|
+
const closure = args?.namedChild(1);
|
|
2877
|
+
if (leaf !== null && closure?.type === "func_literal") {
|
|
2878
|
+
const body = closure.childForFieldName("body");
|
|
2879
|
+
if (body) chiWalk(body, prefix + leaf, out);
|
|
2880
|
+
}
|
|
2881
|
+
return;
|
|
2882
|
+
}
|
|
2883
|
+
if (field === "Group") {
|
|
2884
|
+
const closure = args?.namedChild(0);
|
|
2885
|
+
if (closure?.type === "func_literal") {
|
|
2886
|
+
const body = closure.childForFieldName("body");
|
|
2887
|
+
if (body) chiWalk(body, prefix, out);
|
|
2888
|
+
}
|
|
2889
|
+
return;
|
|
2890
|
+
}
|
|
2891
|
+
if (field === "Mount") {
|
|
2892
|
+
return;
|
|
2893
|
+
}
|
|
2894
|
+
if (field && ROUTER_METHODS.has(field.toLowerCase())) {
|
|
2895
|
+
const leaf = goStringLiteral(args?.namedChild(0));
|
|
2896
|
+
if (leaf !== null) {
|
|
2897
|
+
out.push({
|
|
2898
|
+
method: field.toUpperCase(),
|
|
2899
|
+
pathTemplate: canonicalizeTemplate(stripChiRegex(prefix + leaf)),
|
|
2900
|
+
line: node.startPosition.row + 1,
|
|
2901
|
+
framework: "chi"
|
|
2902
|
+
});
|
|
2903
|
+
}
|
|
2904
|
+
return;
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
chiWalk(node, prefix, out);
|
|
2909
|
+
}
|
|
2910
|
+
function netHttpRoutesFromSource(source, parser) {
|
|
2911
|
+
const tree = parseSource2(parser, source);
|
|
2912
|
+
if (!goImportsNetHttp(tree.rootNode)) return [];
|
|
2913
|
+
const out = [];
|
|
2914
|
+
walk(tree.rootNode, (node) => {
|
|
2915
|
+
if (node.type !== "call_expression") return;
|
|
2916
|
+
const fn = node.childForFieldName("function");
|
|
2917
|
+
if (fn?.type !== "selector_expression") return;
|
|
2918
|
+
const field = fn.childForFieldName("field")?.text;
|
|
2919
|
+
if (field !== "HandleFunc" && field !== "Handle") return;
|
|
2920
|
+
const leaf = goStringLiteral(node.childForFieldName("arguments")?.namedChild(0));
|
|
2921
|
+
if (leaf === null) return;
|
|
2922
|
+
const sp = leaf.indexOf(" ");
|
|
2923
|
+
if (sp < 0) return;
|
|
2924
|
+
const method = leaf.slice(0, sp);
|
|
2925
|
+
const rest = leaf.slice(sp + 1);
|
|
2926
|
+
if (!NET_HTTP_METHODS.has(method)) return;
|
|
2927
|
+
if (!rest.startsWith("/")) return;
|
|
2928
|
+
out.push({
|
|
2929
|
+
method,
|
|
2930
|
+
pathTemplate: canonicalizeTemplate(rest),
|
|
2931
|
+
line: node.startPosition.row + 1,
|
|
2932
|
+
framework: "net/http"
|
|
2933
|
+
});
|
|
2934
|
+
});
|
|
2935
|
+
return out;
|
|
2936
|
+
}
|
|
2937
|
+
function goImportsNetHttp(root) {
|
|
2938
|
+
let found = false;
|
|
2939
|
+
walk(root, (node) => {
|
|
2940
|
+
if (found || node.type !== "import_spec") return;
|
|
2941
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
2942
|
+
const child = node.namedChild(i);
|
|
2943
|
+
if (goStringLiteral(child) === "net/http") found = true;
|
|
2944
|
+
}
|
|
2945
|
+
});
|
|
2946
|
+
return found;
|
|
2947
|
+
}
|
|
2833
2948
|
var FASTAPI_METHODS = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete", "options", "head", "trace"]);
|
|
2834
2949
|
var NESTJS_METHODS = /* @__PURE__ */ new Map([
|
|
2835
2950
|
["Get", "GET"],
|
|
@@ -3414,9 +3529,9 @@ function rubyRocketRoute(args) {
|
|
|
3414
3529
|
if (!pair || pair.type !== "pair") continue;
|
|
3415
3530
|
const k = pair.childForFieldName("key");
|
|
3416
3531
|
if (k?.type !== "string") continue;
|
|
3417
|
-
const
|
|
3418
|
-
if (
|
|
3419
|
-
return { path:
|
|
3532
|
+
const path68 = rubyLiteral(k);
|
|
3533
|
+
if (path68 === null) continue;
|
|
3534
|
+
return { path: path68, target: rubyLiteral(pair.childForFieldName("value")) };
|
|
3420
3535
|
}
|
|
3421
3536
|
return null;
|
|
3422
3537
|
}
|
|
@@ -4093,9 +4208,13 @@ async function addRoutes(graph, services) {
|
|
|
4093
4208
|
const hasFlask = deps["flask"] !== void 0;
|
|
4094
4209
|
const hasDjango = deps["django"] !== void 0;
|
|
4095
4210
|
const hasGin = deps["github.com/gin-gonic/gin"] !== void 0;
|
|
4211
|
+
const hasEcho = deps["github.com/labstack/echo/v4"] !== void 0 || deps["github.com/labstack/echo"] !== void 0;
|
|
4212
|
+
const hasFiber = deps["github.com/gofiber/fiber/v2"] !== void 0 || deps["github.com/gofiber/fiber/v3"] !== void 0;
|
|
4213
|
+
const hasChi = deps["github.com/go-chi/chi/v5"] !== void 0 || deps["github.com/go-chi/chi"] !== void 0;
|
|
4214
|
+
const isGoService = service.node.language === "go";
|
|
4096
4215
|
const hasRails = deps["rails"] !== void 0;
|
|
4097
4216
|
const hasLaravel = deps["laravel/framework"] !== void 0;
|
|
4098
|
-
if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasNestjs && !hasFastapi && !hasFlask && !hasDjango && !hasGin && !hasRails && !hasLaravel)
|
|
4217
|
+
if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasNestjs && !hasFastapi && !hasFlask && !hasDjango && !hasGin && !hasEcho && !hasFiber && !hasChi && !isGoService && !hasRails && !hasLaravel)
|
|
4099
4218
|
continue;
|
|
4100
4219
|
const files = await loadSourceFiles(service.dir);
|
|
4101
4220
|
const mountPrefixes = hasExpress ? await expressMountPrefixes(files, service.dir, await loadTsPathConfig(service.dir)) : /* @__PURE__ */ new Map();
|
|
@@ -4119,7 +4238,12 @@ async function addRoutes(graph, services) {
|
|
|
4119
4238
|
} else if (isRb) {
|
|
4120
4239
|
routes = hasRails && relFile === "config/routes.rb" ? railsRoutesFromSource(file.content, rubyParser) : [];
|
|
4121
4240
|
} else if (isGo) {
|
|
4122
|
-
routes =
|
|
4241
|
+
if (hasGin) routes = ginRoutesFromSource(file.content, goParser);
|
|
4242
|
+
else if (hasEcho) routes = echoRoutesFromSource(file.content, goParser);
|
|
4243
|
+
else if (hasFiber) routes = fiberRoutesFromSource(file.content, goParser);
|
|
4244
|
+
else if (hasChi) routes = chiRoutesFromSource(file.content, goParser);
|
|
4245
|
+
else routes = [];
|
|
4246
|
+
routes = routes.concat(netHttpRoutesFromSource(file.content, goParser));
|
|
4123
4247
|
} else if (isPy) {
|
|
4124
4248
|
routes = hasFastapi || hasFlask ? pythonRoutesFromSource(file.content, pyParser, hasFastapi ? "fastapi" : "flask") : [];
|
|
4125
4249
|
if (hasDjango) routes = routes.concat(djangoRoutesFromSource(file.content, pyParser));
|
|
@@ -5669,19 +5793,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
5669
5793
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
5670
5794
|
let best = { path: [start], edges: [] };
|
|
5671
5795
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
5672
|
-
function step(node,
|
|
5673
|
-
if (
|
|
5674
|
-
best = { path: [...
|
|
5796
|
+
function step(node, path68, edges) {
|
|
5797
|
+
if (path68.length > best.path.length) {
|
|
5798
|
+
best = { path: [...path68], edges: [...edges] };
|
|
5675
5799
|
}
|
|
5676
|
-
if (
|
|
5800
|
+
if (path68.length - 1 >= maxDepth) return;
|
|
5677
5801
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
5678
5802
|
for (const [srcId, edge] of incoming) {
|
|
5679
5803
|
if (visited.has(srcId)) continue;
|
|
5680
5804
|
visited.add(srcId);
|
|
5681
|
-
|
|
5805
|
+
path68.push(srcId);
|
|
5682
5806
|
edges.push(edge);
|
|
5683
|
-
step(srcId,
|
|
5684
|
-
|
|
5807
|
+
step(srcId, path68, edges);
|
|
5808
|
+
path68.pop();
|
|
5685
5809
|
edges.pop();
|
|
5686
5810
|
visited.delete(srcId);
|
|
5687
5811
|
}
|
|
@@ -5689,11 +5813,11 @@ function longestIncomingWalk(graph, start, maxDepth) {
|
|
|
5689
5813
|
step(start, [start], []);
|
|
5690
5814
|
return best;
|
|
5691
5815
|
}
|
|
5692
|
-
function databaseRootCauseShape(graph, origin,
|
|
5816
|
+
function databaseRootCauseShape(graph, origin, walk9) {
|
|
5693
5817
|
const targetDb = origin;
|
|
5694
5818
|
const candidatePairs = compatPairs().filter((p) => p.engine === targetDb.engine);
|
|
5695
5819
|
if (candidatePairs.length === 0) return null;
|
|
5696
|
-
for (const id of
|
|
5820
|
+
for (const id of walk9.path) {
|
|
5697
5821
|
const owner = resolveOwningService(graph, id);
|
|
5698
5822
|
if (!owner) continue;
|
|
5699
5823
|
const { id: serviceId9, svc } = owner;
|
|
@@ -5720,8 +5844,8 @@ function databaseRootCauseShape(graph, origin, walk8) {
|
|
|
5720
5844
|
}
|
|
5721
5845
|
return null;
|
|
5722
5846
|
}
|
|
5723
|
-
function serviceRootCauseShape(graph, _origin,
|
|
5724
|
-
for (const id of
|
|
5847
|
+
function serviceRootCauseShape(graph, _origin, walk9) {
|
|
5848
|
+
for (const id of walk9.path) {
|
|
5725
5849
|
const owner = resolveOwningService(graph, id);
|
|
5726
5850
|
if (!owner) continue;
|
|
5727
5851
|
const { id: serviceId9, svc } = owner;
|
|
@@ -5757,15 +5881,15 @@ function serviceRootCauseShape(graph, _origin, walk8) {
|
|
|
5757
5881
|
}
|
|
5758
5882
|
return null;
|
|
5759
5883
|
}
|
|
5760
|
-
function fileRootCauseShape(graph, origin,
|
|
5884
|
+
function fileRootCauseShape(graph, origin, walk9) {
|
|
5761
5885
|
const owner = resolveOwningService(graph, origin.id);
|
|
5762
5886
|
if (!owner) return null;
|
|
5763
|
-
return serviceRootCauseShape(graph, owner.svc,
|
|
5887
|
+
return serviceRootCauseShape(graph, owner.svc, walk9);
|
|
5764
5888
|
}
|
|
5765
|
-
function symbolRootCauseShape(graph, origin,
|
|
5889
|
+
function symbolRootCauseShape(graph, origin, walk9) {
|
|
5766
5890
|
const owner = resolveOwningService(graph, origin.id);
|
|
5767
5891
|
if (!owner) return null;
|
|
5768
|
-
return serviceRootCauseShape(graph, owner.svc,
|
|
5892
|
+
return serviceRootCauseShape(graph, owner.svc, walk9);
|
|
5769
5893
|
}
|
|
5770
5894
|
var rootCauseShapes = {
|
|
5771
5895
|
[import_types8.NodeType.DatabaseNode]: databaseRootCauseShape,
|
|
@@ -5778,16 +5902,16 @@ function getRootCause(graph, errorNodeId, errorEvent, incidents) {
|
|
|
5778
5902
|
const origin = graph.getNodeAttributes(errorNodeId);
|
|
5779
5903
|
const shape = rootCauseShapes[origin.type];
|
|
5780
5904
|
if (shape) {
|
|
5781
|
-
const
|
|
5782
|
-
const match = shape(graph, origin,
|
|
5905
|
+
const walk9 = longestIncomingWalk(graph, errorNodeId, ROOT_CAUSE_MAX_DEPTH);
|
|
5906
|
+
const match = shape(graph, origin, walk9);
|
|
5783
5907
|
if (match) {
|
|
5784
5908
|
const reason = errorEvent ? `${match.rootCauseReason} (observed error: ${errorEvent.errorMessage})` : match.rootCauseReason;
|
|
5785
5909
|
return import_types8.RootCauseResultSchema.parse({
|
|
5786
5910
|
rootCauseNode: match.rootCauseNode,
|
|
5787
5911
|
rootCauseReason: reason,
|
|
5788
|
-
traversalPath:
|
|
5789
|
-
edgeProvenances:
|
|
5790
|
-
confidence: confidenceFromMix(
|
|
5912
|
+
traversalPath: walk9.path,
|
|
5913
|
+
edgeProvenances: walk9.edges.map((e) => e.provenance),
|
|
5914
|
+
confidence: confidenceFromMix(walk9.edges),
|
|
5791
5915
|
fixRecommendation: match.fixRecommendation
|
|
5792
5916
|
});
|
|
5793
5917
|
}
|
|
@@ -5888,26 +6012,26 @@ function dominantFailingCall(graph, serviceId9, visited) {
|
|
|
5888
6012
|
return best;
|
|
5889
6013
|
}
|
|
5890
6014
|
function followFailingCallChain(graph, originServiceId, maxDepth) {
|
|
5891
|
-
const
|
|
6015
|
+
const path68 = [originServiceId];
|
|
5892
6016
|
const edges = [];
|
|
5893
6017
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
5894
6018
|
let current = originServiceId;
|
|
5895
6019
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
5896
6020
|
const hop = dominantFailingCall(graph, current, visited);
|
|
5897
6021
|
if (!hop) break;
|
|
5898
|
-
|
|
6022
|
+
path68.push(hop.nextService);
|
|
5899
6023
|
edges.push(hop.edge);
|
|
5900
6024
|
visited.add(hop.nextService);
|
|
5901
6025
|
current = hop.nextService;
|
|
5902
6026
|
}
|
|
5903
6027
|
if (edges.length === 0) return null;
|
|
5904
|
-
return { path:
|
|
6028
|
+
return { path: path68, edges, culprit: current };
|
|
5905
6029
|
}
|
|
5906
6030
|
function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
5907
6031
|
const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
|
|
5908
6032
|
if (!chain) return null;
|
|
5909
6033
|
const culprit = chain.culprit;
|
|
5910
|
-
const
|
|
6034
|
+
const path68 = [...chain.path];
|
|
5911
6035
|
const edgeProvenances = chain.edges.map((e) => e.provenance);
|
|
5912
6036
|
const baseConfidence = confidenceFromMix(chain.edges);
|
|
5913
6037
|
const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
|
|
@@ -5915,14 +6039,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
5915
6039
|
if (loc) {
|
|
5916
6040
|
let rootCauseNode = culprit;
|
|
5917
6041
|
if (loc.fileNode) {
|
|
5918
|
-
|
|
6042
|
+
path68.push(loc.fileNode);
|
|
5919
6043
|
edgeProvenances.push(import_types8.Provenance.OBSERVED);
|
|
5920
6044
|
rootCauseNode = loc.fileNode;
|
|
5921
6045
|
}
|
|
5922
6046
|
return import_types8.RootCauseResultSchema.parse({
|
|
5923
6047
|
rootCauseNode,
|
|
5924
6048
|
rootCauseReason: loc.rootCauseReason,
|
|
5925
|
-
traversalPath:
|
|
6049
|
+
traversalPath: path68,
|
|
5926
6050
|
edgeProvenances,
|
|
5927
6051
|
confidence,
|
|
5928
6052
|
...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
|
|
@@ -5934,7 +6058,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
5934
6058
|
return import_types8.RootCauseResultSchema.parse({
|
|
5935
6059
|
rootCauseNode: culprit,
|
|
5936
6060
|
rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
|
|
5937
|
-
traversalPath:
|
|
6061
|
+
traversalPath: path68,
|
|
5938
6062
|
edgeProvenances,
|
|
5939
6063
|
confidence,
|
|
5940
6064
|
fixRecommendation: `Inspect ${culpritName}'s failing handler`
|
|
@@ -6557,6 +6681,13 @@ function parseGoMod(source) {
|
|
|
6557
6681
|
}
|
|
6558
6682
|
return { module: module2, ...goVersion ? { goVersion } : {}, dependencies };
|
|
6559
6683
|
}
|
|
6684
|
+
function goFramework(deps) {
|
|
6685
|
+
if (deps["github.com/gin-gonic/gin"]) return "gin";
|
|
6686
|
+
if (deps["github.com/labstack/echo/v4"] || deps["github.com/labstack/echo"]) return "echo";
|
|
6687
|
+
if (deps["github.com/gofiber/fiber/v2"] || deps["github.com/gofiber/fiber/v3"]) return "fiber";
|
|
6688
|
+
if (deps["github.com/go-chi/chi/v5"] || deps["github.com/go-chi/chi"]) return "chi";
|
|
6689
|
+
return void 0;
|
|
6690
|
+
}
|
|
6560
6691
|
async function discoverGoService(scanPath, dir) {
|
|
6561
6692
|
let raw;
|
|
6562
6693
|
try {
|
|
@@ -6568,6 +6699,7 @@ async function discoverGoService(scanPath, dir) {
|
|
|
6568
6699
|
if (!mod) return null;
|
|
6569
6700
|
const name = mod.module.split("/").filter(Boolean).pop() ?? mod.module;
|
|
6570
6701
|
const pkg = { name, dependencies: mod.dependencies };
|
|
6702
|
+
const framework = goFramework(mod.dependencies);
|
|
6571
6703
|
const node = {
|
|
6572
6704
|
id: (0, import_types10.serviceId)(name),
|
|
6573
6705
|
type: import_types10.NodeType.ServiceNode,
|
|
@@ -6575,7 +6707,7 @@ async function discoverGoService(scanPath, dir) {
|
|
|
6575
6707
|
language: "go",
|
|
6576
6708
|
dependencies: mod.dependencies,
|
|
6577
6709
|
repoPath: import_node_path12.default.relative(scanPath, dir),
|
|
6578
|
-
...
|
|
6710
|
+
...framework ? { framework } : {}
|
|
6579
6711
|
};
|
|
6580
6712
|
return { pkg, dir, node };
|
|
6581
6713
|
}
|
|
@@ -7475,7 +7607,7 @@ async function addSymbolEdges(graph, services) {
|
|
|
7475
7607
|
return best;
|
|
7476
7608
|
};
|
|
7477
7609
|
const requests = [];
|
|
7478
|
-
const
|
|
7610
|
+
const walk9 = (node) => {
|
|
7479
7611
|
if (node.type === "class_declaration" || node.type === "abstract_class_declaration" || node.type === "class") {
|
|
7480
7612
|
const self = localBySpan.get(`${node.startPosition.row + 1}:${node.endPosition.row + 1}`);
|
|
7481
7613
|
if (self && self.kind === "class") {
|
|
@@ -7521,10 +7653,10 @@ async function addSymbolEdges(graph, services) {
|
|
|
7521
7653
|
}
|
|
7522
7654
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
7523
7655
|
const child = node.namedChild(i);
|
|
7524
|
-
if (child)
|
|
7656
|
+
if (child) walk9(child);
|
|
7525
7657
|
}
|
|
7526
7658
|
};
|
|
7527
|
-
|
|
7659
|
+
walk9(root);
|
|
7528
7660
|
for (const req of requests) {
|
|
7529
7661
|
const targetSid = resolveTarget(req.targetName, req.wantKind);
|
|
7530
7662
|
if (!targetSid) continue;
|
|
@@ -8537,20 +8669,20 @@ var import_node_path30 = __toESM(require("path"), 1);
|
|
|
8537
8669
|
var import_types19 = require("@neat.is/types");
|
|
8538
8670
|
async function walkConfigFiles(dir) {
|
|
8539
8671
|
const out = [];
|
|
8540
|
-
async function
|
|
8672
|
+
async function walk9(current) {
|
|
8541
8673
|
const entries = await import_node_fs18.promises.readdir(current, { withFileTypes: true });
|
|
8542
8674
|
for (const entry of entries) {
|
|
8543
8675
|
const full = import_node_path30.default.join(current, entry.name);
|
|
8544
8676
|
if (entry.isDirectory()) {
|
|
8545
8677
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
8546
8678
|
if (await isPythonVenvDir(full)) continue;
|
|
8547
|
-
await
|
|
8679
|
+
await walk9(full);
|
|
8548
8680
|
} else if (entry.isFile() && isConfigFile(entry.name).match) {
|
|
8549
8681
|
out.push(full);
|
|
8550
8682
|
}
|
|
8551
8683
|
}
|
|
8552
8684
|
}
|
|
8553
|
-
await
|
|
8685
|
+
await walk9(dir);
|
|
8554
8686
|
return out;
|
|
8555
8687
|
}
|
|
8556
8688
|
async function addConfigNodes(graph, services, scanPath) {
|
|
@@ -8640,20 +8772,20 @@ function grpcMethodsFromProto(content, fqPackage) {
|
|
|
8640
8772
|
}
|
|
8641
8773
|
async function walkProtoFiles(dir) {
|
|
8642
8774
|
const out = [];
|
|
8643
|
-
async function
|
|
8775
|
+
async function walk9(current) {
|
|
8644
8776
|
const entries = await import_node_fs19.promises.readdir(current, { withFileTypes: true }).catch(() => []);
|
|
8645
8777
|
for (const entry of entries) {
|
|
8646
8778
|
const full = import_node_path31.default.join(current, entry.name);
|
|
8647
8779
|
if (entry.isDirectory()) {
|
|
8648
8780
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
8649
8781
|
if (await isPythonVenvDir(full)) continue;
|
|
8650
|
-
await
|
|
8782
|
+
await walk9(full);
|
|
8651
8783
|
} else if (entry.isFile() && import_node_path31.default.extname(entry.name) === PROTO_EXTENSION) {
|
|
8652
8784
|
out.push(full);
|
|
8653
8785
|
}
|
|
8654
8786
|
}
|
|
8655
8787
|
}
|
|
8656
|
-
await
|
|
8788
|
+
await walk9(dir);
|
|
8657
8789
|
return out;
|
|
8658
8790
|
}
|
|
8659
8791
|
async function addGrpcMethods(graph, services) {
|
|
@@ -8721,7 +8853,7 @@ async function addGrpcMethods(graph, services) {
|
|
|
8721
8853
|
|
|
8722
8854
|
// src/extract/calls/index.ts
|
|
8723
8855
|
init_cjs_shims();
|
|
8724
|
-
var
|
|
8856
|
+
var import_types38 = require("@neat.is/types");
|
|
8725
8857
|
|
|
8726
8858
|
// src/extract/calls/http.ts
|
|
8727
8859
|
init_cjs_shims();
|
|
@@ -9475,7 +9607,7 @@ function isFirestoreClientFactory(node) {
|
|
|
9475
9607
|
}
|
|
9476
9608
|
function firestoreClientVars(root) {
|
|
9477
9609
|
const vars = /* @__PURE__ */ new Set();
|
|
9478
|
-
const
|
|
9610
|
+
const walk9 = (node) => {
|
|
9479
9611
|
if (node.type === "variable_declarator") {
|
|
9480
9612
|
const name = node.childForFieldName("name");
|
|
9481
9613
|
let value = node.childForFieldName("value");
|
|
@@ -9484,9 +9616,9 @@ function firestoreClientVars(root) {
|
|
|
9484
9616
|
vars.add(name.text);
|
|
9485
9617
|
}
|
|
9486
9618
|
}
|
|
9487
|
-
for (const c of namedChildren(node))
|
|
9619
|
+
for (const c of namedChildren(node)) walk9(c);
|
|
9488
9620
|
};
|
|
9489
|
-
|
|
9621
|
+
walk9(root);
|
|
9490
9622
|
return vars;
|
|
9491
9623
|
}
|
|
9492
9624
|
function isClientExpr(node, clientVars) {
|
|
@@ -9641,7 +9773,7 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
9641
9773
|
}
|
|
9642
9774
|
s.add(field);
|
|
9643
9775
|
};
|
|
9644
|
-
const
|
|
9776
|
+
const walk9 = (node) => {
|
|
9645
9777
|
if (node.type === "call_expression") {
|
|
9646
9778
|
const fn = node.childForFieldName("function");
|
|
9647
9779
|
const line = node.startPosition.row + 1;
|
|
@@ -9681,9 +9813,9 @@ function firestoreEndpointsFromFile(file, serviceDir) {
|
|
|
9681
9813
|
}
|
|
9682
9814
|
}
|
|
9683
9815
|
}
|
|
9684
|
-
for (const c of namedChildren(node))
|
|
9816
|
+
for (const c of namedChildren(node)) walk9(c);
|
|
9685
9817
|
};
|
|
9686
|
-
|
|
9818
|
+
walk9(tree.rootNode);
|
|
9687
9819
|
const out = [];
|
|
9688
9820
|
for (const [collPath, line] of collLine) {
|
|
9689
9821
|
const byField = writes.get(collPath);
|
|
@@ -10478,7 +10610,7 @@ function drizzleEndpointsFromFile(file, serviceDir) {
|
|
|
10478
10610
|
const tree = parseSource3(parserForExt2(import_node_path43.default.extname(file.path)), file.content);
|
|
10479
10611
|
const out = [];
|
|
10480
10612
|
const seen = /* @__PURE__ */ new Set();
|
|
10481
|
-
const
|
|
10613
|
+
const walk9 = (node) => {
|
|
10482
10614
|
if (node.type === "call_expression") {
|
|
10483
10615
|
const fn = node.childForFieldName("function");
|
|
10484
10616
|
if (fn?.type === "identifier" && TABLE_BUILDERS.has(fn.text)) {
|
|
@@ -10506,9 +10638,9 @@ function drizzleEndpointsFromFile(file, serviceDir) {
|
|
|
10506
10638
|
}
|
|
10507
10639
|
}
|
|
10508
10640
|
}
|
|
10509
|
-
for (const c of namedChildren4(node))
|
|
10641
|
+
for (const c of namedChildren4(node)) walk9(c);
|
|
10510
10642
|
};
|
|
10511
|
-
|
|
10643
|
+
walk9(tree.rootNode);
|
|
10512
10644
|
return out;
|
|
10513
10645
|
}
|
|
10514
10646
|
function enclosingVarName(call) {
|
|
@@ -10530,7 +10662,7 @@ function enclosingVarName(call) {
|
|
|
10530
10662
|
function collectDrizzleTables(root) {
|
|
10531
10663
|
const tables = [];
|
|
10532
10664
|
const varToTable = /* @__PURE__ */ new Map();
|
|
10533
|
-
const
|
|
10665
|
+
const walk9 = (node) => {
|
|
10534
10666
|
if (node.type === "call_expression") {
|
|
10535
10667
|
const fn = node.childForFieldName("function");
|
|
10536
10668
|
if (fn?.type === "identifier" && TABLE_BUILDERS.has(fn.text)) {
|
|
@@ -10545,9 +10677,9 @@ function collectDrizzleTables(root) {
|
|
|
10545
10677
|
}
|
|
10546
10678
|
}
|
|
10547
10679
|
}
|
|
10548
|
-
for (const c of namedChildren4(node))
|
|
10680
|
+
for (const c of namedChildren4(node)) walk9(c);
|
|
10549
10681
|
};
|
|
10550
|
-
|
|
10682
|
+
walk9(root);
|
|
10551
10683
|
return { tables, varToTable };
|
|
10552
10684
|
}
|
|
10553
10685
|
function referencesTargetVar(call) {
|
|
@@ -10570,7 +10702,7 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
10570
10702
|
const seen = /* @__PURE__ */ new Set();
|
|
10571
10703
|
for (const table of tables) {
|
|
10572
10704
|
if (!table.object) continue;
|
|
10573
|
-
const
|
|
10705
|
+
const walk9 = (node) => {
|
|
10574
10706
|
if (node.type === "call_expression") {
|
|
10575
10707
|
const targetVar = referencesTargetVar(node);
|
|
10576
10708
|
const parentTable = targetVar ? varToTable.get(targetVar) : void 0;
|
|
@@ -10591,9 +10723,9 @@ function drizzleForeignKeys(file, serviceDir) {
|
|
|
10591
10723
|
}
|
|
10592
10724
|
}
|
|
10593
10725
|
}
|
|
10594
|
-
for (const c of namedChildren4(node))
|
|
10726
|
+
for (const c of namedChildren4(node)) walk9(c);
|
|
10595
10727
|
};
|
|
10596
|
-
|
|
10728
|
+
walk9(table.object);
|
|
10597
10729
|
}
|
|
10598
10730
|
return out;
|
|
10599
10731
|
}
|
|
@@ -11673,15 +11805,531 @@ function goSqlEndpointsFromFile(file, serviceDir) {
|
|
|
11673
11805
|
return out;
|
|
11674
11806
|
}
|
|
11675
11807
|
|
|
11808
|
+
// src/extract/calls/gorm.ts
|
|
11809
|
+
init_cjs_shims();
|
|
11810
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
11811
|
+
var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
|
|
11812
|
+
var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
|
|
11813
|
+
var import_types37 = require("@neat.is/types");
|
|
11814
|
+
var GORM_IMPORT_RE = /gorm\.io\/gorm/;
|
|
11815
|
+
var PARSE_CHUNK11 = 16384;
|
|
11816
|
+
function makeGoParser3() {
|
|
11817
|
+
const p = new import_tree_sitter15.default();
|
|
11818
|
+
p.setLanguage(import_tree_sitter_go4.default);
|
|
11819
|
+
return p;
|
|
11820
|
+
}
|
|
11821
|
+
function parseSource10(parser, source) {
|
|
11822
|
+
return parser.parse(
|
|
11823
|
+
(index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK11)
|
|
11824
|
+
);
|
|
11825
|
+
}
|
|
11826
|
+
function walk8(node, visit) {
|
|
11827
|
+
visit(node);
|
|
11828
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
11829
|
+
const c = node.namedChild(i);
|
|
11830
|
+
if (c) walk8(c, visit);
|
|
11831
|
+
}
|
|
11832
|
+
}
|
|
11833
|
+
var COMMON_INITIALISMS = [
|
|
11834
|
+
"ASCII",
|
|
11835
|
+
"HTTPS",
|
|
11836
|
+
"UTF8",
|
|
11837
|
+
"XSRF",
|
|
11838
|
+
"HTML",
|
|
11839
|
+
"HTTP",
|
|
11840
|
+
"JSON",
|
|
11841
|
+
"UUID",
|
|
11842
|
+
"XMPP",
|
|
11843
|
+
"ACL",
|
|
11844
|
+
"API",
|
|
11845
|
+
"CPU",
|
|
11846
|
+
"CSS",
|
|
11847
|
+
"DNS",
|
|
11848
|
+
"EOF",
|
|
11849
|
+
"GUID",
|
|
11850
|
+
"LHS",
|
|
11851
|
+
"QPS",
|
|
11852
|
+
"RAM",
|
|
11853
|
+
"RHS",
|
|
11854
|
+
"RPC",
|
|
11855
|
+
"SLA",
|
|
11856
|
+
"SQL",
|
|
11857
|
+
"SSH",
|
|
11858
|
+
"TCP",
|
|
11859
|
+
"TLS",
|
|
11860
|
+
"TTL",
|
|
11861
|
+
"UDP",
|
|
11862
|
+
"UID",
|
|
11863
|
+
"URI",
|
|
11864
|
+
"URL",
|
|
11865
|
+
"UID",
|
|
11866
|
+
"XSS",
|
|
11867
|
+
"ID",
|
|
11868
|
+
"IP",
|
|
11869
|
+
"UI",
|
|
11870
|
+
"VM",
|
|
11871
|
+
"XML"
|
|
11872
|
+
].sort((a, b) => b.length - a.length);
|
|
11873
|
+
function titleCase(word) {
|
|
11874
|
+
return word.charAt(0) + word.slice(1).toLowerCase();
|
|
11875
|
+
}
|
|
11876
|
+
function replaceInitialisms(name) {
|
|
11877
|
+
let out = "";
|
|
11878
|
+
let i = 0;
|
|
11879
|
+
while (i < name.length) {
|
|
11880
|
+
let matched = false;
|
|
11881
|
+
for (const init of COMMON_INITIALISMS) {
|
|
11882
|
+
if (name.startsWith(init, i)) {
|
|
11883
|
+
out += titleCase(init);
|
|
11884
|
+
i += init.length;
|
|
11885
|
+
matched = true;
|
|
11886
|
+
break;
|
|
11887
|
+
}
|
|
11888
|
+
}
|
|
11889
|
+
if (!matched) {
|
|
11890
|
+
out += name[i];
|
|
11891
|
+
i++;
|
|
11892
|
+
}
|
|
11893
|
+
}
|
|
11894
|
+
return out;
|
|
11895
|
+
}
|
|
11896
|
+
var isUpper = (c) => c >= "A" && c <= "Z";
|
|
11897
|
+
var isDigit = (c) => c >= "0" && c <= "9";
|
|
11898
|
+
function toDBName(name) {
|
|
11899
|
+
if (name === "") return "";
|
|
11900
|
+
const value = replaceInitialisms(name);
|
|
11901
|
+
if (value.length === 1) return value.toLowerCase();
|
|
11902
|
+
let buf = "";
|
|
11903
|
+
let lastCase = false;
|
|
11904
|
+
let curCase = isUpper(value[0]);
|
|
11905
|
+
for (let i = 0; i < value.length - 1; i++) {
|
|
11906
|
+
const v = value[i];
|
|
11907
|
+
const nextCase = isUpper(value[i + 1]);
|
|
11908
|
+
const nextNumber = isDigit(value[i + 1]);
|
|
11909
|
+
if (curCase) {
|
|
11910
|
+
if (lastCase && (nextCase || nextNumber)) {
|
|
11911
|
+
buf += v.toLowerCase();
|
|
11912
|
+
} else {
|
|
11913
|
+
if (i > 0 && value[i - 1] !== "_" && lastCase !== curCase) buf += "_";
|
|
11914
|
+
buf += v.toLowerCase();
|
|
11915
|
+
}
|
|
11916
|
+
} else {
|
|
11917
|
+
buf += v;
|
|
11918
|
+
}
|
|
11919
|
+
lastCase = curCase;
|
|
11920
|
+
curCase = nextCase;
|
|
11921
|
+
}
|
|
11922
|
+
const last = value[value.length - 1];
|
|
11923
|
+
if (curCase) {
|
|
11924
|
+
if (!lastCase && value.length > 1) buf += "_";
|
|
11925
|
+
buf += last.toLowerCase();
|
|
11926
|
+
} else {
|
|
11927
|
+
buf += last;
|
|
11928
|
+
}
|
|
11929
|
+
return buf;
|
|
11930
|
+
}
|
|
11931
|
+
var UNCOUNTABLE = /* @__PURE__ */ new Set([
|
|
11932
|
+
"equipment",
|
|
11933
|
+
"information",
|
|
11934
|
+
"rice",
|
|
11935
|
+
"money",
|
|
11936
|
+
"species",
|
|
11937
|
+
"series",
|
|
11938
|
+
"fish",
|
|
11939
|
+
"sheep",
|
|
11940
|
+
"jeans",
|
|
11941
|
+
"police"
|
|
11942
|
+
]);
|
|
11943
|
+
var IRREGULAR = [
|
|
11944
|
+
["person", "people"],
|
|
11945
|
+
["man", "men"],
|
|
11946
|
+
["child", "children"],
|
|
11947
|
+
["sex", "sexes"],
|
|
11948
|
+
["move", "moves"]
|
|
11949
|
+
];
|
|
11950
|
+
var PLURAL_RULES = [
|
|
11951
|
+
[/(quiz)$/i, "$1zes"],
|
|
11952
|
+
[/^(ox)$/i, "$1en"],
|
|
11953
|
+
[/([ml])ouse$/i, "$1ice"],
|
|
11954
|
+
[/(matr|vert|ind)(?:ix|ex)$/i, "$1ices"],
|
|
11955
|
+
[/(x|ch|ss|sh)$/i, "$1es"],
|
|
11956
|
+
[/([^aeiouy]|qu)y$/i, "$1ies"],
|
|
11957
|
+
[/(hive)$/i, "$1s"],
|
|
11958
|
+
[/(?:([^f])fe|([lr])f)$/i, "$1$2ves"],
|
|
11959
|
+
[/sis$/i, "ses"],
|
|
11960
|
+
[/([ti])um$/i, "$1a"],
|
|
11961
|
+
[/([ti])a$/i, "$1a"],
|
|
11962
|
+
[/(buffal|tomat)o$/i, "$1oes"],
|
|
11963
|
+
[/(bu)s$/i, "$1ses"],
|
|
11964
|
+
[/(alias|status)$/i, "$1es"],
|
|
11965
|
+
[/(octop|vir)i$/i, "$1i"],
|
|
11966
|
+
[/(octop|vir)us$/i, "$1i"],
|
|
11967
|
+
[/(ax|test)is$/i, "$1es"],
|
|
11968
|
+
[/s$/i, "s"]
|
|
11969
|
+
];
|
|
11970
|
+
function pluralize3(word) {
|
|
11971
|
+
if (word === "") return word;
|
|
11972
|
+
const lower = word.toLowerCase();
|
|
11973
|
+
for (const u of UNCOUNTABLE) {
|
|
11974
|
+
if (lower === u || lower.endsWith("_" + u)) return word;
|
|
11975
|
+
}
|
|
11976
|
+
for (const [sing, plur] of IRREGULAR) {
|
|
11977
|
+
const re = new RegExp(sing + "$", "i");
|
|
11978
|
+
if (re.test(word)) return word.replace(re, plur);
|
|
11979
|
+
}
|
|
11980
|
+
for (const [re, rep] of PLURAL_RULES) {
|
|
11981
|
+
if (re.test(word)) return word.replace(re, rep);
|
|
11982
|
+
}
|
|
11983
|
+
return word + "s";
|
|
11984
|
+
}
|
|
11985
|
+
function deriveTableName(structName) {
|
|
11986
|
+
return pluralize3(toDBName(structName));
|
|
11987
|
+
}
|
|
11988
|
+
function stringLiteralValue(node) {
|
|
11989
|
+
if (!node) return null;
|
|
11990
|
+
if (node.type === "interpreted_string_literal" || node.type === "raw_string_literal") {
|
|
11991
|
+
const t = node.text;
|
|
11992
|
+
return t.length >= 2 ? t.slice(1, -1) : "";
|
|
11993
|
+
}
|
|
11994
|
+
return null;
|
|
11995
|
+
}
|
|
11996
|
+
function parseGormTag(tagNode) {
|
|
11997
|
+
const tag = {};
|
|
11998
|
+
if (!tagNode) return tag;
|
|
11999
|
+
let inner = tagNode.text;
|
|
12000
|
+
if (inner.length >= 2) inner = inner.slice(1, -1);
|
|
12001
|
+
if (tagNode.type === "interpreted_string_literal") inner = inner.replace(/\\"/g, '"');
|
|
12002
|
+
const m = inner.match(/gorm:"([^"]*)"/);
|
|
12003
|
+
if (!m) return tag;
|
|
12004
|
+
for (const part of m[1].split(";")) {
|
|
12005
|
+
if (part === "") continue;
|
|
12006
|
+
const idx = part.indexOf(":");
|
|
12007
|
+
const key = (idx >= 0 ? part.slice(0, idx) : part).trim().toLowerCase();
|
|
12008
|
+
const value = idx >= 0 ? part.slice(idx + 1).trim() : "";
|
|
12009
|
+
if (key === "-") tag.skip = true;
|
|
12010
|
+
else if (key === "column") tag.column = value;
|
|
12011
|
+
else if (key === "primarykey" || key === "primary_key") tag.primaryKey = true;
|
|
12012
|
+
else if (key === "foreignkey") tag.foreignKey = value;
|
|
12013
|
+
else if (key === "many2many") tag.many2many = value;
|
|
12014
|
+
else if (key === "embedded") tag.embedded = true;
|
|
12015
|
+
else if (key === "embeddedprefix") tag.embeddedPrefix = value;
|
|
12016
|
+
}
|
|
12017
|
+
return tag;
|
|
12018
|
+
}
|
|
12019
|
+
function unwrapType(typeNode) {
|
|
12020
|
+
let isSlice = false;
|
|
12021
|
+
let isPointer = false;
|
|
12022
|
+
let n = typeNode;
|
|
12023
|
+
while (n && (n.type === "slice_type" || n.type === "array_type" || n.type === "pointer_type")) {
|
|
12024
|
+
if (n.type === "slice_type" || n.type === "array_type") isSlice = true;
|
|
12025
|
+
if (n.type === "pointer_type") isPointer = true;
|
|
12026
|
+
n = n.childForFieldName("element") ?? n.namedChild(n.namedChildCount - 1);
|
|
12027
|
+
}
|
|
12028
|
+
if (!n) return { name: null, qualifier: null, isSlice, isPointer, isQualified: false };
|
|
12029
|
+
if (n.type === "type_identifier") {
|
|
12030
|
+
return { name: n.text, qualifier: null, isSlice, isPointer, isQualified: false };
|
|
12031
|
+
}
|
|
12032
|
+
if (n.type === "qualified_type") {
|
|
12033
|
+
const pkg = n.childForFieldName("package")?.text ?? n.namedChild(0)?.text ?? null;
|
|
12034
|
+
const nm = n.childForFieldName("name")?.text ?? n.namedChild(1)?.text ?? null;
|
|
12035
|
+
return { name: nm, qualifier: pkg, isSlice, isPointer, isQualified: true };
|
|
12036
|
+
}
|
|
12037
|
+
return { name: null, qualifier: null, isSlice, isPointer, isQualified: false };
|
|
12038
|
+
}
|
|
12039
|
+
function readField(fieldDecl) {
|
|
12040
|
+
const names = [];
|
|
12041
|
+
let tagNode = null;
|
|
12042
|
+
for (let i = 0; i < fieldDecl.namedChildCount; i++) {
|
|
12043
|
+
const c = fieldDecl.namedChild(i);
|
|
12044
|
+
if (!c) continue;
|
|
12045
|
+
if (c.type === "field_identifier") names.push(c.text);
|
|
12046
|
+
else if (c.type === "raw_string_literal" || c.type === "interpreted_string_literal") tagNode = c;
|
|
12047
|
+
}
|
|
12048
|
+
const typeNode = fieldDecl.childForFieldName("type");
|
|
12049
|
+
const t = unwrapType(typeNode);
|
|
12050
|
+
return {
|
|
12051
|
+
names,
|
|
12052
|
+
typeName: t.name,
|
|
12053
|
+
qualifier: t.qualifier,
|
|
12054
|
+
isSlice: t.isSlice,
|
|
12055
|
+
isPointer: t.isPointer,
|
|
12056
|
+
isQualified: t.isQualified,
|
|
12057
|
+
tag: parseGormTag(tagNode),
|
|
12058
|
+
line: fieldDecl.startPosition.row + 1
|
|
12059
|
+
};
|
|
12060
|
+
}
|
|
12061
|
+
function collectStructs(tree) {
|
|
12062
|
+
const structs = /* @__PURE__ */ new Map();
|
|
12063
|
+
walk8(tree.rootNode, (node) => {
|
|
12064
|
+
if (node.type !== "type_spec") return;
|
|
12065
|
+
const nameNode = node.childForFieldName("name");
|
|
12066
|
+
const typeNode = node.childForFieldName("type");
|
|
12067
|
+
if (!nameNode || typeNode?.type !== "struct_type") return;
|
|
12068
|
+
const list = typeNode.childForFieldName("body") ?? typeNode.namedChild(0);
|
|
12069
|
+
const fields = [];
|
|
12070
|
+
if (list && list.type === "field_declaration_list") {
|
|
12071
|
+
for (let i = 0; i < list.namedChildCount; i++) {
|
|
12072
|
+
const fd = list.namedChild(i);
|
|
12073
|
+
if (fd?.type === "field_declaration") fields.push(readField(fd));
|
|
12074
|
+
}
|
|
12075
|
+
}
|
|
12076
|
+
structs.set(nameNode.text, {
|
|
12077
|
+
name: nameNode.text,
|
|
12078
|
+
fields,
|
|
12079
|
+
line: node.startPosition.row + 1
|
|
12080
|
+
});
|
|
12081
|
+
});
|
|
12082
|
+
return structs;
|
|
12083
|
+
}
|
|
12084
|
+
var GORM_MODEL_METHODS = /* @__PURE__ */ new Set([
|
|
12085
|
+
"AutoMigrate",
|
|
12086
|
+
"Model",
|
|
12087
|
+
"Create",
|
|
12088
|
+
"Find",
|
|
12089
|
+
"First",
|
|
12090
|
+
"Take",
|
|
12091
|
+
"Last",
|
|
12092
|
+
"Save",
|
|
12093
|
+
"Delete",
|
|
12094
|
+
"Where",
|
|
12095
|
+
"FirstOrCreate",
|
|
12096
|
+
"FirstOrInit"
|
|
12097
|
+
]);
|
|
12098
|
+
function compositeStructName(arg) {
|
|
12099
|
+
let n = arg;
|
|
12100
|
+
if (n.type === "unary_expression") n = n.childForFieldName("operand") ?? n.namedChild(0);
|
|
12101
|
+
if (!n || n.type !== "composite_literal") return null;
|
|
12102
|
+
const typeNode = n.childForFieldName("type");
|
|
12103
|
+
if (!typeNode) return null;
|
|
12104
|
+
if (typeNode.type === "type_identifier") return typeNode.text;
|
|
12105
|
+
if (typeNode.type === "qualified_type") {
|
|
12106
|
+
return typeNode.childForFieldName("name")?.text ?? typeNode.namedChild(1)?.text ?? null;
|
|
12107
|
+
}
|
|
12108
|
+
return null;
|
|
12109
|
+
}
|
|
12110
|
+
function collectCallModels(tree) {
|
|
12111
|
+
const models = /* @__PURE__ */ new Set();
|
|
12112
|
+
walk8(tree.rootNode, (node) => {
|
|
12113
|
+
if (node.type !== "call_expression") return;
|
|
12114
|
+
const fn = node.childForFieldName("function");
|
|
12115
|
+
if (fn?.type !== "selector_expression") return;
|
|
12116
|
+
const method = fn.childForFieldName("field")?.text;
|
|
12117
|
+
if (!method || !GORM_MODEL_METHODS.has(method)) return;
|
|
12118
|
+
const args = node.childForFieldName("arguments");
|
|
12119
|
+
if (!args) return;
|
|
12120
|
+
for (let i = 0; i < args.namedChildCount; i++) {
|
|
12121
|
+
const arg = args.namedChild(i);
|
|
12122
|
+
if (!arg) continue;
|
|
12123
|
+
const name = compositeStructName(arg);
|
|
12124
|
+
if (name) models.add(name);
|
|
12125
|
+
}
|
|
12126
|
+
});
|
|
12127
|
+
return models;
|
|
12128
|
+
}
|
|
12129
|
+
function collectTableNameOverrides(tree) {
|
|
12130
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
12131
|
+
const declarers = /* @__PURE__ */ new Set();
|
|
12132
|
+
walk8(tree.rootNode, (node) => {
|
|
12133
|
+
if (node.type !== "method_declaration") return;
|
|
12134
|
+
if (node.childForFieldName("name")?.text !== "TableName") return;
|
|
12135
|
+
const receiver = node.childForFieldName("receiver");
|
|
12136
|
+
if (!receiver) return;
|
|
12137
|
+
let recvType = null;
|
|
12138
|
+
for (let i = 0; i < receiver.namedChildCount; i++) {
|
|
12139
|
+
const pd = receiver.namedChild(i);
|
|
12140
|
+
if (pd?.type !== "parameter_declaration") continue;
|
|
12141
|
+
const t = unwrapType(pd.childForFieldName("type"));
|
|
12142
|
+
recvType = t.name;
|
|
12143
|
+
}
|
|
12144
|
+
if (!recvType) return;
|
|
12145
|
+
declarers.add(recvType);
|
|
12146
|
+
const body = node.childForFieldName("body");
|
|
12147
|
+
if (!body) return;
|
|
12148
|
+
let literal = null;
|
|
12149
|
+
walk8(body, (n) => {
|
|
12150
|
+
if (literal !== null) return;
|
|
12151
|
+
if (n.type !== "return_statement") return;
|
|
12152
|
+
const exprList = n.namedChild(0);
|
|
12153
|
+
const first = exprList?.namedChild(0) ?? exprList;
|
|
12154
|
+
const v = stringLiteralValue(first);
|
|
12155
|
+
if (v) literal = v;
|
|
12156
|
+
});
|
|
12157
|
+
if (literal !== null) overrides.set(recvType, literal);
|
|
12158
|
+
});
|
|
12159
|
+
return { overrides, declarers };
|
|
12160
|
+
}
|
|
12161
|
+
function isRelationField(field, structs) {
|
|
12162
|
+
if (field.names.length === 0) return false;
|
|
12163
|
+
if (field.isQualified) return false;
|
|
12164
|
+
if (!field.typeName) return false;
|
|
12165
|
+
return structs.has(field.typeName);
|
|
12166
|
+
}
|
|
12167
|
+
function isGormModelEmbed(field) {
|
|
12168
|
+
return field.names.length === 0 && field.qualifier === "gorm" && field.typeName === "Model";
|
|
12169
|
+
}
|
|
12170
|
+
function analyze(tree) {
|
|
12171
|
+
const structs = collectStructs(tree);
|
|
12172
|
+
const { overrides, declarers } = collectTableNameOverrides(tree);
|
|
12173
|
+
const callModels = collectCallModels(tree);
|
|
12174
|
+
const models = /* @__PURE__ */ new Set();
|
|
12175
|
+
for (const [name, info] of structs) {
|
|
12176
|
+
if (info.fields.some(isGormModelEmbed)) models.add(name);
|
|
12177
|
+
}
|
|
12178
|
+
for (const name of callModels) if (structs.has(name)) models.add(name);
|
|
12179
|
+
for (const name of declarers) if (structs.has(name)) models.add(name);
|
|
12180
|
+
let grew = true;
|
|
12181
|
+
while (grew) {
|
|
12182
|
+
grew = false;
|
|
12183
|
+
for (const name of Array.from(models)) {
|
|
12184
|
+
const info = structs.get(name);
|
|
12185
|
+
if (!info) continue;
|
|
12186
|
+
for (const field of info.fields) {
|
|
12187
|
+
if (!isRelationField(field, structs)) continue;
|
|
12188
|
+
const target = field.typeName;
|
|
12189
|
+
if (!models.has(target) && structs.has(target)) {
|
|
12190
|
+
models.add(target);
|
|
12191
|
+
grew = true;
|
|
12192
|
+
}
|
|
12193
|
+
}
|
|
12194
|
+
}
|
|
12195
|
+
}
|
|
12196
|
+
const tableFor = (structName) => overrides.get(structName) ?? deriveTableName(structName);
|
|
12197
|
+
return { structs, models, tableFor };
|
|
12198
|
+
}
|
|
12199
|
+
function collectColumns(struct, structs, seen, prefix, out, emitted) {
|
|
12200
|
+
if (seen.has(struct.name)) return;
|
|
12201
|
+
seen.add(struct.name);
|
|
12202
|
+
const add = (col) => {
|
|
12203
|
+
const full = prefix + col;
|
|
12204
|
+
if (!emitted.has(full)) {
|
|
12205
|
+
emitted.add(full);
|
|
12206
|
+
out.push(full);
|
|
12207
|
+
}
|
|
12208
|
+
};
|
|
12209
|
+
for (const field of struct.fields) {
|
|
12210
|
+
if (field.tag.skip) continue;
|
|
12211
|
+
if (field.names.length === 0) {
|
|
12212
|
+
if (isGormModelEmbed(field)) {
|
|
12213
|
+
add("id");
|
|
12214
|
+
add("created_at");
|
|
12215
|
+
add("updated_at");
|
|
12216
|
+
add("deleted_at");
|
|
12217
|
+
} else if (!field.isQualified && field.typeName && structs.has(field.typeName)) {
|
|
12218
|
+
collectColumns(structs.get(field.typeName), structs, seen, prefix, out, emitted);
|
|
12219
|
+
}
|
|
12220
|
+
continue;
|
|
12221
|
+
}
|
|
12222
|
+
if (field.tag.embedded && !field.isQualified && field.typeName && structs.has(field.typeName)) {
|
|
12223
|
+
collectColumns(
|
|
12224
|
+
structs.get(field.typeName),
|
|
12225
|
+
structs,
|
|
12226
|
+
seen,
|
|
12227
|
+
prefix + (field.tag.embeddedPrefix ?? ""),
|
|
12228
|
+
out,
|
|
12229
|
+
emitted
|
|
12230
|
+
);
|
|
12231
|
+
continue;
|
|
12232
|
+
}
|
|
12233
|
+
if (isRelationField(field, structs)) continue;
|
|
12234
|
+
if (field.names.length === 1 && field.tag.column) {
|
|
12235
|
+
add(field.tag.column);
|
|
12236
|
+
} else {
|
|
12237
|
+
for (const n of field.names) add(toDBName(n));
|
|
12238
|
+
}
|
|
12239
|
+
}
|
|
12240
|
+
seen.delete(struct.name);
|
|
12241
|
+
}
|
|
12242
|
+
function gormEndpointsFromFile(file, serviceDir) {
|
|
12243
|
+
if (import_node_path50.default.extname(file.path) !== ".go") return [];
|
|
12244
|
+
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
12245
|
+
const tree = parseSource10(makeGoParser3(), file.content);
|
|
12246
|
+
const { structs, models, tableFor } = analyze(tree);
|
|
12247
|
+
const out = [];
|
|
12248
|
+
const seenTables = /* @__PURE__ */ new Set();
|
|
12249
|
+
for (const name of models) {
|
|
12250
|
+
const struct = structs.get(name);
|
|
12251
|
+
if (!struct) continue;
|
|
12252
|
+
const table = tableFor(name);
|
|
12253
|
+
if (seenTables.has(table)) continue;
|
|
12254
|
+
seenTables.add(table);
|
|
12255
|
+
const columns = [];
|
|
12256
|
+
collectColumns(struct, structs, /* @__PURE__ */ new Set(), "", columns, /* @__PURE__ */ new Set());
|
|
12257
|
+
out.push({
|
|
12258
|
+
infraId: (0, import_types37.infraId)("sql-table", table),
|
|
12259
|
+
name: table,
|
|
12260
|
+
kind: "sql-table",
|
|
12261
|
+
edgeType: "CALLS",
|
|
12262
|
+
confidenceKind: "structural",
|
|
12263
|
+
...columns.length > 0 ? { columns } : {},
|
|
12264
|
+
evidence: {
|
|
12265
|
+
file: toPosix(import_node_path50.default.relative(serviceDir, file.path)),
|
|
12266
|
+
line: struct.line,
|
|
12267
|
+
snippet: snippet(file.content, struct.line)
|
|
12268
|
+
}
|
|
12269
|
+
});
|
|
12270
|
+
}
|
|
12271
|
+
return out;
|
|
12272
|
+
}
|
|
12273
|
+
function gormForeignKeys(file, serviceDir) {
|
|
12274
|
+
if (import_node_path50.default.extname(file.path) !== ".go") return [];
|
|
12275
|
+
if (!GORM_IMPORT_RE.test(file.content)) return [];
|
|
12276
|
+
const tree = parseSource10(makeGoParser3(), file.content);
|
|
12277
|
+
const { structs, models, tableFor } = analyze(tree);
|
|
12278
|
+
const out = [];
|
|
12279
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12280
|
+
const emit = (childTable, parentTable, line) => {
|
|
12281
|
+
if (!childTable || !parentTable || childTable === parentTable) return;
|
|
12282
|
+
const key = `${childTable}->${parentTable}`;
|
|
12283
|
+
if (seen.has(key)) return;
|
|
12284
|
+
seen.add(key);
|
|
12285
|
+
out.push({
|
|
12286
|
+
childTable,
|
|
12287
|
+
parentTable,
|
|
12288
|
+
evidence: {
|
|
12289
|
+
file: toPosix(import_node_path50.default.relative(serviceDir, file.path)),
|
|
12290
|
+
line,
|
|
12291
|
+
snippet: snippet(file.content, line)
|
|
12292
|
+
}
|
|
12293
|
+
});
|
|
12294
|
+
};
|
|
12295
|
+
for (const name of models) {
|
|
12296
|
+
const struct = structs.get(name);
|
|
12297
|
+
if (!struct) continue;
|
|
12298
|
+
const thisTable = tableFor(name);
|
|
12299
|
+
const scalarNames = new Set(
|
|
12300
|
+
struct.fields.filter((f) => f.names.length > 0 && !isRelationField(f, structs)).flatMap((f) => f.names)
|
|
12301
|
+
);
|
|
12302
|
+
for (const field of struct.fields) {
|
|
12303
|
+
if (field.tag.skip) continue;
|
|
12304
|
+
if (!isRelationField(field, structs)) continue;
|
|
12305
|
+
const relTable = tableFor(field.typeName);
|
|
12306
|
+
if (field.tag.many2many) {
|
|
12307
|
+
emit(field.tag.many2many, thisTable, field.line);
|
|
12308
|
+
emit(field.tag.many2many, relTable, field.line);
|
|
12309
|
+
continue;
|
|
12310
|
+
}
|
|
12311
|
+
if (field.isSlice) {
|
|
12312
|
+
emit(relTable, thisTable, field.line);
|
|
12313
|
+
continue;
|
|
12314
|
+
}
|
|
12315
|
+
const convFk = field.names[0] + "ID";
|
|
12316
|
+
const belongsTo = scalarNames.has(convFk) || (field.tag.foreignKey ? scalarNames.has(field.tag.foreignKey) : false);
|
|
12317
|
+
if (belongsTo) emit(thisTable, relTable, field.line);
|
|
12318
|
+
else emit(relTable, thisTable, field.line);
|
|
12319
|
+
}
|
|
12320
|
+
}
|
|
12321
|
+
return out;
|
|
12322
|
+
}
|
|
12323
|
+
|
|
11676
12324
|
// src/extract/calls/index.ts
|
|
11677
12325
|
function edgeTypeFromEndpoint(ep) {
|
|
11678
12326
|
switch (ep.edgeType) {
|
|
11679
12327
|
case "PUBLISHES_TO":
|
|
11680
|
-
return
|
|
12328
|
+
return import_types38.EdgeType.PUBLISHES_TO;
|
|
11681
12329
|
case "CONSUMES_FROM":
|
|
11682
|
-
return
|
|
12330
|
+
return import_types38.EdgeType.CONSUMES_FROM;
|
|
11683
12331
|
default:
|
|
11684
|
-
return
|
|
12332
|
+
return import_types38.EdgeType.CALLS;
|
|
11685
12333
|
}
|
|
11686
12334
|
}
|
|
11687
12335
|
function isAwsKind(kind) {
|
|
@@ -11714,6 +12362,11 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11714
12362
|
} catch (err) {
|
|
11715
12363
|
recordExtractionError("go SQL call extraction", file.path, err);
|
|
11716
12364
|
}
|
|
12365
|
+
try {
|
|
12366
|
+
endpoints.push(...gormEndpointsFromFile(file, service.dir));
|
|
12367
|
+
} catch (err) {
|
|
12368
|
+
recordExtractionError("gorm data-axis extraction", file.path, err);
|
|
12369
|
+
}
|
|
11717
12370
|
try {
|
|
11718
12371
|
endpoints.push(...railsSchemaEndpointsFromFile(file, service.dir));
|
|
11719
12372
|
endpoints.push(...railsModelEndpointsFromFile(file, service.dir));
|
|
@@ -11736,7 +12389,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11736
12389
|
if (!graph.hasNode(ep.infraId)) {
|
|
11737
12390
|
const node = {
|
|
11738
12391
|
id: ep.infraId,
|
|
11739
|
-
type:
|
|
12392
|
+
type: import_types38.NodeType.InfraNode,
|
|
11740
12393
|
name: ep.name,
|
|
11741
12394
|
// #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
|
|
11742
12395
|
// aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
|
|
@@ -11749,21 +12402,21 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11749
12402
|
}
|
|
11750
12403
|
if (ep.columns && ep.columns.length > 0) {
|
|
11751
12404
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
11752
|
-
if (node.type ===
|
|
12405
|
+
if (node.type === import_types38.NodeType.InfraNode) {
|
|
11753
12406
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
11754
12407
|
...node,
|
|
11755
12408
|
columns: foldColumns(
|
|
11756
12409
|
node.columns,
|
|
11757
12410
|
ep.columns,
|
|
11758
|
-
|
|
11759
|
-
(0,
|
|
12411
|
+
import_types38.Provenance.EXTRACTED,
|
|
12412
|
+
(0, import_types38.confidenceForExtracted)(ep.confidenceKind)
|
|
11760
12413
|
)
|
|
11761
12414
|
});
|
|
11762
12415
|
}
|
|
11763
12416
|
}
|
|
11764
12417
|
if (ep.sdkWrites && Object.keys(ep.sdkWrites).length > 0) {
|
|
11765
12418
|
const node = graph.getNodeAttributes(ep.infraId);
|
|
11766
|
-
if (node.type ===
|
|
12419
|
+
if (node.type === import_types38.NodeType.InfraNode) {
|
|
11767
12420
|
graph.replaceNodeAttributes(ep.infraId, {
|
|
11768
12421
|
...node,
|
|
11769
12422
|
columns: foldSdkWrites(node.columns, ep.sdkWrites)
|
|
@@ -11771,7 +12424,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11771
12424
|
}
|
|
11772
12425
|
}
|
|
11773
12426
|
const edgeType = edgeTypeFromEndpoint(ep);
|
|
11774
|
-
const confidence = (0,
|
|
12427
|
+
const confidence = (0, import_types38.confidenceForExtracted)(ep.confidenceKind);
|
|
11775
12428
|
const relFile = toPosix(ep.evidence.file);
|
|
11776
12429
|
const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
|
|
11777
12430
|
graph,
|
|
@@ -11781,7 +12434,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11781
12434
|
);
|
|
11782
12435
|
nodesAdded += n;
|
|
11783
12436
|
edgesAdded += e;
|
|
11784
|
-
if (!(0,
|
|
12437
|
+
if (!(0, import_types38.passesExtractedFloor)(confidence)) {
|
|
11785
12438
|
noteExtractedDropped({
|
|
11786
12439
|
source: fileNodeId,
|
|
11787
12440
|
target: ep.infraId,
|
|
@@ -11801,7 +12454,7 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
11801
12454
|
source: fileNodeId,
|
|
11802
12455
|
target: ep.infraId,
|
|
11803
12456
|
type: edgeType,
|
|
11804
|
-
provenance:
|
|
12457
|
+
provenance: import_types38.Provenance.EXTRACTED,
|
|
11805
12458
|
confidence,
|
|
11806
12459
|
evidence: ep.evidence
|
|
11807
12460
|
};
|
|
@@ -11824,7 +12477,7 @@ async function addCallEdges(graph, services) {
|
|
|
11824
12477
|
|
|
11825
12478
|
// src/extract/table-edges.ts
|
|
11826
12479
|
init_cjs_shims();
|
|
11827
|
-
var
|
|
12480
|
+
var import_types39 = require("@neat.is/types");
|
|
11828
12481
|
async function addTableEdges(graph, services) {
|
|
11829
12482
|
let nodesAdded = 0;
|
|
11830
12483
|
let edgesAdded = 0;
|
|
@@ -11838,6 +12491,7 @@ async function addTableEdges(graph, services) {
|
|
|
11838
12491
|
refs.push(...sqlalchemyForeignKeys(file, service.dir));
|
|
11839
12492
|
refs.push(...railsSchemaForeignKeys(file, service.dir));
|
|
11840
12493
|
refs.push(...laravelMigrationForeignKeys(file, service.dir));
|
|
12494
|
+
refs.push(...gormForeignKeys(file, service.dir));
|
|
11841
12495
|
modelRefs.push(...railsModelForeignKeys(file, service.dir));
|
|
11842
12496
|
modelRefs.push(...laravelModelForeignKeys(file, service.dir));
|
|
11843
12497
|
} catch (err) {
|
|
@@ -11851,20 +12505,20 @@ async function addTableEdges(graph, services) {
|
|
|
11851
12505
|
}
|
|
11852
12506
|
refs.push(...modelRefs);
|
|
11853
12507
|
for (const ref of refs) {
|
|
11854
|
-
const childId = (0,
|
|
11855
|
-
const parentId = (0,
|
|
12508
|
+
const childId = (0, import_types39.infraId)("sql-table", ref.childTable);
|
|
12509
|
+
const parentId = (0, import_types39.infraId)("sql-table", ref.parentTable);
|
|
11856
12510
|
if (childId === parentId) continue;
|
|
11857
12511
|
nodesAdded += ensureTableNode(graph, childId, ref.childTable);
|
|
11858
12512
|
nodesAdded += ensureTableNode(graph, parentId, ref.parentTable);
|
|
11859
|
-
const edgeId = (0,
|
|
12513
|
+
const edgeId = (0, import_types39.extractedEdgeId)(childId, parentId, import_types39.EdgeType.REFERENCES);
|
|
11860
12514
|
if (graph.hasEdge(edgeId)) continue;
|
|
11861
12515
|
const edge = {
|
|
11862
12516
|
id: edgeId,
|
|
11863
12517
|
source: childId,
|
|
11864
12518
|
target: parentId,
|
|
11865
|
-
type:
|
|
11866
|
-
provenance:
|
|
11867
|
-
confidence: (0,
|
|
12519
|
+
type: import_types39.EdgeType.REFERENCES,
|
|
12520
|
+
provenance: import_types39.Provenance.EXTRACTED,
|
|
12521
|
+
confidence: (0, import_types39.confidenceForExtracted)("structural"),
|
|
11868
12522
|
evidence: ref.evidence
|
|
11869
12523
|
};
|
|
11870
12524
|
graph.addEdgeWithKey(edgeId, childId, parentId, edge);
|
|
@@ -11877,7 +12531,7 @@ function ensureTableNode(graph, id, name) {
|
|
|
11877
12531
|
if (graph.hasNode(id)) return 0;
|
|
11878
12532
|
const node = {
|
|
11879
12533
|
id,
|
|
11880
|
-
type:
|
|
12534
|
+
type: import_types39.NodeType.InfraNode,
|
|
11881
12535
|
name,
|
|
11882
12536
|
provider: "self",
|
|
11883
12537
|
kind: "sql-table"
|
|
@@ -11891,16 +12545,16 @@ init_cjs_shims();
|
|
|
11891
12545
|
|
|
11892
12546
|
// src/extract/infra/docker-compose.ts
|
|
11893
12547
|
init_cjs_shims();
|
|
11894
|
-
var
|
|
11895
|
-
var
|
|
12548
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
12549
|
+
var import_types41 = require("@neat.is/types");
|
|
11896
12550
|
|
|
11897
12551
|
// src/extract/infra/shared.ts
|
|
11898
12552
|
init_cjs_shims();
|
|
11899
|
-
var
|
|
12553
|
+
var import_types40 = require("@neat.is/types");
|
|
11900
12554
|
function makeInfraNode(kind, name, provider = "self", extras) {
|
|
11901
12555
|
return {
|
|
11902
|
-
id: (0,
|
|
11903
|
-
type:
|
|
12556
|
+
id: (0, import_types40.infraId)(kind, name),
|
|
12557
|
+
type: import_types40.NodeType.InfraNode,
|
|
11904
12558
|
name,
|
|
11905
12559
|
provider,
|
|
11906
12560
|
kind,
|
|
@@ -11944,8 +12598,8 @@ function emitPlatformResourceEdge(graph, anchorId, edgeType, kind, name, provide
|
|
|
11944
12598
|
source: anchorId,
|
|
11945
12599
|
target: node.id,
|
|
11946
12600
|
type: edgeType,
|
|
11947
|
-
provenance:
|
|
11948
|
-
confidence: (0,
|
|
12601
|
+
provenance: import_types40.Provenance.EXTRACTED,
|
|
12602
|
+
confidence: (0, import_types40.confidenceForExtracted)("structural"),
|
|
11949
12603
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
11950
12604
|
};
|
|
11951
12605
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -11962,7 +12616,7 @@ function dependsOnList(value) {
|
|
|
11962
12616
|
}
|
|
11963
12617
|
function serviceNameToServiceNode(name, services) {
|
|
11964
12618
|
for (const s of services) {
|
|
11965
|
-
if (s.node.name === name ||
|
|
12619
|
+
if (s.node.name === name || import_node_path51.default.basename(s.dir) === name) return s.node.id;
|
|
11966
12620
|
}
|
|
11967
12621
|
return null;
|
|
11968
12622
|
}
|
|
@@ -11971,7 +12625,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
11971
12625
|
let edgesAdded = 0;
|
|
11972
12626
|
let composePath = null;
|
|
11973
12627
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
11974
|
-
const abs =
|
|
12628
|
+
const abs = import_node_path51.default.join(scanPath, name);
|
|
11975
12629
|
if (await exists2(abs)) {
|
|
11976
12630
|
composePath = abs;
|
|
11977
12631
|
break;
|
|
@@ -11984,13 +12638,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
11984
12638
|
} catch (err) {
|
|
11985
12639
|
recordExtractionError(
|
|
11986
12640
|
"infra docker-compose",
|
|
11987
|
-
|
|
12641
|
+
import_node_path51.default.relative(scanPath, composePath),
|
|
11988
12642
|
err
|
|
11989
12643
|
);
|
|
11990
12644
|
return { nodesAdded, edgesAdded };
|
|
11991
12645
|
}
|
|
11992
12646
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
11993
|
-
const evidenceFile =
|
|
12647
|
+
const evidenceFile = import_node_path51.default.relative(scanPath, composePath).split(import_node_path51.default.sep).join("/");
|
|
11994
12648
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
11995
12649
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
11996
12650
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -12012,15 +12666,15 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
12012
12666
|
for (const dep of dependsOnList(svc.depends_on)) {
|
|
12013
12667
|
const targetId = composeNameToNodeId.get(dep);
|
|
12014
12668
|
if (!targetId) continue;
|
|
12015
|
-
const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId,
|
|
12669
|
+
const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types41.EdgeType.DEPENDS_ON);
|
|
12016
12670
|
if (graph.hasEdge(edgeId)) continue;
|
|
12017
12671
|
const edge = {
|
|
12018
12672
|
id: edgeId,
|
|
12019
12673
|
source: sourceId,
|
|
12020
12674
|
target: targetId,
|
|
12021
|
-
type:
|
|
12022
|
-
provenance:
|
|
12023
|
-
confidence: (0,
|
|
12675
|
+
type: import_types41.EdgeType.DEPENDS_ON,
|
|
12676
|
+
provenance: import_types41.Provenance.EXTRACTED,
|
|
12677
|
+
confidence: (0, import_types41.confidenceForExtracted)("structural"),
|
|
12024
12678
|
evidence: { file: evidenceFile }
|
|
12025
12679
|
};
|
|
12026
12680
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -12032,9 +12686,9 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
12032
12686
|
|
|
12033
12687
|
// src/extract/infra/dockerfile.ts
|
|
12034
12688
|
init_cjs_shims();
|
|
12035
|
-
var
|
|
12689
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
12036
12690
|
var import_node_fs20 = require("fs");
|
|
12037
|
-
var
|
|
12691
|
+
var import_types42 = require("@neat.is/types");
|
|
12038
12692
|
function readDockerfile(content) {
|
|
12039
12693
|
let image = null;
|
|
12040
12694
|
const ports = [];
|
|
@@ -12063,7 +12717,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
12063
12717
|
let nodesAdded = 0;
|
|
12064
12718
|
let edgesAdded = 0;
|
|
12065
12719
|
for (const service of services) {
|
|
12066
|
-
const dockerfilePath =
|
|
12720
|
+
const dockerfilePath = import_node_path52.default.join(service.dir, "Dockerfile");
|
|
12067
12721
|
if (!await exists2(dockerfilePath)) continue;
|
|
12068
12722
|
let content;
|
|
12069
12723
|
try {
|
|
@@ -12071,7 +12725,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
12071
12725
|
} catch (err) {
|
|
12072
12726
|
recordExtractionError(
|
|
12073
12727
|
"infra dockerfile",
|
|
12074
|
-
|
|
12728
|
+
import_node_path52.default.relative(scanPath, dockerfilePath),
|
|
12075
12729
|
err
|
|
12076
12730
|
);
|
|
12077
12731
|
continue;
|
|
@@ -12083,8 +12737,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
12083
12737
|
graph.addNode(node.id, node);
|
|
12084
12738
|
nodesAdded++;
|
|
12085
12739
|
}
|
|
12086
|
-
const relDockerfile = toPosix(
|
|
12087
|
-
const evidenceFile = toPosix(
|
|
12740
|
+
const relDockerfile = toPosix(import_node_path52.default.relative(service.dir, dockerfilePath));
|
|
12741
|
+
const evidenceFile = toPosix(import_node_path52.default.relative(scanPath, dockerfilePath));
|
|
12088
12742
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
12089
12743
|
graph,
|
|
12090
12744
|
service.pkg.name,
|
|
@@ -12093,15 +12747,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
12093
12747
|
);
|
|
12094
12748
|
nodesAdded += fn;
|
|
12095
12749
|
edgesAdded += fe;
|
|
12096
|
-
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id,
|
|
12750
|
+
const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types42.EdgeType.RUNS_ON);
|
|
12097
12751
|
if (!graph.hasEdge(edgeId)) {
|
|
12098
12752
|
const edge = {
|
|
12099
12753
|
id: edgeId,
|
|
12100
12754
|
source: fileNodeId,
|
|
12101
12755
|
target: node.id,
|
|
12102
|
-
type:
|
|
12103
|
-
provenance:
|
|
12104
|
-
confidence: (0,
|
|
12756
|
+
type: import_types42.EdgeType.RUNS_ON,
|
|
12757
|
+
provenance: import_types42.Provenance.EXTRACTED,
|
|
12758
|
+
confidence: (0, import_types42.confidenceForExtracted)("structural"),
|
|
12105
12759
|
evidence: {
|
|
12106
12760
|
file: evidenceFile,
|
|
12107
12761
|
...facts.entrypoint ? { snippet: facts.entrypoint.slice(0, 120) } : {}
|
|
@@ -12116,15 +12770,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
12116
12770
|
graph.addNode(portNode.id, portNode);
|
|
12117
12771
|
nodesAdded++;
|
|
12118
12772
|
}
|
|
12119
|
-
const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id,
|
|
12773
|
+
const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types42.EdgeType.CONNECTS_TO);
|
|
12120
12774
|
if (graph.hasEdge(portEdgeId)) continue;
|
|
12121
12775
|
const portEdge = {
|
|
12122
12776
|
id: portEdgeId,
|
|
12123
12777
|
source: fileNodeId,
|
|
12124
12778
|
target: portNode.id,
|
|
12125
|
-
type:
|
|
12126
|
-
provenance:
|
|
12127
|
-
confidence: (0,
|
|
12779
|
+
type: import_types42.EdgeType.CONNECTS_TO,
|
|
12780
|
+
provenance: import_types42.Provenance.EXTRACTED,
|
|
12781
|
+
confidence: (0, import_types42.confidenceForExtracted)("structural"),
|
|
12128
12782
|
evidence: { file: evidenceFile, snippet: `EXPOSE ${port}` }
|
|
12129
12783
|
};
|
|
12130
12784
|
graph.addEdgeWithKey(portEdgeId, portEdge.source, portEdge.target, portEdge);
|
|
@@ -12137,8 +12791,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
12137
12791
|
// src/extract/infra/terraform.ts
|
|
12138
12792
|
init_cjs_shims();
|
|
12139
12793
|
var import_node_fs21 = require("fs");
|
|
12140
|
-
var
|
|
12141
|
-
var
|
|
12794
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
12795
|
+
var import_types43 = require("@neat.is/types");
|
|
12142
12796
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
12143
12797
|
var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
|
|
12144
12798
|
async function walkTfFiles(start, depth = 0, max = 5) {
|
|
@@ -12148,11 +12802,11 @@ async function walkTfFiles(start, depth = 0, max = 5) {
|
|
|
12148
12802
|
for (const entry of entries) {
|
|
12149
12803
|
if (entry.isDirectory()) {
|
|
12150
12804
|
if (IGNORED_DIRS.has(entry.name) || entry.name === ".terraform") continue;
|
|
12151
|
-
const child =
|
|
12805
|
+
const child = import_node_path53.default.join(start, entry.name);
|
|
12152
12806
|
if (await isPythonVenvDir(child)) continue;
|
|
12153
12807
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
12154
12808
|
} else if (entry.isFile() && entry.name.endsWith(".tf")) {
|
|
12155
|
-
out.push(
|
|
12809
|
+
out.push(import_node_path53.default.join(start, entry.name));
|
|
12156
12810
|
}
|
|
12157
12811
|
}
|
|
12158
12812
|
return out;
|
|
@@ -12184,7 +12838,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
12184
12838
|
const files = await walkTfFiles(scanPath);
|
|
12185
12839
|
for (const file of files) {
|
|
12186
12840
|
const content = await import_node_fs21.promises.readFile(file, "utf8");
|
|
12187
|
-
const evidenceFile = toPosix(
|
|
12841
|
+
const evidenceFile = toPosix(import_node_path53.default.relative(scanPath, file));
|
|
12188
12842
|
const resources = [];
|
|
12189
12843
|
const byKey = /* @__PURE__ */ new Map();
|
|
12190
12844
|
RESOURCE_RE.lastIndex = 0;
|
|
@@ -12219,16 +12873,16 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
12219
12873
|
if (!target) continue;
|
|
12220
12874
|
if (seen.has(target.nodeId)) continue;
|
|
12221
12875
|
seen.add(target.nodeId);
|
|
12222
|
-
const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId,
|
|
12876
|
+
const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types43.EdgeType.DEPENDS_ON);
|
|
12223
12877
|
if (graph.hasEdge(edgeId)) continue;
|
|
12224
12878
|
const line = lineAt2(content, resource.bodyOffset + ref.index);
|
|
12225
12879
|
const edge = {
|
|
12226
12880
|
id: edgeId,
|
|
12227
12881
|
source: resource.nodeId,
|
|
12228
12882
|
target: target.nodeId,
|
|
12229
|
-
type:
|
|
12230
|
-
provenance:
|
|
12231
|
-
confidence: (0,
|
|
12883
|
+
type: import_types43.EdgeType.DEPENDS_ON,
|
|
12884
|
+
provenance: import_types43.Provenance.EXTRACTED,
|
|
12885
|
+
confidence: (0, import_types43.confidenceForExtracted)("structural"),
|
|
12232
12886
|
evidence: { file: evidenceFile, line, snippet: key }
|
|
12233
12887
|
};
|
|
12234
12888
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -12242,7 +12896,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
12242
12896
|
// src/extract/infra/k8s.ts
|
|
12243
12897
|
init_cjs_shims();
|
|
12244
12898
|
var import_node_fs22 = require("fs");
|
|
12245
|
-
var
|
|
12899
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
12246
12900
|
var import_yaml3 = require("yaml");
|
|
12247
12901
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
12248
12902
|
Service: "k8s-service",
|
|
@@ -12260,11 +12914,11 @@ async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
|
12260
12914
|
for (const entry of entries) {
|
|
12261
12915
|
if (entry.isDirectory()) {
|
|
12262
12916
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
12263
|
-
const child =
|
|
12917
|
+
const child = import_node_path54.default.join(start, entry.name);
|
|
12264
12918
|
if (await isPythonVenvDir(child)) continue;
|
|
12265
12919
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
12266
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
12267
|
-
out.push(
|
|
12920
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path54.default.extname(entry.name))) {
|
|
12921
|
+
out.push(import_node_path54.default.join(start, entry.name));
|
|
12268
12922
|
}
|
|
12269
12923
|
}
|
|
12270
12924
|
return out;
|
|
@@ -12298,13 +12952,13 @@ async function addK8sResources(graph, scanPath) {
|
|
|
12298
12952
|
// src/extract/infra/cloudflare.ts
|
|
12299
12953
|
init_cjs_shims();
|
|
12300
12954
|
var import_node_fs23 = require("fs");
|
|
12301
|
-
var
|
|
12955
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
12302
12956
|
var import_smol_toml2 = require("smol-toml");
|
|
12303
|
-
var
|
|
12957
|
+
var import_types44 = require("@neat.is/types");
|
|
12304
12958
|
var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
|
|
12305
12959
|
async function readWranglerConfig(dir) {
|
|
12306
12960
|
for (const filename of WRANGLER_FILENAMES) {
|
|
12307
|
-
const abs =
|
|
12961
|
+
const abs = import_node_path55.default.join(dir, filename);
|
|
12308
12962
|
if (!await exists2(abs)) continue;
|
|
12309
12963
|
const raw = await import_node_fs23.promises.readFile(abs, "utf8");
|
|
12310
12964
|
const config = filename === "wrangler.toml" ? (0, import_smol_toml2.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
@@ -12348,8 +13002,8 @@ function addResourceEdge(graph, anchorId, edgeType, kind, name, evidenceFile, li
|
|
|
12348
13002
|
source: anchorId,
|
|
12349
13003
|
target: node.id,
|
|
12350
13004
|
type: edgeType,
|
|
12351
|
-
provenance:
|
|
12352
|
-
confidence: (0,
|
|
13005
|
+
provenance: import_types44.Provenance.EXTRACTED,
|
|
13006
|
+
confidence: (0, import_types44.confidenceForExtracted)("structural"),
|
|
12353
13007
|
evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
|
|
12354
13008
|
};
|
|
12355
13009
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -12367,11 +13021,11 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12367
13021
|
try {
|
|
12368
13022
|
read = await readWranglerConfig(service.dir);
|
|
12369
13023
|
} catch (err) {
|
|
12370
|
-
recordExtractionError("infra cloudflare",
|
|
13024
|
+
recordExtractionError("infra cloudflare", import_node_path55.default.relative(scanPath, service.dir), err);
|
|
12371
13025
|
continue;
|
|
12372
13026
|
}
|
|
12373
13027
|
if (!read || !read.config.name) continue;
|
|
12374
|
-
const evidenceFile = toPosix(
|
|
13028
|
+
const evidenceFile = toPosix(import_node_path55.default.relative(scanPath, import_node_path55.default.join(service.dir, read.relFile)));
|
|
12375
13029
|
discovered.push({ service, config: read.config, relFile: read.relFile, raw: read.raw, evidenceFile });
|
|
12376
13030
|
}
|
|
12377
13031
|
for (const worker of discovered) {
|
|
@@ -12383,7 +13037,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12383
13037
|
}
|
|
12384
13038
|
let anchorId = service.node.id;
|
|
12385
13039
|
if (config.main) {
|
|
12386
|
-
const entryRelPath = toPosix(
|
|
13040
|
+
const entryRelPath = toPosix(import_node_path55.default.normalize(config.main));
|
|
12387
13041
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
12388
13042
|
graph,
|
|
12389
13043
|
service.pkg.name,
|
|
@@ -12410,15 +13064,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12410
13064
|
nodesAdded++;
|
|
12411
13065
|
}
|
|
12412
13066
|
if (runtimeNode.id !== anchorId) {
|
|
12413
|
-
const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id,
|
|
13067
|
+
const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types44.EdgeType.RUNS_ON);
|
|
12414
13068
|
if (!graph.hasEdge(runsOnId)) {
|
|
12415
13069
|
const edge = {
|
|
12416
13070
|
id: runsOnId,
|
|
12417
13071
|
source: anchorId,
|
|
12418
13072
|
target: runtimeNode.id,
|
|
12419
|
-
type:
|
|
12420
|
-
provenance:
|
|
12421
|
-
confidence: (0,
|
|
13073
|
+
type: import_types44.EdgeType.RUNS_ON,
|
|
13074
|
+
provenance: import_types44.Provenance.EXTRACTED,
|
|
13075
|
+
confidence: (0, import_types44.confidenceForExtracted)("structural"),
|
|
12422
13076
|
evidence: {
|
|
12423
13077
|
file: evidenceFile,
|
|
12424
13078
|
...config.compatibility_date ? { snippet: `compatibility_date = ${config.compatibility_date}`.slice(0, 120) } : {}
|
|
@@ -12432,7 +13086,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12432
13086
|
const result = addResourceEdge(
|
|
12433
13087
|
graph,
|
|
12434
13088
|
anchorId,
|
|
12435
|
-
|
|
13089
|
+
import_types44.EdgeType.CONNECTS_TO,
|
|
12436
13090
|
"cloudflare-route",
|
|
12437
13091
|
route,
|
|
12438
13092
|
evidenceFile,
|
|
@@ -12456,7 +13110,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12456
13110
|
const result = addResourceEdge(
|
|
12457
13111
|
graph,
|
|
12458
13112
|
anchorId,
|
|
12459
|
-
|
|
13113
|
+
import_types44.EdgeType.DEPENDS_ON,
|
|
12460
13114
|
group.kind,
|
|
12461
13115
|
name,
|
|
12462
13116
|
evidenceFile,
|
|
@@ -12470,7 +13124,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12470
13124
|
const result = addResourceEdge(
|
|
12471
13125
|
graph,
|
|
12472
13126
|
anchorId,
|
|
12473
|
-
|
|
13127
|
+
import_types44.EdgeType.DEPENDS_ON,
|
|
12474
13128
|
"cloudflare-cron",
|
|
12475
13129
|
cron,
|
|
12476
13130
|
evidenceFile,
|
|
@@ -12483,7 +13137,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12483
13137
|
const result = addResourceEdge(
|
|
12484
13138
|
graph,
|
|
12485
13139
|
anchorId,
|
|
12486
|
-
|
|
13140
|
+
import_types44.EdgeType.DEPENDS_ON,
|
|
12487
13141
|
"cloudflare-env-var",
|
|
12488
13142
|
varName,
|
|
12489
13143
|
evidenceFile,
|
|
@@ -12496,15 +13150,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12496
13150
|
if (!svc.service) continue;
|
|
12497
13151
|
const target = workerIndex.get(svc.service);
|
|
12498
13152
|
if (target && target.anchorId !== anchorId) {
|
|
12499
|
-
const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId,
|
|
13153
|
+
const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types44.EdgeType.CALLS);
|
|
12500
13154
|
if (!graph.hasEdge(edgeId)) {
|
|
12501
13155
|
const edge = {
|
|
12502
13156
|
id: edgeId,
|
|
12503
13157
|
source: anchorId,
|
|
12504
13158
|
target: target.anchorId,
|
|
12505
|
-
type:
|
|
12506
|
-
provenance:
|
|
12507
|
-
confidence: (0,
|
|
13159
|
+
type: import_types44.EdgeType.CALLS,
|
|
13160
|
+
provenance: import_types44.Provenance.EXTRACTED,
|
|
13161
|
+
confidence: (0, import_types44.confidenceForExtracted)("structural"),
|
|
12508
13162
|
evidence: { file: evidenceFile, line: lineContaining2(raw, svc.service) }
|
|
12509
13163
|
};
|
|
12510
13164
|
graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
|
|
@@ -12515,7 +13169,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12515
13169
|
const result = addResourceEdge(
|
|
12516
13170
|
graph,
|
|
12517
13171
|
anchorId,
|
|
12518
|
-
|
|
13172
|
+
import_types44.EdgeType.DEPENDS_ON,
|
|
12519
13173
|
"cloudflare-service-binding",
|
|
12520
13174
|
svc.service,
|
|
12521
13175
|
evidenceFile,
|
|
@@ -12531,12 +13185,12 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
12531
13185
|
// src/extract/infra/vercel.ts
|
|
12532
13186
|
init_cjs_shims();
|
|
12533
13187
|
var import_node_fs24 = require("fs");
|
|
12534
|
-
var
|
|
12535
|
-
var
|
|
13188
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
13189
|
+
var import_types45 = require("@neat.is/types");
|
|
12536
13190
|
var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
|
|
12537
13191
|
async function readVercelConfig(dir) {
|
|
12538
13192
|
for (const filename of VERCEL_CONFIG_FILENAMES) {
|
|
12539
|
-
const abs =
|
|
13193
|
+
const abs = import_node_path56.default.join(dir, filename);
|
|
12540
13194
|
if (!await exists2(abs)) continue;
|
|
12541
13195
|
const raw = await import_node_fs24.promises.readFile(abs, "utf8");
|
|
12542
13196
|
const config = JSON.parse(maskCommentsInSource(raw));
|
|
@@ -12545,7 +13199,7 @@ async function readVercelConfig(dir) {
|
|
|
12545
13199
|
return null;
|
|
12546
13200
|
}
|
|
12547
13201
|
async function readLinkedProjectName(dir) {
|
|
12548
|
-
const abs =
|
|
13202
|
+
const abs = import_node_path56.default.join(dir, ".vercel", "project.json");
|
|
12549
13203
|
if (!await exists2(abs)) return void 0;
|
|
12550
13204
|
const parsed = JSON.parse(await import_node_fs24.promises.readFile(abs, "utf8"));
|
|
12551
13205
|
return typeof parsed.projectName === "string" ? parsed.projectName : void 0;
|
|
@@ -12563,7 +13217,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
12563
13217
|
read = await readVercelConfig(service.dir);
|
|
12564
13218
|
projectName = await readLinkedProjectName(service.dir);
|
|
12565
13219
|
} catch (err) {
|
|
12566
|
-
recordExtractionError("infra vercel",
|
|
13220
|
+
recordExtractionError("infra vercel", import_node_path56.default.relative(scanPath, service.dir), err);
|
|
12567
13221
|
continue;
|
|
12568
13222
|
}
|
|
12569
13223
|
if (!read && !projectName) continue;
|
|
@@ -12579,7 +13233,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
12579
13233
|
const anchorId = service.node.id;
|
|
12580
13234
|
if (!read) continue;
|
|
12581
13235
|
const { config, relFile, raw } = read;
|
|
12582
|
-
const evidenceFile = toPosix(
|
|
13236
|
+
const evidenceFile = toPosix(import_node_path56.default.relative(scanPath, import_node_path56.default.join(service.dir, relFile)));
|
|
12583
13237
|
const add = (edgeType, kind, name) => {
|
|
12584
13238
|
if (!name) return;
|
|
12585
13239
|
const result = emitPlatformResourceEdge(
|
|
@@ -12595,12 +13249,12 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
12595
13249
|
nodesAdded += result.nodesAdded;
|
|
12596
13250
|
edgesAdded += result.edgesAdded;
|
|
12597
13251
|
};
|
|
12598
|
-
add(
|
|
12599
|
-
for (const cron of config.crons ?? []) add(
|
|
12600
|
-
for (const varName of Object.keys(config.env ?? {})) add(
|
|
12601
|
-
for (const varName of Object.keys(config.build?.env ?? {})) add(
|
|
13252
|
+
add(import_types45.EdgeType.RUNS_ON, "vercel", "vercel");
|
|
13253
|
+
for (const cron of config.crons ?? []) add(import_types45.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
|
|
13254
|
+
for (const varName of Object.keys(config.env ?? {})) add(import_types45.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
13255
|
+
for (const varName of Object.keys(config.build?.env ?? {})) add(import_types45.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
|
|
12602
13256
|
for (const route of [...config.rewrites ?? [], ...config.redirects ?? [], ...config.routes ?? []]) {
|
|
12603
|
-
add(
|
|
13257
|
+
add(import_types45.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
|
|
12604
13258
|
}
|
|
12605
13259
|
}
|
|
12606
13260
|
return { nodesAdded, edgesAdded };
|
|
@@ -12609,13 +13263,13 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
12609
13263
|
// src/extract/infra/railway.ts
|
|
12610
13264
|
init_cjs_shims();
|
|
12611
13265
|
var import_node_fs25 = require("fs");
|
|
12612
|
-
var
|
|
13266
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
12613
13267
|
var import_smol_toml3 = require("smol-toml");
|
|
12614
|
-
var
|
|
13268
|
+
var import_types46 = require("@neat.is/types");
|
|
12615
13269
|
var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
|
|
12616
13270
|
async function readRailwayConfig(dir) {
|
|
12617
13271
|
for (const filename of RAILWAY_FILENAMES) {
|
|
12618
|
-
const abs =
|
|
13272
|
+
const abs = import_node_path57.default.join(dir, filename);
|
|
12619
13273
|
if (!await exists2(abs)) continue;
|
|
12620
13274
|
const raw = await import_node_fs25.promises.readFile(abs, "utf8");
|
|
12621
13275
|
const config = filename === "railway.toml" ? (0, import_smol_toml3.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
@@ -12631,7 +13285,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
12631
13285
|
try {
|
|
12632
13286
|
read = await readRailwayConfig(service.dir);
|
|
12633
13287
|
} catch (err) {
|
|
12634
|
-
recordExtractionError("infra railway",
|
|
13288
|
+
recordExtractionError("infra railway", import_node_path57.default.relative(scanPath, service.dir), err);
|
|
12635
13289
|
continue;
|
|
12636
13290
|
}
|
|
12637
13291
|
if (!read) continue;
|
|
@@ -12641,7 +13295,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
12641
13295
|
}
|
|
12642
13296
|
const anchorId = service.node.id;
|
|
12643
13297
|
const { config, relFile, raw } = read;
|
|
12644
|
-
const evidenceFile = toPosix(
|
|
13298
|
+
const evidenceFile = toPosix(import_node_path57.default.relative(scanPath, import_node_path57.default.join(service.dir, relFile)));
|
|
12645
13299
|
const add = (edgeType, kind, name) => {
|
|
12646
13300
|
if (!name) return;
|
|
12647
13301
|
const result = emitPlatformResourceEdge(
|
|
@@ -12657,9 +13311,9 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
12657
13311
|
nodesAdded += result.nodesAdded;
|
|
12658
13312
|
edgesAdded += result.edgesAdded;
|
|
12659
13313
|
};
|
|
12660
|
-
add(
|
|
12661
|
-
add(
|
|
12662
|
-
add(
|
|
13314
|
+
add(import_types46.EdgeType.RUNS_ON, "railway", "railway");
|
|
13315
|
+
add(import_types46.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
|
|
13316
|
+
add(import_types46.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
|
|
12663
13317
|
}
|
|
12664
13318
|
return { nodesAdded, edgesAdded };
|
|
12665
13319
|
}
|
|
@@ -12667,12 +13321,12 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
12667
13321
|
// src/extract/infra/supabase.ts
|
|
12668
13322
|
init_cjs_shims();
|
|
12669
13323
|
var import_node_fs26 = require("fs");
|
|
12670
|
-
var
|
|
13324
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
12671
13325
|
var import_smol_toml4 = require("smol-toml");
|
|
12672
|
-
var
|
|
13326
|
+
var import_types47 = require("@neat.is/types");
|
|
12673
13327
|
async function readSupabaseConfig(dir) {
|
|
12674
|
-
const relFile =
|
|
12675
|
-
const abs =
|
|
13328
|
+
const relFile = import_node_path58.default.join("supabase", "config.toml");
|
|
13329
|
+
const abs = import_node_path58.default.join(dir, relFile);
|
|
12676
13330
|
if (!await exists2(abs)) return null;
|
|
12677
13331
|
const raw = await import_node_fs26.promises.readFile(abs, "utf8");
|
|
12678
13332
|
const config = (0, import_smol_toml4.parse)(raw);
|
|
@@ -12686,7 +13340,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
12686
13340
|
try {
|
|
12687
13341
|
read = await readSupabaseConfig(service.dir);
|
|
12688
13342
|
} catch (err) {
|
|
12689
|
-
recordExtractionError("infra supabase",
|
|
13343
|
+
recordExtractionError("infra supabase", import_node_path58.default.relative(scanPath, service.dir), err);
|
|
12690
13344
|
continue;
|
|
12691
13345
|
}
|
|
12692
13346
|
if (!read) continue;
|
|
@@ -12701,7 +13355,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
12701
13355
|
});
|
|
12702
13356
|
}
|
|
12703
13357
|
const anchorId = service.node.id;
|
|
12704
|
-
const evidenceFile = toPosix(
|
|
13358
|
+
const evidenceFile = toPosix(import_node_path58.default.relative(scanPath, import_node_path58.default.join(service.dir, relFile)));
|
|
12705
13359
|
const add = (edgeType, kind, name) => {
|
|
12706
13360
|
if (!name) return;
|
|
12707
13361
|
const result = emitPlatformResourceEdge(
|
|
@@ -12717,10 +13371,10 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
12717
13371
|
nodesAdded += result.nodesAdded;
|
|
12718
13372
|
edgesAdded += result.edgesAdded;
|
|
12719
13373
|
};
|
|
12720
|
-
add(
|
|
12721
|
-
for (const fn of Object.keys(config.functions ?? {})) add(
|
|
12722
|
-
if (config.storage) add(
|
|
12723
|
-
if (config.auth) add(
|
|
13374
|
+
add(import_types47.EdgeType.RUNS_ON, "supabase", "supabase");
|
|
13375
|
+
for (const fn of Object.keys(config.functions ?? {})) add(import_types47.EdgeType.DEPENDS_ON, "supabase-function", fn);
|
|
13376
|
+
if (config.storage) add(import_types47.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
|
|
13377
|
+
if (config.auth) add(import_types47.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
|
|
12724
13378
|
}
|
|
12725
13379
|
return { nodesAdded, edgesAdded };
|
|
12726
13380
|
}
|
|
@@ -12743,14 +13397,14 @@ async function addInfra(graph, scanPath, services) {
|
|
|
12743
13397
|
|
|
12744
13398
|
// src/extract/zod-shapes.ts
|
|
12745
13399
|
init_cjs_shims();
|
|
12746
|
-
var
|
|
12747
|
-
var
|
|
13400
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
13401
|
+
var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
|
|
12748
13402
|
var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
|
|
12749
|
-
var
|
|
13403
|
+
var import_types48 = require("@neat.is/types");
|
|
12750
13404
|
var ZOD_IMPORT_RE = /\bzod\b/;
|
|
12751
13405
|
var ZOD_OBJECTS = /* @__PURE__ */ new Set(["z", "zod"]);
|
|
12752
13406
|
function parserForExt3(ext) {
|
|
12753
|
-
const p = new
|
|
13407
|
+
const p = new import_tree_sitter16.default();
|
|
12754
13408
|
p.setLanguage(GRAMMAR_BY_EXT[ext] ?? import_tree_sitter_javascript8.default);
|
|
12755
13409
|
return p;
|
|
12756
13410
|
}
|
|
@@ -12838,7 +13492,7 @@ function topLevelSchemas(root) {
|
|
|
12838
13492
|
}
|
|
12839
13493
|
function zodShapesFromFile(file, serviceDir) {
|
|
12840
13494
|
if (!ZOD_IMPORT_RE.test(file.content)) return [];
|
|
12841
|
-
const tree = parseSource3(parserForExt3(
|
|
13495
|
+
const tree = parseSource3(parserForExt3(import_node_path59.default.extname(file.path)), file.content);
|
|
12842
13496
|
const out = [];
|
|
12843
13497
|
const seen = /* @__PURE__ */ new Set();
|
|
12844
13498
|
for (const { name, call } of topLevelSchemas(tree.rootNode)) {
|
|
@@ -12852,11 +13506,11 @@ function zodShapesFromFile(file, serviceDir) {
|
|
|
12852
13506
|
seen.add(name);
|
|
12853
13507
|
const line = call.startPosition.row + 1;
|
|
12854
13508
|
out.push({
|
|
12855
|
-
infraId: (0,
|
|
13509
|
+
infraId: (0, import_types48.infraId)("zod-schema", name),
|
|
12856
13510
|
name,
|
|
12857
13511
|
fields,
|
|
12858
13512
|
evidence: {
|
|
12859
|
-
file:
|
|
13513
|
+
file: import_node_path59.default.relative(serviceDir, file.path),
|
|
12860
13514
|
line,
|
|
12861
13515
|
snippet: snippet(file.content, line)
|
|
12862
13516
|
}
|
|
@@ -12887,7 +13541,7 @@ async function addZodShapes(graph, services) {
|
|
|
12887
13541
|
if (!graph.hasNode(shape.infraId)) {
|
|
12888
13542
|
const node = {
|
|
12889
13543
|
id: shape.infraId,
|
|
12890
|
-
type:
|
|
13544
|
+
type: import_types48.NodeType.InfraNode,
|
|
12891
13545
|
name: shape.name,
|
|
12892
13546
|
provider: "self",
|
|
12893
13547
|
kind: "zod-schema"
|
|
@@ -12897,14 +13551,14 @@ async function addZodShapes(graph, services) {
|
|
|
12897
13551
|
}
|
|
12898
13552
|
if (shape.fields.length > 0) {
|
|
12899
13553
|
const node = graph.getNodeAttributes(shape.infraId);
|
|
12900
|
-
if (node.type ===
|
|
13554
|
+
if (node.type === import_types48.NodeType.InfraNode) {
|
|
12901
13555
|
graph.replaceNodeAttributes(shape.infraId, {
|
|
12902
13556
|
...node,
|
|
12903
13557
|
columns: foldColumns(
|
|
12904
13558
|
node.columns,
|
|
12905
13559
|
shape.fields,
|
|
12906
|
-
|
|
12907
|
-
(0,
|
|
13560
|
+
import_types48.Provenance.EXTRACTED,
|
|
13561
|
+
(0, import_types48.confidenceForExtracted)("structural")
|
|
12908
13562
|
)
|
|
12909
13563
|
});
|
|
12910
13564
|
}
|
|
@@ -12918,15 +13572,15 @@ async function addZodShapes(graph, services) {
|
|
|
12918
13572
|
);
|
|
12919
13573
|
nodesAdded += n;
|
|
12920
13574
|
edgesAdded += e;
|
|
12921
|
-
const edgeId = (0,
|
|
13575
|
+
const edgeId = (0, import_types48.extractedEdgeId)(fileNodeId, shape.infraId, import_types48.EdgeType.CONTAINS);
|
|
12922
13576
|
if (!graph.hasEdge(edgeId)) {
|
|
12923
13577
|
const edge = {
|
|
12924
13578
|
id: edgeId,
|
|
12925
13579
|
source: fileNodeId,
|
|
12926
13580
|
target: shape.infraId,
|
|
12927
|
-
type:
|
|
12928
|
-
provenance:
|
|
12929
|
-
confidence: (0,
|
|
13581
|
+
type: import_types48.EdgeType.CONTAINS,
|
|
13582
|
+
provenance: import_types48.Provenance.EXTRACTED,
|
|
13583
|
+
confidence: (0, import_types48.confidenceForExtracted)("structural"),
|
|
12930
13584
|
evidence: shape.evidence
|
|
12931
13585
|
};
|
|
12932
13586
|
graph.addEdgeWithKey(edgeId, fileNodeId, shape.infraId, edge);
|
|
@@ -12940,7 +13594,7 @@ async function addZodShapes(graph, services) {
|
|
|
12940
13594
|
|
|
12941
13595
|
// src/extract/firestore-rules.ts
|
|
12942
13596
|
init_cjs_shims();
|
|
12943
|
-
var
|
|
13597
|
+
var import_types49 = require("@neat.is/types");
|
|
12944
13598
|
var FIRESTORE_COLLECTION_KIND = "firestore-collection";
|
|
12945
13599
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["write", "create", "update"]);
|
|
12946
13600
|
function stripComments(src) {
|
|
@@ -13080,7 +13734,7 @@ async function addFirestoreRules(graph, services) {
|
|
|
13080
13734
|
if (guards.size === 0) return { nodesAdded: 0, edgesAdded: 0 };
|
|
13081
13735
|
graph.forEachNode((id, attrs) => {
|
|
13082
13736
|
const node = attrs;
|
|
13083
|
-
if (node.type !==
|
|
13737
|
+
if (node.type !== import_types49.NodeType.InfraNode) return;
|
|
13084
13738
|
if (node.kind !== FIRESTORE_COLLECTION_KIND) return;
|
|
13085
13739
|
const fields = guards.get(collectionKeyFromName(node.name));
|
|
13086
13740
|
if (!fields || fields.size === 0) return;
|
|
@@ -13093,17 +13747,17 @@ async function addFirestoreRules(graph, services) {
|
|
|
13093
13747
|
}
|
|
13094
13748
|
|
|
13095
13749
|
// src/extract/index.ts
|
|
13096
|
-
var
|
|
13750
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
13097
13751
|
|
|
13098
13752
|
// src/extract/retire.ts
|
|
13099
13753
|
init_cjs_shims();
|
|
13100
13754
|
var import_node_fs27 = require("fs");
|
|
13101
|
-
var
|
|
13102
|
-
var
|
|
13755
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
13756
|
+
var import_types50 = require("@neat.is/types");
|
|
13103
13757
|
function dropOrphanedFileNodes(graph) {
|
|
13104
13758
|
const orphans = [];
|
|
13105
13759
|
graph.forEachNode((id, attrs) => {
|
|
13106
|
-
if (attrs.type !==
|
|
13760
|
+
if (attrs.type !== import_types50.NodeType.FileNode) return;
|
|
13107
13761
|
if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
|
|
13108
13762
|
orphans.push(id);
|
|
13109
13763
|
}
|
|
@@ -13116,14 +13770,14 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
13116
13770
|
const bases = [scanPath, ...serviceDirs];
|
|
13117
13771
|
graph.forEachEdge((id, attrs) => {
|
|
13118
13772
|
const edge = attrs;
|
|
13119
|
-
if (edge.provenance !==
|
|
13773
|
+
if (edge.provenance !== import_types50.Provenance.EXTRACTED) return;
|
|
13120
13774
|
const evidenceFile = edge.evidence?.file;
|
|
13121
13775
|
if (!evidenceFile) return;
|
|
13122
|
-
if (
|
|
13776
|
+
if (import_node_path60.default.isAbsolute(evidenceFile)) {
|
|
13123
13777
|
if (!(0, import_node_fs27.existsSync)(evidenceFile)) toDrop.push(id);
|
|
13124
13778
|
return;
|
|
13125
13779
|
}
|
|
13126
|
-
const found = bases.some((base) => (0, import_node_fs27.existsSync)(
|
|
13780
|
+
const found = bases.some((base) => (0, import_node_fs27.existsSync)(import_node_path60.default.join(base, evidenceFile)));
|
|
13127
13781
|
if (!found) toDrop.push(id);
|
|
13128
13782
|
});
|
|
13129
13783
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -13180,7 +13834,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
13180
13834
|
}
|
|
13181
13835
|
const droppedEntries = drainDroppedExtracted();
|
|
13182
13836
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
13183
|
-
const rejectedPath =
|
|
13837
|
+
const rejectedPath = import_node_path61.default.join(import_node_path61.default.dirname(opts.errorsPath), "rejected.ndjson");
|
|
13184
13838
|
try {
|
|
13185
13839
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
13186
13840
|
} catch (err) {
|
|
@@ -13292,8 +13946,8 @@ function canonicalJson(value) {
|
|
|
13292
13946
|
// src/persist.ts
|
|
13293
13947
|
init_cjs_shims();
|
|
13294
13948
|
var import_node_fs29 = require("fs");
|
|
13295
|
-
var
|
|
13296
|
-
var
|
|
13949
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
13950
|
+
var import_types51 = require("@neat.is/types");
|
|
13297
13951
|
var SCHEMA_VERSION = 7;
|
|
13298
13952
|
function migrateV1ToV2(payload) {
|
|
13299
13953
|
const nodes = payload.graph.nodes;
|
|
@@ -13317,7 +13971,7 @@ function migrateV5ToV6(payload) {
|
|
|
13317
13971
|
if (Array.isArray(nodes)) {
|
|
13318
13972
|
for (const node of nodes) {
|
|
13319
13973
|
const attrs = node.attributes;
|
|
13320
|
-
if (!attrs || attrs.type !==
|
|
13974
|
+
if (!attrs || attrs.type !== import_types51.NodeType.InfraNode) continue;
|
|
13321
13975
|
if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
|
|
13322
13976
|
if (!Array.isArray(attrs.columns)) attrs.columns = [];
|
|
13323
13977
|
}
|
|
@@ -13333,12 +13987,12 @@ function migrateV2ToV3(payload) {
|
|
|
13333
13987
|
for (const edge of edges) {
|
|
13334
13988
|
const attrs = edge.attributes;
|
|
13335
13989
|
if (!attrs || attrs.provenance !== "FRONTIER") continue;
|
|
13336
|
-
attrs.provenance =
|
|
13990
|
+
attrs.provenance = import_types51.Provenance.OBSERVED;
|
|
13337
13991
|
const type = typeof attrs.type === "string" ? attrs.type : void 0;
|
|
13338
13992
|
const source = typeof attrs.source === "string" ? attrs.source : void 0;
|
|
13339
13993
|
const target = typeof attrs.target === "string" ? attrs.target : void 0;
|
|
13340
13994
|
if (type && source && target) {
|
|
13341
|
-
const newId = (0,
|
|
13995
|
+
const newId = (0, import_types51.observedEdgeId)(source, target, type);
|
|
13342
13996
|
attrs.id = newId;
|
|
13343
13997
|
if (edge.key) edge.key = newId;
|
|
13344
13998
|
}
|
|
@@ -13347,7 +14001,7 @@ function migrateV2ToV3(payload) {
|
|
|
13347
14001
|
return { ...payload, schemaVersion: 3 };
|
|
13348
14002
|
}
|
|
13349
14003
|
async function ensureDir(filePath) {
|
|
13350
|
-
await import_node_fs29.promises.mkdir(
|
|
14004
|
+
await import_node_fs29.promises.mkdir(import_node_path62.default.dirname(filePath), { recursive: true });
|
|
13351
14005
|
}
|
|
13352
14006
|
async function saveGraphToDisk(graph, outPath) {
|
|
13353
14007
|
await ensureDir(outPath);
|
|
@@ -13437,23 +14091,23 @@ function startPersistLoop(graph, outPath, opts = {}) {
|
|
|
13437
14091
|
|
|
13438
14092
|
// src/projects.ts
|
|
13439
14093
|
init_cjs_shims();
|
|
13440
|
-
var
|
|
14094
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
13441
14095
|
function pathsForProject(project, baseDir) {
|
|
13442
14096
|
if (project === DEFAULT_PROJECT) {
|
|
13443
14097
|
return {
|
|
13444
|
-
snapshotPath:
|
|
13445
|
-
errorsPath:
|
|
13446
|
-
staleEventsPath:
|
|
13447
|
-
embeddingsCachePath:
|
|
13448
|
-
policyViolationsPath:
|
|
14098
|
+
snapshotPath: import_node_path63.default.join(baseDir, "graph.json"),
|
|
14099
|
+
errorsPath: import_node_path63.default.join(baseDir, "errors.ndjson"),
|
|
14100
|
+
staleEventsPath: import_node_path63.default.join(baseDir, "stale-events.ndjson"),
|
|
14101
|
+
embeddingsCachePath: import_node_path63.default.join(baseDir, "embeddings.json"),
|
|
14102
|
+
policyViolationsPath: import_node_path63.default.join(baseDir, "policy-violations.ndjson")
|
|
13449
14103
|
};
|
|
13450
14104
|
}
|
|
13451
14105
|
return {
|
|
13452
|
-
snapshotPath:
|
|
13453
|
-
errorsPath:
|
|
13454
|
-
staleEventsPath:
|
|
13455
|
-
embeddingsCachePath:
|
|
13456
|
-
policyViolationsPath:
|
|
14106
|
+
snapshotPath: import_node_path63.default.join(baseDir, `${project}.json`),
|
|
14107
|
+
errorsPath: import_node_path63.default.join(baseDir, `errors.${project}.ndjson`),
|
|
14108
|
+
staleEventsPath: import_node_path63.default.join(baseDir, `stale-events.${project}.ndjson`),
|
|
14109
|
+
embeddingsCachePath: import_node_path63.default.join(baseDir, `embeddings.${project}.json`),
|
|
14110
|
+
policyViolationsPath: import_node_path63.default.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
13457
14111
|
};
|
|
13458
14112
|
}
|
|
13459
14113
|
var Projects = class {
|
|
@@ -13495,18 +14149,18 @@ function parseExtraProjects(raw) {
|
|
|
13495
14149
|
init_cjs_shims();
|
|
13496
14150
|
var import_node_fs30 = require("fs");
|
|
13497
14151
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
13498
|
-
var
|
|
13499
|
-
var
|
|
14152
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
14153
|
+
var import_types52 = require("@neat.is/types");
|
|
13500
14154
|
function neatHome() {
|
|
13501
14155
|
const override = process.env.NEAT_HOME;
|
|
13502
|
-
if (override && override.length > 0) return
|
|
13503
|
-
return
|
|
14156
|
+
if (override && override.length > 0) return import_node_path64.default.resolve(override);
|
|
14157
|
+
return import_node_path64.default.join(import_node_os3.default.homedir(), ".neat");
|
|
13504
14158
|
}
|
|
13505
14159
|
function registryPath() {
|
|
13506
|
-
return
|
|
14160
|
+
return import_node_path64.default.join(neatHome(), "projects.json");
|
|
13507
14161
|
}
|
|
13508
14162
|
function daemonsDir() {
|
|
13509
|
-
return
|
|
14163
|
+
return import_node_path64.default.join(neatHome(), "daemons");
|
|
13510
14164
|
}
|
|
13511
14165
|
function isFiniteInt(v) {
|
|
13512
14166
|
return typeof v === "number" && Number.isFinite(v);
|
|
@@ -13547,7 +14201,7 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
13547
14201
|
const out = [];
|
|
13548
14202
|
for (const name of names) {
|
|
13549
14203
|
if (!name.endsWith(".json")) continue;
|
|
13550
|
-
const file =
|
|
14204
|
+
const file = import_node_path64.default.join(dir, name);
|
|
13551
14205
|
let raw;
|
|
13552
14206
|
try {
|
|
13553
14207
|
raw = await import_node_fs30.promises.readFile(file, "utf8");
|
|
@@ -13586,7 +14240,7 @@ async function readRegistry() {
|
|
|
13586
14240
|
throw err;
|
|
13587
14241
|
}
|
|
13588
14242
|
const parsed = JSON.parse(raw);
|
|
13589
|
-
return
|
|
14243
|
+
return import_types52.RegistryFileSchema.parse(parsed);
|
|
13590
14244
|
}
|
|
13591
14245
|
async function getProject(name) {
|
|
13592
14246
|
const reg = await readRegistry();
|
|
@@ -13661,7 +14315,7 @@ init_auth();
|
|
|
13661
14315
|
// src/connectors-config.ts
|
|
13662
14316
|
init_cjs_shims();
|
|
13663
14317
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
13664
|
-
var
|
|
14318
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
13665
14319
|
var import_node_fs31 = require("fs");
|
|
13666
14320
|
var CONNECTORS_CONFIG_VERSION = 1;
|
|
13667
14321
|
var EnvRefUnsetError = class extends Error {
|
|
@@ -13676,11 +14330,11 @@ var EnvRefUnsetError = class extends Error {
|
|
|
13676
14330
|
};
|
|
13677
14331
|
function neatHome2() {
|
|
13678
14332
|
const override = process.env.NEAT_HOME;
|
|
13679
|
-
if (override && override.length > 0) return
|
|
13680
|
-
return
|
|
14333
|
+
if (override && override.length > 0) return import_node_path65.default.resolve(override);
|
|
14334
|
+
return import_node_path65.default.join(import_node_os4.default.homedir(), ".neat");
|
|
13681
14335
|
}
|
|
13682
14336
|
function connectorsConfigPath(home = neatHome2()) {
|
|
13683
|
-
return
|
|
14337
|
+
return import_node_path65.default.join(home, "connectors.json");
|
|
13684
14338
|
}
|
|
13685
14339
|
var MODE_MASK_LOOSER_THAN_0600 = 63;
|
|
13686
14340
|
async function warnIfModeLooserThan0600(file) {
|
|
@@ -13867,15 +14521,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
|
|
|
13867
14521
|
|
|
13868
14522
|
// src/connectors/index.ts
|
|
13869
14523
|
init_cjs_shims();
|
|
13870
|
-
var
|
|
14524
|
+
var import_types53 = require("@neat.is/types");
|
|
13871
14525
|
var NO_ENV = "unknown";
|
|
13872
14526
|
function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
13873
14527
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
13874
14528
|
const sites = [];
|
|
13875
14529
|
for (const edgeId of graph.inboundEdges(targetNodeId)) {
|
|
13876
14530
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
13877
|
-
if (edge.provenance !==
|
|
13878
|
-
const parsed = (0,
|
|
14531
|
+
if (edge.provenance !== import_types53.Provenance.EXTRACTED) continue;
|
|
14532
|
+
const parsed = (0, import_types53.parseFileId)(edge.source);
|
|
13879
14533
|
if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
|
|
13880
14534
|
const site = { relPath: edge.evidence.file };
|
|
13881
14535
|
if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
|
|
@@ -13886,7 +14540,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
|
13886
14540
|
function routeCallSiteFor(graph, targetNodeId) {
|
|
13887
14541
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
13888
14542
|
const attrs = graph.getNodeAttributes(targetNodeId);
|
|
13889
|
-
if (attrs.type !==
|
|
14543
|
+
if (attrs.type !== import_types53.NodeType.RouteNode || !attrs.path) return void 0;
|
|
13890
14544
|
const site = { relPath: attrs.path };
|
|
13891
14545
|
if (attrs.line !== void 0) site.line = attrs.line;
|
|
13892
14546
|
return site;
|
|
@@ -14326,10 +14980,10 @@ var SUPABASE_RPC_TARGET_KIND = "supabase-rpc";
|
|
|
14326
14980
|
// src/connectors/supabase/map.ts
|
|
14327
14981
|
var REST_RPC_PATH_RE = /^\/rest\/v1\/rpc\/([^/?]+)/;
|
|
14328
14982
|
var REST_TABLE_PATH_RE = /^\/rest\/v1\/([^/?]+)/;
|
|
14329
|
-
function targetFromRestPath(
|
|
14330
|
-
const rpcMatch = REST_RPC_PATH_RE.exec(
|
|
14983
|
+
function targetFromRestPath(path68) {
|
|
14984
|
+
const rpcMatch = REST_RPC_PATH_RE.exec(path68);
|
|
14331
14985
|
if (rpcMatch) return { targetKind: SUPABASE_RPC_TARGET_KIND, name: rpcMatch[1] };
|
|
14332
|
-
const tableMatch = REST_TABLE_PATH_RE.exec(
|
|
14986
|
+
const tableMatch = REST_TABLE_PATH_RE.exec(path68);
|
|
14333
14987
|
if (tableMatch) return { targetKind: SUPABASE_TABLE_TARGET_KIND, name: tableMatch[1] };
|
|
14334
14988
|
return null;
|
|
14335
14989
|
}
|
|
@@ -14440,23 +15094,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
|
|
|
14440
15094
|
|
|
14441
15095
|
// src/connectors/supabase/resolve.ts
|
|
14442
15096
|
init_cjs_shims();
|
|
14443
|
-
var
|
|
15097
|
+
var import_types55 = require("@neat.is/types");
|
|
14444
15098
|
function createSupabaseResolveTarget(graph, config) {
|
|
14445
15099
|
return (signal, _ctx) => {
|
|
14446
15100
|
if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
|
|
14447
15101
|
return null;
|
|
14448
15102
|
}
|
|
14449
|
-
const subResourceId = (0,
|
|
15103
|
+
const subResourceId = (0, import_types55.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
|
|
14450
15104
|
if (graph.hasNode(subResourceId)) {
|
|
14451
|
-
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType:
|
|
15105
|
+
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types55.EdgeType.CALLS };
|
|
14452
15106
|
}
|
|
14453
|
-
const bareResourceId = (0,
|
|
15107
|
+
const bareResourceId = (0, import_types55.infraId)(signal.targetKind, signal.targetName);
|
|
14454
15108
|
if (graph.hasNode(bareResourceId)) {
|
|
14455
|
-
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType:
|
|
15109
|
+
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types55.EdgeType.CALLS };
|
|
14456
15110
|
}
|
|
14457
|
-
const projectLevelId = (0,
|
|
15111
|
+
const projectLevelId = (0, import_types55.infraId)("supabase", config.nodeRef);
|
|
14458
15112
|
if (graph.hasNode(projectLevelId)) {
|
|
14459
|
-
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType:
|
|
15113
|
+
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types55.EdgeType.CALLS };
|
|
14460
15114
|
}
|
|
14461
15115
|
return null;
|
|
14462
15116
|
};
|
|
@@ -14549,7 +15203,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
|
|
|
14549
15203
|
|
|
14550
15204
|
// src/connectors/railway/index.ts
|
|
14551
15205
|
init_cjs_shims();
|
|
14552
|
-
var
|
|
15206
|
+
var import_types59 = require("@neat.is/types");
|
|
14553
15207
|
|
|
14554
15208
|
// src/connectors/railway/client.ts
|
|
14555
15209
|
init_cjs_shims();
|
|
@@ -14700,7 +15354,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
|
|
|
14700
15354
|
const out = [];
|
|
14701
15355
|
graph.forEachNode((_id, attrs) => {
|
|
14702
15356
|
const node = attrs;
|
|
14703
|
-
if (node.type !==
|
|
15357
|
+
if (node.type !== import_types59.NodeType.RouteNode) return;
|
|
14704
15358
|
const route = attrs;
|
|
14705
15359
|
if (route.service !== serviceName) return;
|
|
14706
15360
|
out.push({
|
|
@@ -14804,12 +15458,12 @@ function createRailwayResolveTarget(config) {
|
|
|
14804
15458
|
const serviceName = config.serviceNameById[config.serviceId];
|
|
14805
15459
|
if (!serviceName) return null;
|
|
14806
15460
|
if (signal.targetKind === ROUTE_TARGET_KIND) {
|
|
14807
|
-
return { targetNodeId: signal.targetName, serviceName, edgeType:
|
|
15461
|
+
return { targetNodeId: signal.targetName, serviceName, edgeType: import_types59.EdgeType.CALLS };
|
|
14808
15462
|
}
|
|
14809
15463
|
if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
|
|
14810
15464
|
const peerName = config.serviceNameById[signal.targetName];
|
|
14811
15465
|
if (!peerName) return null;
|
|
14812
|
-
return { targetNodeId: (0,
|
|
15466
|
+
return { targetNodeId: (0, import_types59.serviceId)(peerName), serviceName, edgeType: import_types59.EdgeType.CONNECTS_TO };
|
|
14813
15467
|
}
|
|
14814
15468
|
return null;
|
|
14815
15469
|
};
|
|
@@ -14933,9 +15587,9 @@ function parseFirebaseTargetName(targetName) {
|
|
|
14933
15587
|
const secondSep = rest.indexOf(FIELD_SEP);
|
|
14934
15588
|
if (secondSep === -1) return null;
|
|
14935
15589
|
const method = rest.slice(0, secondSep);
|
|
14936
|
-
const
|
|
14937
|
-
if (!resourceName || !method || !
|
|
14938
|
-
return { resourceName, method, path:
|
|
15590
|
+
const path68 = rest.slice(secondSep + 1);
|
|
15591
|
+
if (!resourceName || !method || !path68) return null;
|
|
15592
|
+
return { resourceName, method, path: path68 };
|
|
14939
15593
|
}
|
|
14940
15594
|
function resourceNameFor(type, labels) {
|
|
14941
15595
|
if (!labels) return null;
|
|
@@ -14973,14 +15627,14 @@ function mapLogEntryToSignal(entry) {
|
|
|
14973
15627
|
if (!req) return null;
|
|
14974
15628
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
14975
15629
|
const method = req.requestMethod.toUpperCase();
|
|
14976
|
-
const
|
|
14977
|
-
if (
|
|
15630
|
+
const path68 = pathFromRequestUrl(req.requestUrl);
|
|
15631
|
+
if (path68 === null) return null;
|
|
14978
15632
|
const timestamp = entry.timestamp;
|
|
14979
15633
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
14980
15634
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD2;
|
|
14981
15635
|
return {
|
|
14982
15636
|
targetKind: resourceType,
|
|
14983
|
-
targetName: packFirebaseTargetName({ resourceName, method, path:
|
|
15637
|
+
targetName: packFirebaseTargetName({ resourceName, method, path: path68 }),
|
|
14984
15638
|
callCount: 1,
|
|
14985
15639
|
errorCount: isError ? 1 : 0,
|
|
14986
15640
|
lastObservedIso: timestamp
|
|
@@ -14997,7 +15651,7 @@ function mapLogEntriesToSignals(entries) {
|
|
|
14997
15651
|
|
|
14998
15652
|
// src/connectors/firebase/resolve.ts
|
|
14999
15653
|
init_cjs_shims();
|
|
15000
|
-
var
|
|
15654
|
+
var import_types60 = require("@neat.is/types");
|
|
15001
15655
|
function neatServiceNameFor(resourceType, resourceName, serviceMap) {
|
|
15002
15656
|
switch (resourceType) {
|
|
15003
15657
|
case "cloud_function":
|
|
@@ -15012,7 +15666,7 @@ function routeEntriesFor(graph, serviceName) {
|
|
|
15012
15666
|
const entries = [];
|
|
15013
15667
|
graph.forEachNode((_id, attrs) => {
|
|
15014
15668
|
const node = attrs;
|
|
15015
|
-
if (node.type !==
|
|
15669
|
+
if (node.type !== import_types60.NodeType.RouteNode) return;
|
|
15016
15670
|
const route = attrs;
|
|
15017
15671
|
if (route.service !== serviceName) return;
|
|
15018
15672
|
entries.push({
|
|
@@ -15044,7 +15698,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
|
|
|
15044
15698
|
return {
|
|
15045
15699
|
targetNodeId: match.routeNodeId,
|
|
15046
15700
|
serviceName,
|
|
15047
|
-
edgeType:
|
|
15701
|
+
edgeType: import_types60.EdgeType.CALLS
|
|
15048
15702
|
};
|
|
15049
15703
|
};
|
|
15050
15704
|
}
|
|
@@ -15071,7 +15725,7 @@ init_cjs_shims();
|
|
|
15071
15725
|
|
|
15072
15726
|
// src/connectors/cloudflare/connector.ts
|
|
15073
15727
|
init_cjs_shims();
|
|
15074
|
-
var
|
|
15728
|
+
var import_types62 = require("@neat.is/types");
|
|
15075
15729
|
|
|
15076
15730
|
// src/connectors/cloudflare/client.ts
|
|
15077
15731
|
init_cjs_shims();
|
|
@@ -15187,7 +15841,7 @@ function mapEventToSignal(event) {
|
|
|
15187
15841
|
if (Number.isNaN(observedAt.getTime())) return null;
|
|
15188
15842
|
const statusCode = metadata?.statusCode;
|
|
15189
15843
|
const isError = typeof statusCode === "number" && statusCode >= ERROR_STATUS_THRESHOLD3;
|
|
15190
|
-
const
|
|
15844
|
+
const path68 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
|
|
15191
15845
|
return {
|
|
15192
15846
|
targetKind: CLOUDFLARE_TARGET_KIND,
|
|
15193
15847
|
targetName: scriptName,
|
|
@@ -15195,7 +15849,7 @@ function mapEventToSignal(event) {
|
|
|
15195
15849
|
errorCount: isError ? 1 : 0,
|
|
15196
15850
|
lastObservedIso: observedAt.toISOString(),
|
|
15197
15851
|
method,
|
|
15198
|
-
...
|
|
15852
|
+
...path68 ? { path: path68 } : {},
|
|
15199
15853
|
...typeof statusCode === "number" ? { statusCode } : {},
|
|
15200
15854
|
...typeof metadata?.duration === "number" ? { duration: metadata.duration } : {}
|
|
15201
15855
|
};
|
|
@@ -15235,19 +15889,19 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
15235
15889
|
graph.forEachNode((id, attrs) => {
|
|
15236
15890
|
if (found) return;
|
|
15237
15891
|
const a = attrs;
|
|
15238
|
-
if (a.type ===
|
|
15892
|
+
if (a.type === import_types62.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
|
|
15239
15893
|
found = id;
|
|
15240
15894
|
}
|
|
15241
15895
|
});
|
|
15242
15896
|
return found;
|
|
15243
15897
|
}
|
|
15244
|
-
function findMatchingRouteNode(graph, serviceName, method,
|
|
15245
|
-
const normalizedPath = normalizePathTemplate(
|
|
15898
|
+
function findMatchingRouteNode(graph, serviceName, method, path68) {
|
|
15899
|
+
const normalizedPath = normalizePathTemplate(path68);
|
|
15246
15900
|
let found = null;
|
|
15247
15901
|
graph.forEachNode((id, attrs) => {
|
|
15248
15902
|
if (found) return;
|
|
15249
15903
|
const a = attrs;
|
|
15250
|
-
if (a.type !==
|
|
15904
|
+
if (a.type !== import_types62.NodeType.RouteNode || a.service !== serviceName) return;
|
|
15251
15905
|
if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
|
|
15252
15906
|
const routeMethod = (a.method ?? "").toUpperCase();
|
|
15253
15907
|
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
@@ -15259,18 +15913,18 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
15259
15913
|
return (signal) => {
|
|
15260
15914
|
if (signal.targetKind !== CLOUDFLARE_TARGET_KIND) return null;
|
|
15261
15915
|
const scriptName = signal.targetName;
|
|
15262
|
-
const { method, path:
|
|
15916
|
+
const { method, path: path68 } = signal;
|
|
15263
15917
|
const resolveRouteGrain = (serviceName, wholeFileId) => {
|
|
15264
|
-
if (!method || !
|
|
15265
|
-
return findMatchingRouteNode(graph, serviceName, method,
|
|
15918
|
+
if (!method || !path68) return wholeFileId;
|
|
15919
|
+
return findMatchingRouteNode(graph, serviceName, method, path68) ?? wholeFileId;
|
|
15266
15920
|
};
|
|
15267
15921
|
const mapping = config.workers?.[scriptName];
|
|
15268
15922
|
if (mapping) {
|
|
15269
|
-
const wholeFileId = (0,
|
|
15923
|
+
const wholeFileId = (0, import_types62.fileId)(mapping.service, mapping.entryFile);
|
|
15270
15924
|
return {
|
|
15271
15925
|
targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
|
|
15272
15926
|
serviceName: mapping.service,
|
|
15273
|
-
edgeType:
|
|
15927
|
+
edgeType: import_types62.EdgeType.CALLS
|
|
15274
15928
|
};
|
|
15275
15929
|
}
|
|
15276
15930
|
const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
|
|
@@ -15279,13 +15933,13 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
15279
15933
|
return {
|
|
15280
15934
|
targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
|
|
15281
15935
|
serviceName: fileNode.service,
|
|
15282
|
-
edgeType:
|
|
15936
|
+
edgeType: import_types62.EdgeType.CALLS
|
|
15283
15937
|
};
|
|
15284
15938
|
}
|
|
15285
15939
|
return {
|
|
15286
|
-
targetNodeId: (0,
|
|
15940
|
+
targetNodeId: (0, import_types62.infraId)("cloudflare-worker", scriptName),
|
|
15287
15941
|
serviceName: scriptName,
|
|
15288
|
-
edgeType:
|
|
15942
|
+
edgeType: import_types62.EdgeType.CALLS,
|
|
15289
15943
|
ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
|
|
15290
15944
|
};
|
|
15291
15945
|
};
|
|
@@ -15481,14 +16135,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
|
|
|
15481
16135
|
|
|
15482
16136
|
// src/connectors/neon/resolve.ts
|
|
15483
16137
|
init_cjs_shims();
|
|
15484
|
-
var
|
|
16138
|
+
var import_types66 = require("@neat.is/types");
|
|
15485
16139
|
function createNeonResolveTarget(config) {
|
|
15486
16140
|
return (signal) => {
|
|
15487
16141
|
if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
15488
16142
|
return {
|
|
15489
|
-
targetNodeId: (0,
|
|
16143
|
+
targetNodeId: (0, import_types66.infraId)("sql-table", signal.targetName),
|
|
15490
16144
|
serviceName: config.serviceName,
|
|
15491
|
-
edgeType:
|
|
16145
|
+
edgeType: import_types66.EdgeType.CALLS,
|
|
15492
16146
|
ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
|
|
15493
16147
|
};
|
|
15494
16148
|
};
|
|
@@ -15614,9 +16268,9 @@ function parseCloudRunTargetName(targetName) {
|
|
|
15614
16268
|
const secondSep = rest.indexOf(FIELD_SEP2);
|
|
15615
16269
|
if (secondSep === -1) return null;
|
|
15616
16270
|
const method = rest.slice(0, secondSep);
|
|
15617
|
-
const
|
|
15618
|
-
if (!serviceName || !method || !
|
|
15619
|
-
return { serviceName, method, path:
|
|
16271
|
+
const path68 = rest.slice(secondSep + 1);
|
|
16272
|
+
if (!serviceName || !method || !path68) return null;
|
|
16273
|
+
return { serviceName, method, path: path68 };
|
|
15620
16274
|
}
|
|
15621
16275
|
|
|
15622
16276
|
// src/connectors/cloud-run/map.ts
|
|
@@ -15645,14 +16299,14 @@ function mapLogEntryToSignal2(entry) {
|
|
|
15645
16299
|
if (!req) return null;
|
|
15646
16300
|
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
15647
16301
|
const method = req.requestMethod.toUpperCase();
|
|
15648
|
-
const
|
|
15649
|
-
if (
|
|
16302
|
+
const path68 = pathFromRequestUrl2(req.requestUrl);
|
|
16303
|
+
if (path68 === null) return null;
|
|
15650
16304
|
const timestamp = entry.timestamp;
|
|
15651
16305
|
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
15652
16306
|
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD4;
|
|
15653
16307
|
return {
|
|
15654
16308
|
targetKind: CLOUD_RUN_TARGET_KIND,
|
|
15655
|
-
targetName: packCloudRunTargetName({ serviceName, method, path:
|
|
16309
|
+
targetName: packCloudRunTargetName({ serviceName, method, path: path68 }),
|
|
15656
16310
|
callCount: 1,
|
|
15657
16311
|
errorCount: isError ? 1 : 0,
|
|
15658
16312
|
lastObservedIso: timestamp
|
|
@@ -15669,14 +16323,14 @@ function mapLogEntriesToSignals2(entries) {
|
|
|
15669
16323
|
|
|
15670
16324
|
// src/connectors/cloud-run/resolve.ts
|
|
15671
16325
|
init_cjs_shims();
|
|
15672
|
-
var
|
|
16326
|
+
var import_types70 = require("@neat.is/types");
|
|
15673
16327
|
var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
|
|
15674
16328
|
function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
|
|
15675
16329
|
let found = null;
|
|
15676
16330
|
graph.forEachNode((_id, attrs) => {
|
|
15677
16331
|
if (found) return;
|
|
15678
16332
|
const node = attrs;
|
|
15679
|
-
if (node.type !==
|
|
16333
|
+
if (node.type !== import_types70.NodeType.RouteNode) return;
|
|
15680
16334
|
const route = attrs;
|
|
15681
16335
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
15682
16336
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -15691,23 +16345,23 @@ function createCloudRunResolveTarget(graph, config) {
|
|
|
15691
16345
|
if (signal.targetKind !== CLOUD_RUN_TARGET_KIND) return null;
|
|
15692
16346
|
const identity = parseCloudRunTargetName(signal.targetName);
|
|
15693
16347
|
if (!identity) return null;
|
|
15694
|
-
const { serviceName: gcpServiceName, method, path:
|
|
16348
|
+
const { serviceName: gcpServiceName, method, path: path68 } = identity;
|
|
15695
16349
|
const mappedService = config.serviceMap?.[gcpServiceName];
|
|
15696
16350
|
if (mappedService) {
|
|
15697
16351
|
const routeNodeId = findMatchingRouteNode2(
|
|
15698
16352
|
graph,
|
|
15699
16353
|
mappedService,
|
|
15700
16354
|
method,
|
|
15701
|
-
normalizePathTemplate(
|
|
16355
|
+
normalizePathTemplate(path68)
|
|
15702
16356
|
);
|
|
15703
16357
|
if (routeNodeId) {
|
|
15704
|
-
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType:
|
|
16358
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types70.EdgeType.CALLS };
|
|
15705
16359
|
}
|
|
15706
16360
|
}
|
|
15707
16361
|
return {
|
|
15708
|
-
targetNodeId: (0,
|
|
16362
|
+
targetNodeId: (0, import_types70.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
|
|
15709
16363
|
serviceName: mappedService ?? gcpServiceName,
|
|
15710
|
-
edgeType:
|
|
16364
|
+
edgeType: import_types70.EdgeType.CALLS,
|
|
15711
16365
|
ensureInfraNode: {
|
|
15712
16366
|
kind: CLOUD_RUN_SERVICE_INFRA_KIND,
|
|
15713
16367
|
name: gcpServiceName,
|
|
@@ -15748,7 +16402,7 @@ function createCloudRunConnector(graph, config = {}) {
|
|
|
15748
16402
|
|
|
15749
16403
|
// src/connectors/render/index.ts
|
|
15750
16404
|
init_cjs_shims();
|
|
15751
|
-
var
|
|
16405
|
+
var import_types73 = require("@neat.is/types");
|
|
15752
16406
|
|
|
15753
16407
|
// src/connectors/render/types.ts
|
|
15754
16408
|
init_cjs_shims();
|
|
@@ -15826,7 +16480,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
15826
16480
|
const out = [];
|
|
15827
16481
|
graph.forEachNode((_id, attrs) => {
|
|
15828
16482
|
const node = attrs;
|
|
15829
|
-
if (node.type !==
|
|
16483
|
+
if (node.type !== import_types73.NodeType.RouteNode) return;
|
|
15830
16484
|
const route = attrs;
|
|
15831
16485
|
if (route.service !== serviceName) return;
|
|
15832
16486
|
out.push({
|
|
@@ -15911,7 +16565,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
|
|
|
15911
16565
|
function createRenderResolveTarget(config) {
|
|
15912
16566
|
return (signal) => {
|
|
15913
16567
|
if (signal.targetKind === ROUTE_TARGET_KIND2) {
|
|
15914
|
-
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType:
|
|
16568
|
+
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types73.EdgeType.CALLS };
|
|
15915
16569
|
}
|
|
15916
16570
|
return null;
|
|
15917
16571
|
};
|
|
@@ -16049,21 +16703,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
|
|
|
16049
16703
|
|
|
16050
16704
|
// src/connectors/planetscale/resolve.ts
|
|
16051
16705
|
init_cjs_shims();
|
|
16052
|
-
var
|
|
16706
|
+
var import_types77 = require("@neat.is/types");
|
|
16053
16707
|
var PLANETSCALE_DATABASE_KIND = "planetscale-database";
|
|
16054
16708
|
function createPlanetscaleResolveTarget(graph, config) {
|
|
16055
16709
|
const databaseName = `${config.organization}/${config.database}`;
|
|
16056
16710
|
return (signal, _ctx) => {
|
|
16057
16711
|
if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
16058
|
-
const tableId = (0,
|
|
16712
|
+
const tableId = (0, import_types77.infraId)("sql-table", signal.targetName);
|
|
16059
16713
|
if (graph.hasNode(tableId)) {
|
|
16060
|
-
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType:
|
|
16714
|
+
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types77.EdgeType.CALLS };
|
|
16061
16715
|
}
|
|
16062
|
-
const providerId = (0,
|
|
16716
|
+
const providerId = (0, import_types77.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
|
|
16063
16717
|
return {
|
|
16064
16718
|
targetNodeId: providerId,
|
|
16065
16719
|
serviceName: config.serviceName,
|
|
16066
|
-
edgeType:
|
|
16720
|
+
edgeType: import_types77.EdgeType.CALLS,
|
|
16067
16721
|
ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
|
|
16068
16722
|
};
|
|
16069
16723
|
};
|
|
@@ -16691,11 +17345,11 @@ function registerRoutes(scope, ctx) {
|
|
|
16691
17345
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
16692
17346
|
const parsed = [];
|
|
16693
17347
|
for (const c of candidates) {
|
|
16694
|
-
const r =
|
|
17348
|
+
const r = import_types80.DivergenceTypeSchema.safeParse(c);
|
|
16695
17349
|
if (!r.success) {
|
|
16696
17350
|
return reply.code(400).send({
|
|
16697
17351
|
error: `unknown divergence type "${c}"`,
|
|
16698
|
-
allowed:
|
|
17352
|
+
allowed: import_types80.DivergenceTypeSchema.options
|
|
16699
17353
|
});
|
|
16700
17354
|
}
|
|
16701
17355
|
parsed.push(r.data);
|
|
@@ -17004,7 +17658,7 @@ function registerRoutes(scope, ctx) {
|
|
|
17004
17658
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
17005
17659
|
let violations = await log.readAll();
|
|
17006
17660
|
if (req.query.severity) {
|
|
17007
|
-
const sev =
|
|
17661
|
+
const sev = import_types80.PolicySeveritySchema.safeParse(req.query.severity);
|
|
17008
17662
|
if (!sev.success) {
|
|
17009
17663
|
return reply.code(400).send({
|
|
17010
17664
|
error: "invalid severity",
|
|
@@ -17043,7 +17697,7 @@ function registerRoutes(scope, ctx) {
|
|
|
17043
17697
|
scope.post("/policies/check", async (req, reply) => {
|
|
17044
17698
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
17045
17699
|
if (!proj) return;
|
|
17046
|
-
const parsed =
|
|
17700
|
+
const parsed = import_types80.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
17047
17701
|
if (!parsed.success) {
|
|
17048
17702
|
return reply.code(400).send({
|
|
17049
17703
|
error: "invalid /policies/check body",
|
|
@@ -17365,7 +18019,7 @@ init_otel_grpc();
|
|
|
17365
18019
|
// src/search.ts
|
|
17366
18020
|
init_cjs_shims();
|
|
17367
18021
|
var import_node_fs32 = require("fs");
|
|
17368
|
-
var
|
|
18022
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
17369
18023
|
var import_node_crypto4 = require("crypto");
|
|
17370
18024
|
var DEFAULT_LIMIT = 10;
|
|
17371
18025
|
var NOMIC_DIM = 768;
|
|
@@ -17528,7 +18182,7 @@ async function readCache(cachePath) {
|
|
|
17528
18182
|
}
|
|
17529
18183
|
}
|
|
17530
18184
|
async function writeCache(cachePath, cache) {
|
|
17531
|
-
await import_node_fs32.promises.mkdir(
|
|
18185
|
+
await import_node_fs32.promises.mkdir(import_node_path66.default.dirname(cachePath), { recursive: true });
|
|
17532
18186
|
await import_node_fs32.promises.writeFile(cachePath, JSON.stringify(cache));
|
|
17533
18187
|
}
|
|
17534
18188
|
var VectorIndex = class {
|
|
@@ -17709,14 +18363,14 @@ async function bootProject(registry, name, scanPath, baseDir) {
|
|
|
17709
18363
|
async function main() {
|
|
17710
18364
|
const baseDirEnv = process.env.NEAT_OUT_DIR;
|
|
17711
18365
|
const legacyOutPath = process.env.NEAT_OUT_PATH;
|
|
17712
|
-
const baseDir = baseDirEnv ?
|
|
17713
|
-
const defaultScanPath =
|
|
18366
|
+
const baseDir = baseDirEnv ? import_node_path67.default.resolve(baseDirEnv) : legacyOutPath ? import_node_path67.default.resolve(import_node_path67.default.dirname(legacyOutPath)) : import_node_path67.default.resolve("./neat-out");
|
|
18367
|
+
const defaultScanPath = import_node_path67.default.resolve(process.env.NEAT_SCAN_PATH ?? "./demo");
|
|
17714
18368
|
const registry = new Projects();
|
|
17715
18369
|
await bootProject(registry, DEFAULT_PROJECT, defaultScanPath, baseDir);
|
|
17716
18370
|
for (const name of parseExtraProjects(process.env.NEAT_PROJECTS)) {
|
|
17717
18371
|
const envKey = `NEAT_PROJECT_SCAN_PATH_${name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`;
|
|
17718
18372
|
const projectScan = process.env[envKey];
|
|
17719
|
-
await bootProject(registry, name, projectScan ?
|
|
18373
|
+
await bootProject(registry, name, projectScan ? import_node_path67.default.resolve(projectScan) : void 0, baseDir);
|
|
17720
18374
|
}
|
|
17721
18375
|
const host = process.env.HOST ?? "0.0.0.0";
|
|
17722
18376
|
const port = Number(process.env.PORT ?? 8080);
|