@neat.is/core 0.5.3 → 0.5.4-dev.20260721
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-I72HTUOG.js → chunk-4RU3AAOI.js} +2 -2
- package/dist/{chunk-CFDPIMRP.js → chunk-I4NZ7PSN.js} +3 -2
- package/dist/chunk-I4NZ7PSN.js.map +1 -0
- package/dist/{chunk-GJHEZC5K.js → chunk-PEFX3DBR.js} +422 -111
- package/dist/chunk-PEFX3DBR.js.map +1 -0
- package/dist/{chunk-X2AMX3QZ.js → chunk-VR73QNJD.js} +263 -10
- package/dist/chunk-VR73QNJD.js.map +1 -0
- package/dist/cli.cjs +1094 -448
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +95 -19
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +798 -282
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +807 -291
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-IDMIH6ZY.js → otel-grpc-TEGOXE6T.js} +3 -3
- package/dist/server.cjs +498 -172
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-CFDPIMRP.js.map +0 -1
- package/dist/chunk-GJHEZC5K.js.map +0 -1
- package/dist/chunk-X2AMX3QZ.js.map +0 -1
- /package/dist/{chunk-I72HTUOG.js.map → chunk-4RU3AAOI.js.map} +0 -0
- /package/dist/{otel-grpc-IDMIH6ZY.js.map → otel-grpc-TEGOXE6T.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mountBearerAuth,
|
|
3
3
|
readAuthEnv
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-I4NZ7PSN.js";
|
|
5
5
|
|
|
6
6
|
// src/graph.ts
|
|
7
7
|
import GraphDefault from "graphology";
|
|
@@ -456,19 +456,19 @@ function confidenceFromMix(edges, now = Date.now()) {
|
|
|
456
456
|
function longestIncomingWalk(graph, start, maxDepth) {
|
|
457
457
|
let best = { path: [start], edges: [] };
|
|
458
458
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
459
|
-
function step(node,
|
|
460
|
-
if (
|
|
461
|
-
best = { path: [...
|
|
459
|
+
function step(node, path48, edges) {
|
|
460
|
+
if (path48.length > best.path.length) {
|
|
461
|
+
best = { path: [...path48], edges: [...edges] };
|
|
462
462
|
}
|
|
463
|
-
if (
|
|
463
|
+
if (path48.length - 1 >= maxDepth) return;
|
|
464
464
|
const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
|
|
465
465
|
for (const [srcId, edge] of incoming) {
|
|
466
466
|
if (visited.has(srcId)) continue;
|
|
467
467
|
visited.add(srcId);
|
|
468
|
-
|
|
468
|
+
path48.push(srcId);
|
|
469
469
|
edges.push(edge);
|
|
470
|
-
step(srcId,
|
|
471
|
-
|
|
470
|
+
step(srcId, path48, edges);
|
|
471
|
+
path48.pop();
|
|
472
472
|
edges.pop();
|
|
473
473
|
visited.delete(srcId);
|
|
474
474
|
}
|
|
@@ -662,26 +662,26 @@ function dominantFailingCall(graph, serviceId5, visited) {
|
|
|
662
662
|
return best;
|
|
663
663
|
}
|
|
664
664
|
function followFailingCallChain(graph, originServiceId, maxDepth) {
|
|
665
|
-
const
|
|
665
|
+
const path48 = [originServiceId];
|
|
666
666
|
const edges = [];
|
|
667
667
|
const visited = /* @__PURE__ */ new Set([originServiceId]);
|
|
668
668
|
let current = originServiceId;
|
|
669
669
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
670
670
|
const hop = dominantFailingCall(graph, current, visited);
|
|
671
671
|
if (!hop) break;
|
|
672
|
-
|
|
672
|
+
path48.push(hop.nextService);
|
|
673
673
|
edges.push(hop.edge);
|
|
674
674
|
visited.add(hop.nextService);
|
|
675
675
|
current = hop.nextService;
|
|
676
676
|
}
|
|
677
677
|
if (edges.length === 0) return null;
|
|
678
|
-
return { path:
|
|
678
|
+
return { path: path48, edges, culprit: current };
|
|
679
679
|
}
|
|
680
680
|
function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
681
681
|
const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
|
|
682
682
|
if (!chain) return null;
|
|
683
683
|
const culprit = chain.culprit;
|
|
684
|
-
const
|
|
684
|
+
const path48 = [...chain.path];
|
|
685
685
|
const edgeProvenances = chain.edges.map((e) => e.provenance);
|
|
686
686
|
const baseConfidence = confidenceFromMix(chain.edges);
|
|
687
687
|
const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
|
|
@@ -689,14 +689,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
689
689
|
if (loc) {
|
|
690
690
|
let rootCauseNode = culprit;
|
|
691
691
|
if (loc.fileNode) {
|
|
692
|
-
|
|
692
|
+
path48.push(loc.fileNode);
|
|
693
693
|
edgeProvenances.push(Provenance.OBSERVED);
|
|
694
694
|
rootCauseNode = loc.fileNode;
|
|
695
695
|
}
|
|
696
696
|
return RootCauseResultSchema.parse({
|
|
697
697
|
rootCauseNode,
|
|
698
698
|
rootCauseReason: loc.rootCauseReason,
|
|
699
|
-
traversalPath:
|
|
699
|
+
traversalPath: path48,
|
|
700
700
|
edgeProvenances,
|
|
701
701
|
confidence,
|
|
702
702
|
...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
|
|
@@ -708,7 +708,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
|
|
|
708
708
|
return RootCauseResultSchema.parse({
|
|
709
709
|
rootCauseNode: culprit,
|
|
710
710
|
rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
|
|
711
|
-
traversalPath:
|
|
711
|
+
traversalPath: path48,
|
|
712
712
|
edgeProvenances,
|
|
713
713
|
confidence,
|
|
714
714
|
fixRecommendation: `Inspect ${culpritName}'s failing handler`
|
|
@@ -2229,6 +2229,18 @@ async function handleSpan(ctx, span) {
|
|
|
2229
2229
|
callSiteEvidence
|
|
2230
2230
|
);
|
|
2231
2231
|
if (result) affectedNode = targetId;
|
|
2232
|
+
if (span.dbSystem === "mongodb" && span.dbCollection) {
|
|
2233
|
+
const collectionId = ensureInfraNode(ctx.graph, "mongodb-collection", span.dbCollection, "self");
|
|
2234
|
+
upsertObservedEdge(
|
|
2235
|
+
ctx.graph,
|
|
2236
|
+
EdgeType3.CALLS,
|
|
2237
|
+
observedSource(),
|
|
2238
|
+
collectionId,
|
|
2239
|
+
ts,
|
|
2240
|
+
isError,
|
|
2241
|
+
callSiteEvidence
|
|
2242
|
+
);
|
|
2243
|
+
}
|
|
2232
2244
|
}
|
|
2233
2245
|
} else if (span.messagingSystem && span.messagingDestination && spanMintsMessagingEdge(span.kind)) {
|
|
2234
2246
|
const targetId = ensureMessagingDestinationNode(
|
|
@@ -5826,6 +5838,301 @@ function supabaseEndpointsFromFile(file, serviceDir) {
|
|
|
5826
5838
|
return out;
|
|
5827
5839
|
}
|
|
5828
5840
|
|
|
5841
|
+
// src/extract/calls/mongoose.ts
|
|
5842
|
+
import path31 from "path";
|
|
5843
|
+
import { infraId as infraId7 } from "@neat.is/types";
|
|
5844
|
+
var MONGOOSE_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongoose['"`]/;
|
|
5845
|
+
var MONGODB_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongodb['"`]/;
|
|
5846
|
+
var PLURALIZE_DISABLED_RE = /\bpluralize\s*\(\s*(?:null|false)\s*\)/;
|
|
5847
|
+
var UNCOUNTABLES = /* @__PURE__ */ new Set([
|
|
5848
|
+
"advice",
|
|
5849
|
+
"energy",
|
|
5850
|
+
"excretion",
|
|
5851
|
+
"digestion",
|
|
5852
|
+
"cooperation",
|
|
5853
|
+
"health",
|
|
5854
|
+
"justice",
|
|
5855
|
+
"labour",
|
|
5856
|
+
"machinery",
|
|
5857
|
+
"equipment",
|
|
5858
|
+
"information",
|
|
5859
|
+
"pollution",
|
|
5860
|
+
"sewage",
|
|
5861
|
+
"paper",
|
|
5862
|
+
"money",
|
|
5863
|
+
"species",
|
|
5864
|
+
"series",
|
|
5865
|
+
"rain",
|
|
5866
|
+
"rice",
|
|
5867
|
+
"fish",
|
|
5868
|
+
"sheep",
|
|
5869
|
+
"moose",
|
|
5870
|
+
"deer",
|
|
5871
|
+
"news",
|
|
5872
|
+
"expertise",
|
|
5873
|
+
"status",
|
|
5874
|
+
"media"
|
|
5875
|
+
]);
|
|
5876
|
+
var PLURALIZE_RULES = [
|
|
5877
|
+
[/human$/gi, "humans"],
|
|
5878
|
+
[/(m)an$/gi, "$1en"],
|
|
5879
|
+
[/(pe)rson$/gi, "$1ople"],
|
|
5880
|
+
[/(child)$/gi, "$1ren"],
|
|
5881
|
+
[/^(ox)$/gi, "$1en"],
|
|
5882
|
+
[/(ax|test)is$/gi, "$1es"],
|
|
5883
|
+
[/(octop|vir)us$/gi, "$1i"],
|
|
5884
|
+
[/(alias|status)$/gi, "$1es"],
|
|
5885
|
+
[/(bu)s$/gi, "$1ses"],
|
|
5886
|
+
[/(buffal|tomat|potat)o$/gi, "$1oes"],
|
|
5887
|
+
[/([ti])um$/gi, "$1a"],
|
|
5888
|
+
[/sis$/gi, "ses"],
|
|
5889
|
+
[/(?:([^f])fe|([lr])f)$/gi, "$1$2ves"],
|
|
5890
|
+
[/(hive)$/gi, "$1s"],
|
|
5891
|
+
[/([^aeiouy]|qu)y$/gi, "$1ies"],
|
|
5892
|
+
[/(x|ch|ss|sh)$/gi, "$1es"],
|
|
5893
|
+
[/(matr|vert|ind)ix|ex$/gi, "$1ices"],
|
|
5894
|
+
[/([m|l])ouse$/gi, "$1ice"],
|
|
5895
|
+
[/(kn|w|l)ife$/gi, "$1ives"],
|
|
5896
|
+
[/(quiz)$/gi, "$1zes"],
|
|
5897
|
+
[/s$/gi, "s"],
|
|
5898
|
+
[/([^a-z])$/, "$1"],
|
|
5899
|
+
[/$/gi, "s"]
|
|
5900
|
+
];
|
|
5901
|
+
function pluralizeCollection(name) {
|
|
5902
|
+
const str = name.toLowerCase();
|
|
5903
|
+
if (UNCOUNTABLES.has(str)) return str;
|
|
5904
|
+
for (const [re, repl] of PLURALIZE_RULES) {
|
|
5905
|
+
if (str.match(re)) return str.replace(re, repl);
|
|
5906
|
+
}
|
|
5907
|
+
return str;
|
|
5908
|
+
}
|
|
5909
|
+
var MODEL_METHODS = [
|
|
5910
|
+
"find",
|
|
5911
|
+
"findOne",
|
|
5912
|
+
"findById",
|
|
5913
|
+
"findByIdAndUpdate",
|
|
5914
|
+
"findByIdAndDelete",
|
|
5915
|
+
"findOneAndUpdate",
|
|
5916
|
+
"findOneAndDelete",
|
|
5917
|
+
"findOneAndReplace",
|
|
5918
|
+
"countDocuments",
|
|
5919
|
+
"estimatedDocumentCount",
|
|
5920
|
+
"distinct",
|
|
5921
|
+
"aggregate",
|
|
5922
|
+
"exists",
|
|
5923
|
+
"where",
|
|
5924
|
+
"populate",
|
|
5925
|
+
"watch",
|
|
5926
|
+
"hydrate",
|
|
5927
|
+
"create",
|
|
5928
|
+
"insertMany",
|
|
5929
|
+
"insertOne",
|
|
5930
|
+
"updateOne",
|
|
5931
|
+
"updateMany",
|
|
5932
|
+
"replaceOne",
|
|
5933
|
+
"deleteOne",
|
|
5934
|
+
"deleteMany",
|
|
5935
|
+
"bulkWrite",
|
|
5936
|
+
"bulkSave",
|
|
5937
|
+
"save",
|
|
5938
|
+
// pre-v7, removed in current mongoose but present in older codebases:
|
|
5939
|
+
"count",
|
|
5940
|
+
"update",
|
|
5941
|
+
"remove",
|
|
5942
|
+
"findOneAndRemove",
|
|
5943
|
+
"findByIdAndRemove"
|
|
5944
|
+
];
|
|
5945
|
+
var MODEL_METHODS_ALT = MODEL_METHODS.join("|");
|
|
5946
|
+
function schemaCollectionVars(content) {
|
|
5947
|
+
const out = /* @__PURE__ */ new Map();
|
|
5948
|
+
const re = /(?:const|let|var)\s+(\w+)\s*=\s*new\s+(?:mongoose\s*\.\s*)?Schema\s*\(/g;
|
|
5949
|
+
let m;
|
|
5950
|
+
while ((m = re.exec(content)) !== null) {
|
|
5951
|
+
const windowText = content.slice(m.index, m.index + 2e3);
|
|
5952
|
+
const opt = /\bcollection\s*:\s*['"`]([\w.-]+)['"`]/.exec(windowText);
|
|
5953
|
+
if (opt) out.set(m[1], opt[1]);
|
|
5954
|
+
}
|
|
5955
|
+
return out;
|
|
5956
|
+
}
|
|
5957
|
+
function resolveModel(modelName, rest, schemaColl, pluralizeOn) {
|
|
5958
|
+
const trimmed = rest.trim();
|
|
5959
|
+
const literalThird = /,\s*['"`]([\w.-]+)['"`]\s*$/.exec(trimmed);
|
|
5960
|
+
if (literalThird) return { name: literalThird[1], kind: "mongodb-collection" };
|
|
5961
|
+
const firstIdent = /^([A-Za-z_$][\w$]*)/.exec(trimmed)?.[1];
|
|
5962
|
+
if (firstIdent && schemaColl.has(firstIdent)) {
|
|
5963
|
+
return { name: schemaColl.get(firstIdent), kind: "mongodb-collection" };
|
|
5964
|
+
}
|
|
5965
|
+
if (/,\s*[A-Za-z_$][\w$]*\s*$/.test(trimmed)) {
|
|
5966
|
+
return { name: modelName, kind: "mongodb-model" };
|
|
5967
|
+
}
|
|
5968
|
+
return { name: pluralizeOn ? pluralizeCollection(modelName) : modelName, kind: "mongodb-collection" };
|
|
5969
|
+
}
|
|
5970
|
+
function collectModelDefs(content, pluralizeOn) {
|
|
5971
|
+
const schemaColl = schemaCollectionVars(content);
|
|
5972
|
+
const out = [];
|
|
5973
|
+
const re = /(?:(?:const|let|var)\s+(\w+)\s*=\s*)?(?:await\s+)?(?:\b\w+\s*\.\s*)?\bmodel\s*\(\s*['"`]([\w$]+)['"`]\s*(?:,\s*([\s\S]{0,300}?))?\)/g;
|
|
5974
|
+
let m;
|
|
5975
|
+
while ((m = re.exec(content)) !== null) {
|
|
5976
|
+
out.push({
|
|
5977
|
+
modelName: m[2],
|
|
5978
|
+
varName: m[1] ?? null,
|
|
5979
|
+
resolved: resolveModel(m[2], m[3] ?? "", schemaColl, pluralizeOn),
|
|
5980
|
+
matchText: m[0]
|
|
5981
|
+
});
|
|
5982
|
+
}
|
|
5983
|
+
return out;
|
|
5984
|
+
}
|
|
5985
|
+
function endpoint(r, file, serviceDir, matchText) {
|
|
5986
|
+
const line = lineOf(file.content, matchText);
|
|
5987
|
+
return {
|
|
5988
|
+
infraId: infraId7(r.kind, r.name),
|
|
5989
|
+
name: r.name,
|
|
5990
|
+
kind: r.kind,
|
|
5991
|
+
edgeType: "CALLS",
|
|
5992
|
+
confidenceKind: "verified-call-site",
|
|
5993
|
+
evidence: { file: path31.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
|
|
5994
|
+
};
|
|
5995
|
+
}
|
|
5996
|
+
function mongooseEndpointsFromFile(file, serviceDir) {
|
|
5997
|
+
const hasMongoose = MONGOOSE_IMPORT_RE.test(file.content);
|
|
5998
|
+
const hasMongodb = MONGODB_IMPORT_RE.test(file.content);
|
|
5999
|
+
if (!hasMongoose && !hasMongodb) return [];
|
|
6000
|
+
const content = file.content;
|
|
6001
|
+
const out = [];
|
|
6002
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6003
|
+
const push = (r, matchText) => {
|
|
6004
|
+
const key = `${r.kind}/${r.name}`;
|
|
6005
|
+
if (seen.has(key)) return;
|
|
6006
|
+
seen.add(key);
|
|
6007
|
+
out.push(endpoint(r, file, serviceDir, matchText));
|
|
6008
|
+
};
|
|
6009
|
+
if (hasMongoose) {
|
|
6010
|
+
const pluralizeOn = !PLURALIZE_DISABLED_RE.test(content);
|
|
6011
|
+
for (const def of collectModelDefs(content, pluralizeOn)) push(def.resolved, def.matchText);
|
|
6012
|
+
}
|
|
6013
|
+
const collRe = /\.\s*collection\s*\(\s*['"`]([\w.$-]+)['"`]\s*\)/g;
|
|
6014
|
+
let c;
|
|
6015
|
+
while ((c = collRe.exec(content)) !== null) {
|
|
6016
|
+
push({ name: c[1], kind: "mongodb-collection" }, c[0]);
|
|
6017
|
+
}
|
|
6018
|
+
return out;
|
|
6019
|
+
}
|
|
6020
|
+
function parseDestructure(inner, specifier, out) {
|
|
6021
|
+
for (const raw of inner.split(",")) {
|
|
6022
|
+
const part = raw.trim();
|
|
6023
|
+
if (!part) continue;
|
|
6024
|
+
const asM = /^(\w+)\s+as\s+(\w+)$/.exec(part);
|
|
6025
|
+
const colonM = /^(\w+)\s*:\s*(\w+)$/.exec(part);
|
|
6026
|
+
if (asM) out.push({ local: asM[2], kind: "named", exportName: asM[1], specifier });
|
|
6027
|
+
else if (colonM) out.push({ local: colonM[2], kind: "named", exportName: colonM[1], specifier });
|
|
6028
|
+
else {
|
|
6029
|
+
const id = /^(\w+)$/.exec(part);
|
|
6030
|
+
if (id) out.push({ local: id[1], kind: "named", exportName: id[1], specifier });
|
|
6031
|
+
}
|
|
6032
|
+
}
|
|
6033
|
+
}
|
|
6034
|
+
function parseImportBindings(content) {
|
|
6035
|
+
const out = [];
|
|
6036
|
+
const esm = /import\s+([^;'"`\n]+?)\s+from\s*['"`]([^'"`]+)['"`]/g;
|
|
6037
|
+
let m;
|
|
6038
|
+
while ((m = esm.exec(content)) !== null) {
|
|
6039
|
+
const clause = m[1].trim();
|
|
6040
|
+
const spec = m[2];
|
|
6041
|
+
const ns = /^\*\s+as\s+(\w+)$/.exec(clause);
|
|
6042
|
+
if (ns) {
|
|
6043
|
+
out.push({ local: ns[1], kind: "namespace", specifier: spec });
|
|
6044
|
+
continue;
|
|
6045
|
+
}
|
|
6046
|
+
const named = /\{([^}]*)\}/.exec(clause);
|
|
6047
|
+
if (named) parseDestructure(named[1], spec, out);
|
|
6048
|
+
const def = /^(\w+)\s*(?:,|$)/.exec(clause);
|
|
6049
|
+
if (def && !clause.startsWith("{")) out.push({ local: def[1], kind: "default", specifier: spec });
|
|
6050
|
+
}
|
|
6051
|
+
const cjs = /(?:const|let|var)\s+(\{[^}]*\}|\w+)\s*=\s*require\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
6052
|
+
while ((m = cjs.exec(content)) !== null) {
|
|
6053
|
+
const lhs = m[1];
|
|
6054
|
+
const spec = m[2];
|
|
6055
|
+
if (lhs.startsWith("{")) parseDestructure(lhs.slice(1, -1), spec, out);
|
|
6056
|
+
else out.push({ local: lhs, kind: "whole", specifier: spec });
|
|
6057
|
+
}
|
|
6058
|
+
return out;
|
|
6059
|
+
}
|
|
6060
|
+
function fileExportsOf(content, pluralizeOn) {
|
|
6061
|
+
const defs = collectModelDefs(content, pluralizeOn).filter((d) => d.resolved.kind === "mongodb-collection");
|
|
6062
|
+
if (defs.length === 0) return null;
|
|
6063
|
+
const byVar = /* @__PURE__ */ new Map();
|
|
6064
|
+
for (const d of defs) if (d.varName) byVar.set(d.varName, d.resolved.name);
|
|
6065
|
+
const byName = new Map(byVar);
|
|
6066
|
+
let def;
|
|
6067
|
+
const named = /(?:module\.exports|export\s+default)\s*=\s*(\w+)\b/.exec(content);
|
|
6068
|
+
if (named && byVar.has(named[1])) def = byVar.get(named[1]);
|
|
6069
|
+
if (!def) {
|
|
6070
|
+
const inline = /(?:module\.exports|export\s+default)\s*=\s*(?:await\s+)?(?:\w+\s*\.\s*)?model\s*\(\s*['"`]([\w$]+)['"`]/.exec(content);
|
|
6071
|
+
if (inline) def = pluralizeOn ? pluralizeCollection(inline[1]) : inline[1];
|
|
6072
|
+
}
|
|
6073
|
+
if (!def && byVar.size === 1) def = [...byVar.values()][0];
|
|
6074
|
+
return { byName, ...def ? { default: def } : {} };
|
|
6075
|
+
}
|
|
6076
|
+
async function mongooseCrossFileEndpoints(files, serviceDir) {
|
|
6077
|
+
const mongooseFiles = files.filter((f) => MONGOOSE_IMPORT_RE.test(f.content));
|
|
6078
|
+
if (mongooseFiles.length === 0) return [];
|
|
6079
|
+
const pluralizeOn = !files.some((f) => PLURALIZE_DISABLED_RE.test(f.content));
|
|
6080
|
+
const registry = /* @__PURE__ */ new Map();
|
|
6081
|
+
for (const f of mongooseFiles) {
|
|
6082
|
+
const fx = fileExportsOf(f.content, pluralizeOn);
|
|
6083
|
+
if (fx) registry.set(toPosix2(path31.relative(serviceDir, f.path)), fx);
|
|
6084
|
+
}
|
|
6085
|
+
if (registry.size === 0) return [];
|
|
6086
|
+
const out = [];
|
|
6087
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6088
|
+
for (const f of files) {
|
|
6089
|
+
const bindings = parseImportBindings(f.content);
|
|
6090
|
+
if (bindings.length === 0) continue;
|
|
6091
|
+
const directColl = /* @__PURE__ */ new Map();
|
|
6092
|
+
const nsExports = /* @__PURE__ */ new Map();
|
|
6093
|
+
for (const b of bindings) {
|
|
6094
|
+
const resolvedRel = await resolveJsImport(b.specifier, path31.dirname(f.path), serviceDir, null);
|
|
6095
|
+
if (!resolvedRel) continue;
|
|
6096
|
+
const fx = registry.get(resolvedRel);
|
|
6097
|
+
if (!fx) continue;
|
|
6098
|
+
if (b.kind === "named" && b.exportName) {
|
|
6099
|
+
const coll = fx.byName.get(b.exportName);
|
|
6100
|
+
if (coll) directColl.set(b.local, coll);
|
|
6101
|
+
} else if (b.kind === "default") {
|
|
6102
|
+
if (fx.default) directColl.set(b.local, fx.default);
|
|
6103
|
+
} else {
|
|
6104
|
+
if (fx.default) directColl.set(b.local, fx.default);
|
|
6105
|
+
nsExports.set(b.local, fx);
|
|
6106
|
+
}
|
|
6107
|
+
}
|
|
6108
|
+
if (directColl.size === 0 && nsExports.size === 0) continue;
|
|
6109
|
+
const localDefs = new Set(
|
|
6110
|
+
collectModelDefs(f.content, pluralizeOn).map((d) => d.varName).filter((v) => v !== null)
|
|
6111
|
+
);
|
|
6112
|
+
const emit = (collection, matchText) => {
|
|
6113
|
+
const key = `${f.path}::${collection}`;
|
|
6114
|
+
if (seen.has(key)) return;
|
|
6115
|
+
seen.add(key);
|
|
6116
|
+
out.push(endpoint({ name: collection, kind: "mongodb-collection" }, f, serviceDir, matchText));
|
|
6117
|
+
};
|
|
6118
|
+
for (const [local, collection] of directColl) {
|
|
6119
|
+
if (localDefs.has(local)) continue;
|
|
6120
|
+
const qre = new RegExp(`\\b${local}\\s*\\.\\s*(?:${MODEL_METHODS_ALT})\\s*\\(`, "g");
|
|
6121
|
+
let qm;
|
|
6122
|
+
while ((qm = qre.exec(f.content)) !== null) emit(collection, qm[0]);
|
|
6123
|
+
}
|
|
6124
|
+
for (const [local, fx] of nsExports) {
|
|
6125
|
+
const qre = new RegExp(`\\b${local}\\s*\\.\\s*(\\w+)\\s*\\.\\s*(?:${MODEL_METHODS_ALT})\\s*\\(`, "g");
|
|
6126
|
+
let qm;
|
|
6127
|
+
while ((qm = qre.exec(f.content)) !== null) {
|
|
6128
|
+
const coll = fx.byName.get(qm[1]);
|
|
6129
|
+
if (coll) emit(coll, qm[0]);
|
|
6130
|
+
}
|
|
6131
|
+
}
|
|
6132
|
+
}
|
|
6133
|
+
return out;
|
|
6134
|
+
}
|
|
6135
|
+
|
|
5829
6136
|
// src/extract/calls/index.ts
|
|
5830
6137
|
function edgeTypeFromEndpoint(ep) {
|
|
5831
6138
|
switch (ep.edgeType) {
|
|
@@ -5846,16 +6153,20 @@ async function addExternalEndpointEdges(graph, services) {
|
|
|
5846
6153
|
for (const service of services) {
|
|
5847
6154
|
const files = await loadSourceFiles(service.dir);
|
|
5848
6155
|
const endpoints = [];
|
|
6156
|
+
const maskedFiles = [];
|
|
5849
6157
|
for (const file of files) {
|
|
5850
6158
|
if (isTestPath(file.path)) continue;
|
|
5851
6159
|
const masked = maskCommentsInSource(file.content);
|
|
5852
6160
|
const maskedFile = { path: file.path, content: masked };
|
|
6161
|
+
maskedFiles.push(maskedFile);
|
|
5853
6162
|
endpoints.push(...kafkaEndpointsFromFile(maskedFile, service.dir));
|
|
5854
6163
|
endpoints.push(...redisEndpointsFromFile(maskedFile, service.dir));
|
|
5855
6164
|
endpoints.push(...awsEndpointsFromFile(maskedFile, service.dir));
|
|
5856
6165
|
endpoints.push(...grpcEndpointsFromFile(maskedFile, service.dir));
|
|
5857
6166
|
endpoints.push(...supabaseEndpointsFromFile(maskedFile, service.dir));
|
|
6167
|
+
endpoints.push(...mongooseEndpointsFromFile(maskedFile, service.dir));
|
|
5858
6168
|
}
|
|
6169
|
+
endpoints.push(...await mongooseCrossFileEndpoints(maskedFiles, service.dir));
|
|
5859
6170
|
if (endpoints.length === 0) continue;
|
|
5860
6171
|
const seenEdges = /* @__PURE__ */ new Set();
|
|
5861
6172
|
for (const ep of endpoints) {
|
|
@@ -5926,14 +6237,14 @@ async function addCallEdges(graph, services) {
|
|
|
5926
6237
|
}
|
|
5927
6238
|
|
|
5928
6239
|
// src/extract/infra/docker-compose.ts
|
|
5929
|
-
import
|
|
6240
|
+
import path32 from "path";
|
|
5930
6241
|
import { EdgeType as EdgeType13, Provenance as Provenance13, confidenceForExtracted as confidenceForExtracted11 } from "@neat.is/types";
|
|
5931
6242
|
|
|
5932
6243
|
// src/extract/infra/shared.ts
|
|
5933
|
-
import { NodeType as NodeType13, Provenance as Provenance12, confidenceForExtracted as confidenceForExtracted10, infraId as
|
|
6244
|
+
import { NodeType as NodeType13, Provenance as Provenance12, confidenceForExtracted as confidenceForExtracted10, infraId as infraId8 } from "@neat.is/types";
|
|
5934
6245
|
function makeInfraNode(kind, name, provider = "self", extras) {
|
|
5935
6246
|
return {
|
|
5936
|
-
id:
|
|
6247
|
+
id: infraId8(kind, name),
|
|
5937
6248
|
type: NodeType13.InfraNode,
|
|
5938
6249
|
name,
|
|
5939
6250
|
provider,
|
|
@@ -5996,7 +6307,7 @@ function dependsOnList(value) {
|
|
|
5996
6307
|
}
|
|
5997
6308
|
function serviceNameToServiceNode(name, services) {
|
|
5998
6309
|
for (const s of services) {
|
|
5999
|
-
if (s.node.name === name ||
|
|
6310
|
+
if (s.node.name === name || path32.basename(s.dir) === name) return s.node.id;
|
|
6000
6311
|
}
|
|
6001
6312
|
return null;
|
|
6002
6313
|
}
|
|
@@ -6005,7 +6316,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
6005
6316
|
let edgesAdded = 0;
|
|
6006
6317
|
let composePath = null;
|
|
6007
6318
|
for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
|
|
6008
|
-
const abs =
|
|
6319
|
+
const abs = path32.join(scanPath, name);
|
|
6009
6320
|
if (await exists(abs)) {
|
|
6010
6321
|
composePath = abs;
|
|
6011
6322
|
break;
|
|
@@ -6018,13 +6329,13 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
6018
6329
|
} catch (err) {
|
|
6019
6330
|
recordExtractionError(
|
|
6020
6331
|
"infra docker-compose",
|
|
6021
|
-
|
|
6332
|
+
path32.relative(scanPath, composePath),
|
|
6022
6333
|
err
|
|
6023
6334
|
);
|
|
6024
6335
|
return { nodesAdded, edgesAdded };
|
|
6025
6336
|
}
|
|
6026
6337
|
if (!compose?.services) return { nodesAdded, edgesAdded };
|
|
6027
|
-
const evidenceFile =
|
|
6338
|
+
const evidenceFile = path32.relative(scanPath, composePath).split(path32.sep).join("/");
|
|
6028
6339
|
const composeNameToNodeId = /* @__PURE__ */ new Map();
|
|
6029
6340
|
for (const [composeName, svc] of Object.entries(compose.services)) {
|
|
6030
6341
|
const matchedServiceId = serviceNameToServiceNode(composeName, services);
|
|
@@ -6065,7 +6376,7 @@ async function addComposeInfra(graph, scanPath, services) {
|
|
|
6065
6376
|
}
|
|
6066
6377
|
|
|
6067
6378
|
// src/extract/infra/dockerfile.ts
|
|
6068
|
-
import
|
|
6379
|
+
import path33 from "path";
|
|
6069
6380
|
import { promises as fs16 } from "fs";
|
|
6070
6381
|
import { EdgeType as EdgeType14, Provenance as Provenance14, confidenceForExtracted as confidenceForExtracted12 } from "@neat.is/types";
|
|
6071
6382
|
function readDockerfile(content) {
|
|
@@ -6096,7 +6407,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
6096
6407
|
let nodesAdded = 0;
|
|
6097
6408
|
let edgesAdded = 0;
|
|
6098
6409
|
for (const service of services) {
|
|
6099
|
-
const dockerfilePath =
|
|
6410
|
+
const dockerfilePath = path33.join(service.dir, "Dockerfile");
|
|
6100
6411
|
if (!await exists(dockerfilePath)) continue;
|
|
6101
6412
|
let content;
|
|
6102
6413
|
try {
|
|
@@ -6104,7 +6415,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
6104
6415
|
} catch (err) {
|
|
6105
6416
|
recordExtractionError(
|
|
6106
6417
|
"infra dockerfile",
|
|
6107
|
-
|
|
6418
|
+
path33.relative(scanPath, dockerfilePath),
|
|
6108
6419
|
err
|
|
6109
6420
|
);
|
|
6110
6421
|
continue;
|
|
@@ -6116,8 +6427,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
6116
6427
|
graph.addNode(node.id, node);
|
|
6117
6428
|
nodesAdded++;
|
|
6118
6429
|
}
|
|
6119
|
-
const relDockerfile = toPosix2(
|
|
6120
|
-
const evidenceFile = toPosix2(
|
|
6430
|
+
const relDockerfile = toPosix2(path33.relative(service.dir, dockerfilePath));
|
|
6431
|
+
const evidenceFile = toPosix2(path33.relative(scanPath, dockerfilePath));
|
|
6121
6432
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
6122
6433
|
graph,
|
|
6123
6434
|
service.pkg.name,
|
|
@@ -6169,7 +6480,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
|
|
|
6169
6480
|
|
|
6170
6481
|
// src/extract/infra/terraform.ts
|
|
6171
6482
|
import { promises as fs17 } from "fs";
|
|
6172
|
-
import
|
|
6483
|
+
import path34 from "path";
|
|
6173
6484
|
import { EdgeType as EdgeType15, Provenance as Provenance15, confidenceForExtracted as confidenceForExtracted13 } from "@neat.is/types";
|
|
6174
6485
|
var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
|
|
6175
6486
|
var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
|
|
@@ -6180,11 +6491,11 @@ async function walkTfFiles(start, depth = 0, max = 5) {
|
|
|
6180
6491
|
for (const entry of entries) {
|
|
6181
6492
|
if (entry.isDirectory()) {
|
|
6182
6493
|
if (IGNORED_DIRS.has(entry.name) || entry.name === ".terraform") continue;
|
|
6183
|
-
const child =
|
|
6494
|
+
const child = path34.join(start, entry.name);
|
|
6184
6495
|
if (await isPythonVenvDir(child)) continue;
|
|
6185
6496
|
out.push(...await walkTfFiles(child, depth + 1, max));
|
|
6186
6497
|
} else if (entry.isFile() && entry.name.endsWith(".tf")) {
|
|
6187
|
-
out.push(
|
|
6498
|
+
out.push(path34.join(start, entry.name));
|
|
6188
6499
|
}
|
|
6189
6500
|
}
|
|
6190
6501
|
return out;
|
|
@@ -6216,7 +6527,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
6216
6527
|
const files = await walkTfFiles(scanPath);
|
|
6217
6528
|
for (const file of files) {
|
|
6218
6529
|
const content = await fs17.readFile(file, "utf8");
|
|
6219
|
-
const evidenceFile = toPosix2(
|
|
6530
|
+
const evidenceFile = toPosix2(path34.relative(scanPath, file));
|
|
6220
6531
|
const resources = [];
|
|
6221
6532
|
const byKey = /* @__PURE__ */ new Map();
|
|
6222
6533
|
RESOURCE_RE.lastIndex = 0;
|
|
@@ -6273,7 +6584,7 @@ async function addTerraformResources(graph, scanPath) {
|
|
|
6273
6584
|
|
|
6274
6585
|
// src/extract/infra/k8s.ts
|
|
6275
6586
|
import { promises as fs18 } from "fs";
|
|
6276
|
-
import
|
|
6587
|
+
import path35 from "path";
|
|
6277
6588
|
import { parseAllDocuments as parseAllDocuments2 } from "yaml";
|
|
6278
6589
|
var K8S_KIND_TO_INFRA_KIND = {
|
|
6279
6590
|
Service: "k8s-service",
|
|
@@ -6291,11 +6602,11 @@ async function walkYamlFiles2(start, depth = 0, max = 5) {
|
|
|
6291
6602
|
for (const entry of entries) {
|
|
6292
6603
|
if (entry.isDirectory()) {
|
|
6293
6604
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
6294
|
-
const child =
|
|
6605
|
+
const child = path35.join(start, entry.name);
|
|
6295
6606
|
if (await isPythonVenvDir(child)) continue;
|
|
6296
6607
|
out.push(...await walkYamlFiles2(child, depth + 1, max));
|
|
6297
|
-
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(
|
|
6298
|
-
out.push(
|
|
6608
|
+
} else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(path35.extname(entry.name))) {
|
|
6609
|
+
out.push(path35.join(start, entry.name));
|
|
6299
6610
|
}
|
|
6300
6611
|
}
|
|
6301
6612
|
return out;
|
|
@@ -6328,13 +6639,13 @@ async function addK8sResources(graph, scanPath) {
|
|
|
6328
6639
|
|
|
6329
6640
|
// src/extract/infra/cloudflare.ts
|
|
6330
6641
|
import { promises as fs19 } from "fs";
|
|
6331
|
-
import
|
|
6642
|
+
import path36 from "path";
|
|
6332
6643
|
import { parse as parseToml2 } from "smol-toml";
|
|
6333
6644
|
import { EdgeType as EdgeType16, Provenance as Provenance16, confidenceForExtracted as confidenceForExtracted14 } from "@neat.is/types";
|
|
6334
6645
|
var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
|
|
6335
6646
|
async function readWranglerConfig(dir) {
|
|
6336
6647
|
for (const filename of WRANGLER_FILENAMES) {
|
|
6337
|
-
const abs =
|
|
6648
|
+
const abs = path36.join(dir, filename);
|
|
6338
6649
|
if (!await exists(abs)) continue;
|
|
6339
6650
|
const raw = await fs19.readFile(abs, "utf8");
|
|
6340
6651
|
const config = filename === "wrangler.toml" ? parseToml2(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
@@ -6397,11 +6708,11 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
6397
6708
|
try {
|
|
6398
6709
|
read = await readWranglerConfig(service.dir);
|
|
6399
6710
|
} catch (err) {
|
|
6400
|
-
recordExtractionError("infra cloudflare",
|
|
6711
|
+
recordExtractionError("infra cloudflare", path36.relative(scanPath, service.dir), err);
|
|
6401
6712
|
continue;
|
|
6402
6713
|
}
|
|
6403
6714
|
if (!read || !read.config.name) continue;
|
|
6404
|
-
const evidenceFile = toPosix2(
|
|
6715
|
+
const evidenceFile = toPosix2(path36.relative(scanPath, path36.join(service.dir, read.relFile)));
|
|
6405
6716
|
discovered.push({ service, config: read.config, relFile: read.relFile, raw: read.raw, evidenceFile });
|
|
6406
6717
|
}
|
|
6407
6718
|
for (const worker of discovered) {
|
|
@@ -6413,7 +6724,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
6413
6724
|
}
|
|
6414
6725
|
let anchorId = service.node.id;
|
|
6415
6726
|
if (config.main) {
|
|
6416
|
-
const entryRelPath = toPosix2(
|
|
6727
|
+
const entryRelPath = toPosix2(path36.normalize(config.main));
|
|
6417
6728
|
const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
|
|
6418
6729
|
graph,
|
|
6419
6730
|
service.pkg.name,
|
|
@@ -6560,12 +6871,12 @@ async function addCloudflareWorkers(graph, services, scanPath) {
|
|
|
6560
6871
|
|
|
6561
6872
|
// src/extract/infra/vercel.ts
|
|
6562
6873
|
import { promises as fs20 } from "fs";
|
|
6563
|
-
import
|
|
6874
|
+
import path37 from "path";
|
|
6564
6875
|
import { EdgeType as EdgeType17 } from "@neat.is/types";
|
|
6565
6876
|
var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
|
|
6566
6877
|
async function readVercelConfig(dir) {
|
|
6567
6878
|
for (const filename of VERCEL_CONFIG_FILENAMES) {
|
|
6568
|
-
const abs =
|
|
6879
|
+
const abs = path37.join(dir, filename);
|
|
6569
6880
|
if (!await exists(abs)) continue;
|
|
6570
6881
|
const raw = await fs20.readFile(abs, "utf8");
|
|
6571
6882
|
const config = JSON.parse(maskCommentsInSource(raw));
|
|
@@ -6574,7 +6885,7 @@ async function readVercelConfig(dir) {
|
|
|
6574
6885
|
return null;
|
|
6575
6886
|
}
|
|
6576
6887
|
async function readLinkedProjectName(dir) {
|
|
6577
|
-
const abs =
|
|
6888
|
+
const abs = path37.join(dir, ".vercel", "project.json");
|
|
6578
6889
|
if (!await exists(abs)) return void 0;
|
|
6579
6890
|
const parsed = JSON.parse(await fs20.readFile(abs, "utf8"));
|
|
6580
6891
|
return typeof parsed.projectName === "string" ? parsed.projectName : void 0;
|
|
@@ -6592,7 +6903,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
6592
6903
|
read = await readVercelConfig(service.dir);
|
|
6593
6904
|
projectName = await readLinkedProjectName(service.dir);
|
|
6594
6905
|
} catch (err) {
|
|
6595
|
-
recordExtractionError("infra vercel",
|
|
6906
|
+
recordExtractionError("infra vercel", path37.relative(scanPath, service.dir), err);
|
|
6596
6907
|
continue;
|
|
6597
6908
|
}
|
|
6598
6909
|
if (!read && !projectName) continue;
|
|
@@ -6608,7 +6919,7 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
6608
6919
|
const anchorId = service.node.id;
|
|
6609
6920
|
if (!read) continue;
|
|
6610
6921
|
const { config, relFile, raw } = read;
|
|
6611
|
-
const evidenceFile = toPosix2(
|
|
6922
|
+
const evidenceFile = toPosix2(path37.relative(scanPath, path37.join(service.dir, relFile)));
|
|
6612
6923
|
const add = (edgeType, kind, name) => {
|
|
6613
6924
|
if (!name) return;
|
|
6614
6925
|
const result = emitPlatformResourceEdge(
|
|
@@ -6637,13 +6948,13 @@ async function addVercelServices(graph, services, scanPath) {
|
|
|
6637
6948
|
|
|
6638
6949
|
// src/extract/infra/railway.ts
|
|
6639
6950
|
import { promises as fs21 } from "fs";
|
|
6640
|
-
import
|
|
6951
|
+
import path38 from "path";
|
|
6641
6952
|
import { parse as parseToml3 } from "smol-toml";
|
|
6642
6953
|
import { EdgeType as EdgeType18 } from "@neat.is/types";
|
|
6643
6954
|
var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
|
|
6644
6955
|
async function readRailwayConfig(dir) {
|
|
6645
6956
|
for (const filename of RAILWAY_FILENAMES) {
|
|
6646
|
-
const abs =
|
|
6957
|
+
const abs = path38.join(dir, filename);
|
|
6647
6958
|
if (!await exists(abs)) continue;
|
|
6648
6959
|
const raw = await fs21.readFile(abs, "utf8");
|
|
6649
6960
|
const config = filename === "railway.toml" ? parseToml3(raw) : JSON.parse(maskCommentsInSource(raw));
|
|
@@ -6659,7 +6970,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
6659
6970
|
try {
|
|
6660
6971
|
read = await readRailwayConfig(service.dir);
|
|
6661
6972
|
} catch (err) {
|
|
6662
|
-
recordExtractionError("infra railway",
|
|
6973
|
+
recordExtractionError("infra railway", path38.relative(scanPath, service.dir), err);
|
|
6663
6974
|
continue;
|
|
6664
6975
|
}
|
|
6665
6976
|
if (!read) continue;
|
|
@@ -6669,7 +6980,7 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
6669
6980
|
}
|
|
6670
6981
|
const anchorId = service.node.id;
|
|
6671
6982
|
const { config, relFile, raw } = read;
|
|
6672
|
-
const evidenceFile = toPosix2(
|
|
6983
|
+
const evidenceFile = toPosix2(path38.relative(scanPath, path38.join(service.dir, relFile)));
|
|
6673
6984
|
const add = (edgeType, kind, name) => {
|
|
6674
6985
|
if (!name) return;
|
|
6675
6986
|
const result = emitPlatformResourceEdge(
|
|
@@ -6694,12 +7005,12 @@ async function addRailwayServices(graph, services, scanPath) {
|
|
|
6694
7005
|
|
|
6695
7006
|
// src/extract/infra/supabase.ts
|
|
6696
7007
|
import { promises as fs22 } from "fs";
|
|
6697
|
-
import
|
|
7008
|
+
import path39 from "path";
|
|
6698
7009
|
import { parse as parseToml4 } from "smol-toml";
|
|
6699
7010
|
import { EdgeType as EdgeType19 } from "@neat.is/types";
|
|
6700
7011
|
async function readSupabaseConfig(dir) {
|
|
6701
|
-
const relFile =
|
|
6702
|
-
const abs =
|
|
7012
|
+
const relFile = path39.join("supabase", "config.toml");
|
|
7013
|
+
const abs = path39.join(dir, relFile);
|
|
6703
7014
|
if (!await exists(abs)) return null;
|
|
6704
7015
|
const raw = await fs22.readFile(abs, "utf8");
|
|
6705
7016
|
const config = parseToml4(raw);
|
|
@@ -6713,7 +7024,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
6713
7024
|
try {
|
|
6714
7025
|
read = await readSupabaseConfig(service.dir);
|
|
6715
7026
|
} catch (err) {
|
|
6716
|
-
recordExtractionError("infra supabase",
|
|
7027
|
+
recordExtractionError("infra supabase", path39.relative(scanPath, service.dir), err);
|
|
6717
7028
|
continue;
|
|
6718
7029
|
}
|
|
6719
7030
|
if (!read) continue;
|
|
@@ -6728,7 +7039,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
|
|
|
6728
7039
|
});
|
|
6729
7040
|
}
|
|
6730
7041
|
const anchorId = service.node.id;
|
|
6731
|
-
const evidenceFile = toPosix2(
|
|
7042
|
+
const evidenceFile = toPosix2(path39.relative(scanPath, path39.join(service.dir, relFile)));
|
|
6732
7043
|
const add = (edgeType, kind, name) => {
|
|
6733
7044
|
if (!name) return;
|
|
6734
7045
|
const result = emitPlatformResourceEdge(
|
|
@@ -6769,11 +7080,11 @@ async function addInfra(graph, scanPath, services) {
|
|
|
6769
7080
|
}
|
|
6770
7081
|
|
|
6771
7082
|
// src/extract/index.ts
|
|
6772
|
-
import
|
|
7083
|
+
import path41 from "path";
|
|
6773
7084
|
|
|
6774
7085
|
// src/extract/retire.ts
|
|
6775
7086
|
import { existsSync as existsSync2 } from "fs";
|
|
6776
|
-
import
|
|
7087
|
+
import path40 from "path";
|
|
6777
7088
|
import { NodeType as NodeType14, Provenance as Provenance17 } from "@neat.is/types";
|
|
6778
7089
|
function dropOrphanedFileNodes(graph) {
|
|
6779
7090
|
const orphans = [];
|
|
@@ -6807,11 +7118,11 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
|
|
|
6807
7118
|
if (edge.provenance !== Provenance17.EXTRACTED) return;
|
|
6808
7119
|
const evidenceFile = edge.evidence?.file;
|
|
6809
7120
|
if (!evidenceFile) return;
|
|
6810
|
-
if (
|
|
7121
|
+
if (path40.isAbsolute(evidenceFile)) {
|
|
6811
7122
|
if (!existsSync2(evidenceFile)) toDrop.push(id);
|
|
6812
7123
|
return;
|
|
6813
7124
|
}
|
|
6814
|
-
const found = bases.some((base) => existsSync2(
|
|
7125
|
+
const found = bases.some((base) => existsSync2(path40.join(base, evidenceFile)));
|
|
6815
7126
|
if (!found) toDrop.push(id);
|
|
6816
7127
|
});
|
|
6817
7128
|
for (const id of toDrop) graph.dropEdge(id);
|
|
@@ -6853,7 +7164,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
6853
7164
|
}
|
|
6854
7165
|
const droppedEntries = drainDroppedExtracted();
|
|
6855
7166
|
if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
|
|
6856
|
-
const rejectedPath =
|
|
7167
|
+
const rejectedPath = path41.join(path41.dirname(opts.errorsPath), "rejected.ndjson");
|
|
6857
7168
|
try {
|
|
6858
7169
|
await writeRejectedExtracted(droppedEntries, rejectedPath);
|
|
6859
7170
|
} catch (err) {
|
|
@@ -7171,7 +7482,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
7171
7482
|
|
|
7172
7483
|
// src/persist.ts
|
|
7173
7484
|
import { promises as fs23 } from "fs";
|
|
7174
|
-
import
|
|
7485
|
+
import path42 from "path";
|
|
7175
7486
|
import { Provenance as Provenance19, observedEdgeId as observedEdgeId2 } from "@neat.is/types";
|
|
7176
7487
|
var SCHEMA_VERSION = 4;
|
|
7177
7488
|
function migrateV1ToV2(payload) {
|
|
@@ -7208,7 +7519,7 @@ function migrateV2ToV3(payload) {
|
|
|
7208
7519
|
return { ...payload, schemaVersion: 3 };
|
|
7209
7520
|
}
|
|
7210
7521
|
async function ensureDir(filePath) {
|
|
7211
|
-
await fs23.mkdir(
|
|
7522
|
+
await fs23.mkdir(path42.dirname(filePath), { recursive: true });
|
|
7212
7523
|
}
|
|
7213
7524
|
async function saveGraphToDisk(graph, outPath) {
|
|
7214
7525
|
await ensureDir(outPath);
|
|
@@ -7364,23 +7675,23 @@ function canonicalJson(value) {
|
|
|
7364
7675
|
}
|
|
7365
7676
|
|
|
7366
7677
|
// src/projects.ts
|
|
7367
|
-
import
|
|
7678
|
+
import path43 from "path";
|
|
7368
7679
|
function pathsForProject(project, baseDir) {
|
|
7369
7680
|
if (project === DEFAULT_PROJECT) {
|
|
7370
7681
|
return {
|
|
7371
|
-
snapshotPath:
|
|
7372
|
-
errorsPath:
|
|
7373
|
-
staleEventsPath:
|
|
7374
|
-
embeddingsCachePath:
|
|
7375
|
-
policyViolationsPath:
|
|
7682
|
+
snapshotPath: path43.join(baseDir, "graph.json"),
|
|
7683
|
+
errorsPath: path43.join(baseDir, "errors.ndjson"),
|
|
7684
|
+
staleEventsPath: path43.join(baseDir, "stale-events.ndjson"),
|
|
7685
|
+
embeddingsCachePath: path43.join(baseDir, "embeddings.json"),
|
|
7686
|
+
policyViolationsPath: path43.join(baseDir, "policy-violations.ndjson")
|
|
7376
7687
|
};
|
|
7377
7688
|
}
|
|
7378
7689
|
return {
|
|
7379
|
-
snapshotPath:
|
|
7380
|
-
errorsPath:
|
|
7381
|
-
staleEventsPath:
|
|
7382
|
-
embeddingsCachePath:
|
|
7383
|
-
policyViolationsPath:
|
|
7690
|
+
snapshotPath: path43.join(baseDir, `${project}.json`),
|
|
7691
|
+
errorsPath: path43.join(baseDir, `errors.${project}.ndjson`),
|
|
7692
|
+
staleEventsPath: path43.join(baseDir, `stale-events.${project}.ndjson`),
|
|
7693
|
+
embeddingsCachePath: path43.join(baseDir, `embeddings.${project}.json`),
|
|
7694
|
+
policyViolationsPath: path43.join(baseDir, `policy-violations.${project}.ndjson`)
|
|
7384
7695
|
};
|
|
7385
7696
|
}
|
|
7386
7697
|
var Projects = class {
|
|
@@ -7421,7 +7732,7 @@ function parseExtraProjects(raw) {
|
|
|
7421
7732
|
// src/registry.ts
|
|
7422
7733
|
import { promises as fs25 } from "fs";
|
|
7423
7734
|
import os2 from "os";
|
|
7424
|
-
import
|
|
7735
|
+
import path44 from "path";
|
|
7425
7736
|
import {
|
|
7426
7737
|
RegistryFileSchema
|
|
7427
7738
|
} from "@neat.is/types";
|
|
@@ -7429,20 +7740,20 @@ var LOCK_TIMEOUT_MS = 5e3;
|
|
|
7429
7740
|
var LOCK_RETRY_MS = 50;
|
|
7430
7741
|
function neatHome() {
|
|
7431
7742
|
const override = process.env.NEAT_HOME;
|
|
7432
|
-
if (override && override.length > 0) return
|
|
7433
|
-
return
|
|
7743
|
+
if (override && override.length > 0) return path44.resolve(override);
|
|
7744
|
+
return path44.join(os2.homedir(), ".neat");
|
|
7434
7745
|
}
|
|
7435
7746
|
function registryPath() {
|
|
7436
|
-
return
|
|
7747
|
+
return path44.join(neatHome(), "projects.json");
|
|
7437
7748
|
}
|
|
7438
7749
|
function registryLockPath() {
|
|
7439
|
-
return
|
|
7750
|
+
return path44.join(neatHome(), "projects.json.lock");
|
|
7440
7751
|
}
|
|
7441
7752
|
function daemonPidPath() {
|
|
7442
|
-
return
|
|
7753
|
+
return path44.join(neatHome(), "neatd.pid");
|
|
7443
7754
|
}
|
|
7444
7755
|
function daemonsDir() {
|
|
7445
|
-
return
|
|
7756
|
+
return path44.join(neatHome(), "daemons");
|
|
7446
7757
|
}
|
|
7447
7758
|
function isFiniteInt(v) {
|
|
7448
7759
|
return typeof v === "number" && Number.isFinite(v);
|
|
@@ -7483,7 +7794,7 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
|
|
|
7483
7794
|
const out = [];
|
|
7484
7795
|
for (const name of names) {
|
|
7485
7796
|
if (!name.endsWith(".json")) continue;
|
|
7486
|
-
const file =
|
|
7797
|
+
const file = path44.join(dir, name);
|
|
7487
7798
|
let raw;
|
|
7488
7799
|
try {
|
|
7489
7800
|
raw = await fs25.readFile(file, "utf8");
|
|
@@ -7604,7 +7915,7 @@ function lockHolderMessage(holder, lockPath, timeoutMs) {
|
|
|
7604
7915
|
}
|
|
7605
7916
|
}
|
|
7606
7917
|
async function normalizeProjectPath(input) {
|
|
7607
|
-
const resolved =
|
|
7918
|
+
const resolved = path44.resolve(input);
|
|
7608
7919
|
try {
|
|
7609
7920
|
return await fs25.realpath(resolved);
|
|
7610
7921
|
} catch {
|
|
@@ -7612,7 +7923,7 @@ async function normalizeProjectPath(input) {
|
|
|
7612
7923
|
}
|
|
7613
7924
|
}
|
|
7614
7925
|
async function writeAtomically(target, contents) {
|
|
7615
|
-
await fs25.mkdir(
|
|
7926
|
+
await fs25.mkdir(path44.dirname(target), { recursive: true });
|
|
7616
7927
|
const tmp = `${target}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
7617
7928
|
const fd = await fs25.open(tmp, "w");
|
|
7618
7929
|
try {
|
|
@@ -7625,7 +7936,7 @@ async function writeAtomically(target, contents) {
|
|
|
7625
7936
|
}
|
|
7626
7937
|
async function acquireLock(lockPath, timeoutMs = LOCK_TIMEOUT_MS, probe = defaultLockHolderProbe) {
|
|
7627
7938
|
const deadline = Date.now() + timeoutMs;
|
|
7628
|
-
await fs25.mkdir(
|
|
7939
|
+
await fs25.mkdir(path44.dirname(lockPath), { recursive: true });
|
|
7629
7940
|
let probedHolder = false;
|
|
7630
7941
|
while (true) {
|
|
7631
7942
|
try {
|
|
@@ -7821,13 +8132,13 @@ import { DivergenceTypeSchema, PoliciesCheckBodySchema, PolicySeveritySchema } f
|
|
|
7821
8132
|
|
|
7822
8133
|
// src/extend/index.ts
|
|
7823
8134
|
import { promises as fs27 } from "fs";
|
|
7824
|
-
import
|
|
8135
|
+
import path46 from "path";
|
|
7825
8136
|
import os3 from "os";
|
|
7826
8137
|
import { resolve as registryResolve, list as registryList } from "@neat.is/instrumentation-registry";
|
|
7827
8138
|
|
|
7828
8139
|
// src/installers/package-manager.ts
|
|
7829
8140
|
import { promises as fs26 } from "fs";
|
|
7830
|
-
import
|
|
8141
|
+
import path45 from "path";
|
|
7831
8142
|
import { spawn } from "child_process";
|
|
7832
8143
|
var LOCKFILE_PRIORITY = [
|
|
7833
8144
|
{ lockfile: "bun.lockb", pm: "bun", args: ["install", "--no-summary"] },
|
|
@@ -7849,22 +8160,22 @@ async function exists2(p) {
|
|
|
7849
8160
|
}
|
|
7850
8161
|
}
|
|
7851
8162
|
async function detectPackageManager(serviceDir) {
|
|
7852
|
-
let dir =
|
|
8163
|
+
let dir = path45.resolve(serviceDir);
|
|
7853
8164
|
const stops = /* @__PURE__ */ new Set();
|
|
7854
8165
|
for (let i = 0; i < 64; i++) {
|
|
7855
8166
|
if (stops.has(dir)) break;
|
|
7856
8167
|
stops.add(dir);
|
|
7857
8168
|
for (const candidate of LOCKFILE_PRIORITY) {
|
|
7858
|
-
const lockPath =
|
|
8169
|
+
const lockPath = path45.join(dir, candidate.lockfile);
|
|
7859
8170
|
if (await exists2(lockPath)) {
|
|
7860
8171
|
return { pm: candidate.pm, cwd: dir, args: [...candidate.args] };
|
|
7861
8172
|
}
|
|
7862
8173
|
}
|
|
7863
|
-
const parent =
|
|
8174
|
+
const parent = path45.dirname(dir);
|
|
7864
8175
|
if (parent === dir) break;
|
|
7865
8176
|
dir = parent;
|
|
7866
8177
|
}
|
|
7867
|
-
return { pm: "npm", cwd:
|
|
8178
|
+
return { pm: "npm", cwd: path45.resolve(serviceDir), args: [...NPM_FALLBACK_ARGS] };
|
|
7868
8179
|
}
|
|
7869
8180
|
async function runPackageManagerInstall(cmd) {
|
|
7870
8181
|
return new Promise((resolve) => {
|
|
@@ -7913,7 +8224,7 @@ async function fileExists2(p) {
|
|
|
7913
8224
|
}
|
|
7914
8225
|
}
|
|
7915
8226
|
async function readPackageJson(scanPath) {
|
|
7916
|
-
const pkgPath =
|
|
8227
|
+
const pkgPath = path46.join(scanPath, "package.json");
|
|
7917
8228
|
const raw = await fs27.readFile(pkgPath, "utf8");
|
|
7918
8229
|
return JSON.parse(raw);
|
|
7919
8230
|
}
|
|
@@ -7932,11 +8243,11 @@ async function findHookFiles(scanPath) {
|
|
|
7932
8243
|
for (const entry of entries) {
|
|
7933
8244
|
if (entry.isDirectory()) {
|
|
7934
8245
|
if (entry.name.startsWith(".") || HOOK_WALK_SKIP_DIRS.has(entry.name)) continue;
|
|
7935
|
-
await walk3(
|
|
8246
|
+
await walk3(path46.join(dir, entry.name));
|
|
7936
8247
|
} else if (entry.isFile()) {
|
|
7937
8248
|
if ((entry.name.startsWith("instrumentation") || entry.name.startsWith("otel-init")) && /\.(ts|js|cjs|mjs)$/.test(entry.name)) {
|
|
7938
|
-
const rel =
|
|
7939
|
-
found.push(rel.split(
|
|
8249
|
+
const rel = path46.relative(scanPath, path46.join(dir, entry.name));
|
|
8250
|
+
found.push(rel.split(path46.sep).join("/"));
|
|
7940
8251
|
}
|
|
7941
8252
|
}
|
|
7942
8253
|
}
|
|
@@ -7947,7 +8258,7 @@ async function findHookFiles(scanPath) {
|
|
|
7947
8258
|
async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
|
|
7948
8259
|
let fallback = null;
|
|
7949
8260
|
for (const file of hookFiles) {
|
|
7950
|
-
const content = await fs27.readFile(
|
|
8261
|
+
const content = await fs27.readFile(path46.join(scanPath, file), "utf8");
|
|
7951
8262
|
const patched = splicedContent(content, snippet2);
|
|
7952
8263
|
if (patched !== null) return { file, content, patched };
|
|
7953
8264
|
if (fallback === null) fallback = { file, content };
|
|
@@ -7955,11 +8266,11 @@ async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
|
|
|
7955
8266
|
return { file: fallback.file, content: fallback.content, patched: null };
|
|
7956
8267
|
}
|
|
7957
8268
|
function extendLogPath() {
|
|
7958
|
-
return process.env.NEAT_EXTEND_LOG ??
|
|
8269
|
+
return process.env.NEAT_EXTEND_LOG ?? path46.join(os3.homedir(), ".neat", "extend-log.ndjson");
|
|
7959
8270
|
}
|
|
7960
8271
|
async function appendExtendLog(entry) {
|
|
7961
8272
|
const logPath = extendLogPath();
|
|
7962
|
-
await fs27.mkdir(
|
|
8273
|
+
await fs27.mkdir(path46.dirname(logPath), { recursive: true });
|
|
7963
8274
|
await fs27.appendFile(logPath, JSON.stringify(entry) + "\n", "utf8");
|
|
7964
8275
|
}
|
|
7965
8276
|
function splicedContent(fileContent, snippet2) {
|
|
@@ -8018,7 +8329,7 @@ function lookupInstrumentation(library, installedVersion) {
|
|
|
8018
8329
|
}
|
|
8019
8330
|
async function describeProjectInstrumentation(ctx) {
|
|
8020
8331
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
8021
|
-
const envNeat = await fileExists2(
|
|
8332
|
+
const envNeat = await fileExists2(path46.join(ctx.scanPath, ".env.neat"));
|
|
8022
8333
|
const registryInstrPackages = new Set(
|
|
8023
8334
|
registryList().map((e) => e.instrumentation_package).filter((p) => !!p)
|
|
8024
8335
|
);
|
|
@@ -8040,7 +8351,7 @@ async function applyExtension(ctx, args, options) {
|
|
|
8040
8351
|
);
|
|
8041
8352
|
}
|
|
8042
8353
|
for (const file of hookFiles) {
|
|
8043
|
-
const content = await fs27.readFile(
|
|
8354
|
+
const content = await fs27.readFile(path46.join(ctx.scanPath, file), "utf8");
|
|
8044
8355
|
if (content.includes(args.registration_snippet)) {
|
|
8045
8356
|
return { library: args.library, filesTouched: [], depsAdded: [], installOutput: "", alreadyApplied: true };
|
|
8046
8357
|
}
|
|
@@ -8052,10 +8363,10 @@ async function applyExtension(ctx, args, options) {
|
|
|
8052
8363
|
);
|
|
8053
8364
|
}
|
|
8054
8365
|
const primaryFile = primary.file;
|
|
8055
|
-
const primaryPath =
|
|
8366
|
+
const primaryPath = path46.join(ctx.scanPath, primaryFile);
|
|
8056
8367
|
const filesTouched = [];
|
|
8057
8368
|
const depsAdded = [];
|
|
8058
|
-
const pkgPath =
|
|
8369
|
+
const pkgPath = path46.join(ctx.scanPath, "package.json");
|
|
8059
8370
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
8060
8371
|
if (!(pkg.dependencies ?? {})[args.instrumentation_package]) {
|
|
8061
8372
|
pkg.dependencies = { ...pkg.dependencies ?? {}, [args.instrumentation_package]: args.version };
|
|
@@ -8094,7 +8405,7 @@ async function dryRunExtension(ctx, args) {
|
|
|
8094
8405
|
};
|
|
8095
8406
|
}
|
|
8096
8407
|
for (const file of hookFiles) {
|
|
8097
|
-
const content = await fs27.readFile(
|
|
8408
|
+
const content = await fs27.readFile(path46.join(ctx.scanPath, file), "utf8");
|
|
8098
8409
|
if (content.includes(args.registration_snippet)) {
|
|
8099
8410
|
return {
|
|
8100
8411
|
library: args.library,
|
|
@@ -8135,7 +8446,7 @@ async function rollbackExtension(ctx, args) {
|
|
|
8135
8446
|
if (!match) {
|
|
8136
8447
|
return { undone: false, message: "no apply found for library" };
|
|
8137
8448
|
}
|
|
8138
|
-
const pkgPath =
|
|
8449
|
+
const pkgPath = path46.join(ctx.scanPath, "package.json");
|
|
8139
8450
|
if (await fileExists2(pkgPath)) {
|
|
8140
8451
|
const pkg = await readPackageJson(ctx.scanPath);
|
|
8141
8452
|
if (pkg.dependencies?.[match.instrumentation_package]) {
|
|
@@ -8146,7 +8457,7 @@ async function rollbackExtension(ctx, args) {
|
|
|
8146
8457
|
}
|
|
8147
8458
|
const hookFiles = await findHookFiles(ctx.scanPath);
|
|
8148
8459
|
for (const file of hookFiles) {
|
|
8149
|
-
const filePath =
|
|
8460
|
+
const filePath = path46.join(ctx.scanPath, file);
|
|
8150
8461
|
const content = await fs27.readFile(filePath, "utf8");
|
|
8151
8462
|
if (content.includes(match.registration_snippet)) {
|
|
8152
8463
|
const filtered = content.split("\n").filter((line) => !line.includes(match.registration_snippet)).join("\n");
|
|
@@ -8261,7 +8572,7 @@ data: ${JSON.stringify(envelope.payload)}
|
|
|
8261
8572
|
|
|
8262
8573
|
// src/connectors-config.ts
|
|
8263
8574
|
import os4 from "os";
|
|
8264
|
-
import
|
|
8575
|
+
import path47 from "path";
|
|
8265
8576
|
import { promises as fs28 } from "fs";
|
|
8266
8577
|
var CONNECTORS_CONFIG_VERSION = 1;
|
|
8267
8578
|
var EnvRefUnsetError = class extends Error {
|
|
@@ -8276,11 +8587,11 @@ var EnvRefUnsetError = class extends Error {
|
|
|
8276
8587
|
};
|
|
8277
8588
|
function neatHome2() {
|
|
8278
8589
|
const override = process.env.NEAT_HOME;
|
|
8279
|
-
if (override && override.length > 0) return
|
|
8280
|
-
return
|
|
8590
|
+
if (override && override.length > 0) return path47.resolve(override);
|
|
8591
|
+
return path47.join(os4.homedir(), ".neat");
|
|
8281
8592
|
}
|
|
8282
8593
|
function connectorsConfigPath(home = neatHome2()) {
|
|
8283
|
-
return
|
|
8594
|
+
return path47.join(home, "connectors.json");
|
|
8284
8595
|
}
|
|
8285
8596
|
var MODE_MASK_LOOSER_THAN_0600 = 63;
|
|
8286
8597
|
async function warnIfModeLooserThan0600(file) {
|
|
@@ -8411,7 +8722,7 @@ function connectorMatchesProject(entry, project) {
|
|
|
8411
8722
|
var CONNECTORS_LOCK_TIMEOUT_MS = 5e3;
|
|
8412
8723
|
var CONNECTORS_LOCK_RETRY_MS = 50;
|
|
8413
8724
|
function connectorsConfigLockPath(home = neatHome2()) {
|
|
8414
|
-
return
|
|
8725
|
+
return path47.join(home, "connectors.json.lock");
|
|
8415
8726
|
}
|
|
8416
8727
|
function isEnvRef(value) {
|
|
8417
8728
|
return value.length > 1 && value.startsWith("$");
|
|
@@ -8424,7 +8735,7 @@ function redactCredentialRef(ref) {
|
|
|
8424
8735
|
return out;
|
|
8425
8736
|
}
|
|
8426
8737
|
async function writeConfigAtomically0600(file, contents) {
|
|
8427
|
-
await fs28.mkdir(
|
|
8738
|
+
await fs28.mkdir(path47.dirname(file), { recursive: true });
|
|
8428
8739
|
const tmp = `${file}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
8429
8740
|
const fd = await fs28.open(tmp, "w", 384);
|
|
8430
8741
|
try {
|
|
@@ -8438,7 +8749,7 @@ async function writeConfigAtomically0600(file, contents) {
|
|
|
8438
8749
|
}
|
|
8439
8750
|
async function acquireConnectorsLock(lockPath, timeoutMs = CONNECTORS_LOCK_TIMEOUT_MS) {
|
|
8440
8751
|
const deadline = Date.now() + timeoutMs;
|
|
8441
|
-
await fs28.mkdir(
|
|
8752
|
+
await fs28.mkdir(path47.dirname(lockPath), { recursive: true });
|
|
8442
8753
|
for (; ; ) {
|
|
8443
8754
|
try {
|
|
8444
8755
|
const fd = await fs28.open(lockPath, "wx");
|
|
@@ -9396,4 +9707,4 @@ export {
|
|
|
9396
9707
|
recordConnectorPoll,
|
|
9397
9708
|
buildApi
|
|
9398
9709
|
};
|
|
9399
|
-
//# sourceMappingURL=chunk-
|
|
9710
|
+
//# sourceMappingURL=chunk-PEFX3DBR.js.map
|