@neat.is/core 0.5.1 → 0.5.3

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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  routeSpanToProject,
3
3
  startDaemon
4
- } from "./chunk-DPEPI2N6.js";
4
+ } from "./chunk-X2AMX3QZ.js";
5
5
  import {
6
6
  ProjectNameCollisionError,
7
7
  addProject,
@@ -37,7 +37,7 @@ import {
37
37
  thresholdForEdgeType,
38
38
  touchLastSeen,
39
39
  writeAtomically
40
- } from "./chunk-BI3XKGVG.js";
40
+ } from "./chunk-GJHEZC5K.js";
41
41
  import {
42
42
  startOtelGrpcReceiver
43
43
  } from "./chunk-I72HTUOG.js";
package/dist/neatd.cjs CHANGED
@@ -4633,14 +4633,21 @@ function engineFromImage(image) {
4633
4633
  // src/extract/databases/dotenv.ts
4634
4634
  var CONNECTION_KEYS = /* @__PURE__ */ new Set([
4635
4635
  "DATABASE_URL",
4636
+ "DATABASE_URI",
4636
4637
  "DB_URL",
4638
+ "DB_URI",
4637
4639
  "POSTGRES_URL",
4640
+ "POSTGRES_URI",
4638
4641
  "POSTGRESQL_URL",
4642
+ "POSTGRESQL_URI",
4639
4643
  "MYSQL_URL",
4644
+ "MYSQL_URI",
4645
+ "MONGODB_URL",
4640
4646
  "MONGODB_URI",
4641
4647
  "MONGO_URL",
4642
4648
  "MONGO_URI",
4643
- "REDIS_URL"
4649
+ "REDIS_URL",
4650
+ "REDIS_URI"
4644
4651
  ]);
4645
4652
  function parseDotenvLine(line) {
4646
4653
  const trimmed = line.trim();
@@ -7778,11 +7785,42 @@ async function readPackageJson(scanPath) {
7778
7785
  const raw = await import_node_fs26.promises.readFile(pkgPath, "utf8");
7779
7786
  return JSON.parse(raw);
7780
7787
  }
7788
+ var HOOK_WALK_SKIP_DIRS = /* @__PURE__ */ new Set([
7789
+ "node_modules",
7790
+ "dist",
7791
+ "build",
7792
+ "out",
7793
+ "coverage",
7794
+ "neat-out"
7795
+ ]);
7781
7796
  async function findHookFiles(scanPath) {
7782
- const entries = await import_node_fs26.promises.readdir(scanPath);
7783
- return entries.filter(
7784
- (e) => (e.startsWith("instrumentation") || e.startsWith("otel-init")) && /\.(ts|js)$/.test(e)
7785
- ).sort();
7797
+ const found = [];
7798
+ const walk3 = async (dir) => {
7799
+ const entries = await import_node_fs26.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
7800
+ for (const entry2 of entries) {
7801
+ if (entry2.isDirectory()) {
7802
+ if (entry2.name.startsWith(".") || HOOK_WALK_SKIP_DIRS.has(entry2.name)) continue;
7803
+ await walk3(import_node_path44.default.join(dir, entry2.name));
7804
+ } else if (entry2.isFile()) {
7805
+ if ((entry2.name.startsWith("instrumentation") || entry2.name.startsWith("otel-init")) && /\.(ts|js|cjs|mjs)$/.test(entry2.name)) {
7806
+ const rel = import_node_path44.default.relative(scanPath, import_node_path44.default.join(dir, entry2.name));
7807
+ found.push(rel.split(import_node_path44.default.sep).join("/"));
7808
+ }
7809
+ }
7810
+ }
7811
+ };
7812
+ await walk3(scanPath);
7813
+ return found.sort();
7814
+ }
7815
+ async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
7816
+ let fallback = null;
7817
+ for (const file of hookFiles) {
7818
+ const content = await import_node_fs26.promises.readFile(import_node_path44.default.join(scanPath, file), "utf8");
7819
+ const patched = splicedContent(content, snippet2);
7820
+ if (patched !== null) return { file, content, patched };
7821
+ if (fallback === null) fallback = { file, content };
7822
+ }
7823
+ return { file: fallback.file, content: fallback.content, patched: null };
7786
7824
  }
7787
7825
  function extendLogPath() {
7788
7826
  return process.env.NEAT_EXTEND_LOG ?? import_node_path44.default.join(import_node_os2.default.homedir(), ".neat", "extend-log.ndjson");
@@ -7875,7 +7913,13 @@ async function applyExtension(ctx, args, options) {
7875
7913
  return { library: args.library, filesTouched: [], depsAdded: [], installOutput: "", alreadyApplied: true };
7876
7914
  }
7877
7915
  }
7878
- const primaryFile = hookFiles[0];
7916
+ const primary = await pickPrimaryHookFile(ctx.scanPath, hookFiles, args.registration_snippet);
7917
+ if (primary.patched === null) {
7918
+ throw new Error(
7919
+ `Could not find instrumentation insertion point in ${hookFiles.join(", ")}. Expected __INSTRUMENTATION_BLOCK__, instrumentations.push(, or new NodeSDK(.`
7920
+ );
7921
+ }
7922
+ const primaryFile = primary.file;
7879
7923
  const primaryPath = import_node_path44.default.join(ctx.scanPath, primaryFile);
7880
7924
  const filesTouched = [];
7881
7925
  const depsAdded = [];
@@ -7887,14 +7931,7 @@ async function applyExtension(ctx, args, options) {
7887
7931
  filesTouched.push("package.json");
7888
7932
  depsAdded.push(`${args.instrumentation_package}@${args.version}`);
7889
7933
  }
7890
- const hookContent = await import_node_fs26.promises.readFile(primaryPath, "utf8");
7891
- const patched = splicedContent(hookContent, args.registration_snippet);
7892
- if (!patched) {
7893
- throw new Error(
7894
- `Could not find instrumentation insertion point in ${primaryFile}. Expected __INSTRUMENTATION_BLOCK__, instrumentations.push(, or new NodeSDK(.`
7895
- );
7896
- }
7897
- await import_node_fs26.promises.writeFile(primaryPath, patched, "utf8");
7934
+ await import_node_fs26.promises.writeFile(primaryPath, primary.patched, "utf8");
7898
7935
  filesTouched.push(primaryFile);
7899
7936
  const cmd = await detectPackageManager(ctx.scanPath);
7900
7937
  const installer = options?.runInstall ?? runPackageManagerInstall;
@@ -7936,7 +7973,7 @@ async function dryRunExtension(ctx, args) {
7936
7973
  };
7937
7974
  }
7938
7975
  }
7939
- const primaryFile = hookFiles[0];
7976
+ const primary = await pickPrimaryHookFile(ctx.scanPath, hookFiles, args.registration_snippet);
7940
7977
  const filesTouched = [];
7941
7978
  const depsToAdd = [];
7942
7979
  let packageJsonPatch = {};
@@ -7947,10 +7984,8 @@ async function dryRunExtension(ctx, args) {
7947
7984
  depsToAdd.push(`${args.instrumentation_package}@${args.version}`);
7948
7985
  filesTouched.push("package.json");
7949
7986
  }
7950
- const hookContent = await import_node_fs26.promises.readFile(import_node_path44.default.join(ctx.scanPath, primaryFile), "utf8");
7951
- const patched = splicedContent(hookContent, args.registration_snippet);
7952
- if (patched) {
7953
- filesTouched.push(primaryFile);
7987
+ if (primary.patched !== null) {
7988
+ filesTouched.push(primary.file);
7954
7989
  templatePatch = `+ ${args.registration_snippet}`;
7955
7990
  } else {
7956
7991
  templatePatch = "Could not find insertion point in hook file.";
@@ -9488,7 +9523,7 @@ function registerRoutes(scope, ctx) {
9488
9523
  });
9489
9524
  }
9490
9525
  async function buildApi(opts) {
9491
- const app = (0, import_fastify.default)({ logger: false });
9526
+ const app = (0, import_fastify.default)({ logger: false, routerOptions: { maxParamLength: 1024 } });
9492
9527
  await app.register(import_cors.default, { origin: true });
9493
9528
  const env = readAuthEnv();
9494
9529
  const authToken = opts.authToken ?? env.authToken;
@@ -9665,8 +9700,8 @@ async function runConnectorPoll(connector, ctx, graph, resolveTarget) {
9665
9700
  line: callSite.line
9666
9701
  } : void 0;
9667
9702
  const calls = Math.trunc(signal.callCount);
9668
- if (calls < 1) continue;
9669
- const errors = Math.min(Math.max(Math.trunc(signal.errorCount), 0), calls);
9703
+ if (!Number.isFinite(calls) || calls < 1) continue;
9704
+ const errors = Number.isFinite(signal.errorCount) ? Math.min(Math.max(Math.trunc(signal.errorCount), 0), calls) : 0;
9670
9705
  let created = false;
9671
9706
  let ok = true;
9672
9707
  for (let i = 0; i < calls; i++) {
@@ -10113,7 +10148,10 @@ function targetFromRestPath(path53) {
10113
10148
  var ERROR_STATUS_THRESHOLD = 500;
10114
10149
  function mapEdgeLogRowsToSignals(rows) {
10115
10150
  const buckets2 = /* @__PURE__ */ new Map();
10151
+ if (!Array.isArray(rows)) return [];
10116
10152
  for (const row of rows) {
10153
+ if (!row || typeof row !== "object") continue;
10154
+ if (typeof row.path !== "string" || typeof row.timestamp !== "string") continue;
10117
10155
  const target = targetFromRestPath(row.path);
10118
10156
  if (!target) continue;
10119
10157
  const key = `${target.targetKind}:${target.name}`;
@@ -10154,9 +10192,12 @@ function tableNameFromQueryText(query) {
10154
10192
  function diffPgStatStatementsToSignals(rows, previous, nowIso2) {
10155
10193
  const signals = [];
10156
10194
  const seen = /* @__PURE__ */ new Set();
10195
+ if (!Array.isArray(rows)) return signals;
10157
10196
  for (const row of rows) {
10158
- seen.add(row.queryid);
10197
+ if (!row || typeof row !== "object" || typeof row.queryid !== "string") continue;
10159
10198
  const calls = Number(row.calls);
10199
+ if (!Number.isFinite(calls)) continue;
10200
+ seen.add(row.queryid);
10160
10201
  const prior = previous.get(row.queryid);
10161
10202
  previous.set(row.queryid, { calls });
10162
10203
  if (!prior || calls < prior.calls) continue;
@@ -10480,7 +10521,12 @@ function upsertBucket(buckets2, key, isError, timestamp, build) {
10480
10521
  }
10481
10522
  function mapRailwayHttpLogsToSignals(entries, routeIndex) {
10482
10523
  const buckets2 = /* @__PURE__ */ new Map();
10524
+ if (!Array.isArray(entries)) return [];
10483
10525
  for (const entry2 of entries) {
10526
+ if (!entry2 || typeof entry2 !== "object") continue;
10527
+ if (typeof entry2.method !== "string" || typeof entry2.path !== "string" || typeof entry2.timestamp !== "string") {
10528
+ continue;
10529
+ }
10484
10530
  const method = entry2.method.toUpperCase();
10485
10531
  const normalizedPath = normalizePathTemplate(entry2.path);
10486
10532
  const match = findRailwayRoute(routeIndex, method, normalizedPath);
@@ -10519,8 +10565,11 @@ function mapRailwayHttpLogsToSignals(entries, routeIndex) {
10519
10565
  }
10520
10566
  function mapRailwayNetworkFlowLogsToSignals(entries) {
10521
10567
  const buckets2 = /* @__PURE__ */ new Map();
10568
+ if (!Array.isArray(entries)) return [];
10522
10569
  for (const entry2 of entries) {
10523
- if (!entry2.peerServiceId) continue;
10570
+ if (!entry2 || typeof entry2 !== "object") continue;
10571
+ if (typeof entry2.peerServiceId !== "string" || entry2.peerServiceId.length === 0) continue;
10572
+ if (typeof entry2.timestamp !== "string") continue;
10524
10573
  const isError = entry2.dropCause !== null && entry2.dropCause !== "";
10525
10574
  upsertBucket(buckets2, entry2.peerServiceId, isError, entry2.timestamp, () => ({
10526
10575
  targetKind: PEER_SERVICE_TARGET_KIND,
@@ -10648,7 +10697,7 @@ async function fetchHttpRequestLogEntries(creds, sinceIso) {
10648
10697
  throw new Error(`Cloud Logging entries.list failed: ${res.status} ${res.statusText}`);
10649
10698
  }
10650
10699
  const json = await res.json();
10651
- out.push(...json.entries ?? []);
10700
+ if (Array.isArray(json.entries)) out.push(...json.entries);
10652
10701
  if (!json.nextPageToken) break;
10653
10702
  pageToken = json.nextPageToken;
10654
10703
  }
@@ -10685,7 +10734,7 @@ function resourceNameFor(type, labels) {
10685
10734
  }
10686
10735
  }
10687
10736
  function pathFromRequestUrl(requestUrl) {
10688
- if (!requestUrl) return null;
10737
+ if (typeof requestUrl !== "string" || requestUrl.length === 0) return null;
10689
10738
  if (requestUrl.startsWith("/")) {
10690
10739
  const withoutQuery = requestUrl.split("?")[0];
10691
10740
  return withoutQuery && withoutQuery.length > 0 ? withoutQuery : "/";
@@ -10700,18 +10749,19 @@ function pathFromRequestUrl(requestUrl) {
10700
10749
  }
10701
10750
  var ERROR_STATUS_THRESHOLD2 = 500;
10702
10751
  function mapLogEntryToSignal(entry2) {
10752
+ if (!entry2 || typeof entry2 !== "object") return null;
10703
10753
  const resourceType = entry2.resource?.type;
10704
10754
  if (!resourceType || !isFirebaseResourceType(resourceType)) return null;
10705
10755
  const resourceName = resourceNameFor(resourceType, entry2.resource?.labels);
10706
10756
  if (!resourceName) return null;
10707
10757
  const req2 = entry2.httpRequest;
10708
10758
  if (!req2) return null;
10709
- if (!req2.requestMethod) return null;
10759
+ if (typeof req2.requestMethod !== "string" || req2.requestMethod.length === 0) return null;
10710
10760
  const method = req2.requestMethod.toUpperCase();
10711
10761
  const path53 = pathFromRequestUrl(req2.requestUrl);
10712
10762
  if (path53 === null) return null;
10713
10763
  const timestamp = entry2.timestamp;
10714
- if (!timestamp) return null;
10764
+ if (typeof timestamp !== "string" || timestamp.length === 0) return null;
10715
10765
  const isError = typeof req2.status === "number" && req2.status >= ERROR_STATUS_THRESHOLD2;
10716
10766
  return {
10717
10767
  targetKind: resourceType,
@@ -10863,7 +10913,7 @@ async function queryWorkerInvocations(ctx, config, window, fetchImpl = fetch) {
10863
10913
  throw new Error(`cloudflare connector: telemetry query returned an error (${message})`);
10864
10914
  }
10865
10915
  const events = payload.result?.events?.events;
10866
- if (events === void 0) {
10916
+ if (!Array.isArray(events)) {
10867
10917
  console.warn(
10868
10918
  "[neat connector] cloudflare: telemetry query returned success:true but no result.events.events array \u2014 the response shape may have changed; treating as zero events this tick"
10869
10919
  );
@@ -10893,7 +10943,7 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
10893
10943
  ]);
10894
10944
  var LEADING_TOKEN_RE = /^(\S+)\s+\S/;
10895
10945
  function parseHttpMethodFromTrigger(trigger) {
10896
- if (!trigger) return null;
10946
+ if (typeof trigger !== "string") return null;
10897
10947
  const match = LEADING_TOKEN_RE.exec(trigger.trim());
10898
10948
  const token = match?.[1];
10899
10949
  if (!token) return null;
@@ -10909,14 +10959,17 @@ function parsePathFromTrigger(trigger) {
10909
10959
  }
10910
10960
  var ERROR_STATUS_THRESHOLD3 = 500;
10911
10961
  function mapEventToSignal(event) {
10962
+ if (!event || typeof event !== "object") return null;
10912
10963
  const metadata = event.$metadata;
10913
10964
  const workers = event.$workers;
10914
10965
  const method = parseHttpMethodFromTrigger(metadata?.trigger);
10915
10966
  if (!method) return null;
10916
10967
  const scriptName = workers?.scriptName ?? metadata?.service;
10917
- if (!scriptName) return null;
10968
+ if (typeof scriptName !== "string" || scriptName.length === 0) return null;
10918
10969
  const timestampMs = event.timestamp ?? metadata?.startTime;
10919
10970
  if (typeof timestampMs !== "number" || !Number.isFinite(timestampMs)) return null;
10971
+ const observedAt = new Date(timestampMs);
10972
+ if (Number.isNaN(observedAt.getTime())) return null;
10920
10973
  const statusCode = metadata?.statusCode;
10921
10974
  const isError = typeof statusCode === "number" && statusCode >= ERROR_STATUS_THRESHOLD3;
10922
10975
  const path53 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
@@ -10925,7 +10978,7 @@ function mapEventToSignal(event) {
10925
10978
  targetName: scriptName,
10926
10979
  callCount: 1,
10927
10980
  errorCount: isError ? 1 : 0,
10928
- lastObservedIso: new Date(timestampMs).toISOString(),
10981
+ lastObservedIso: observedAt.toISOString(),
10929
10982
  method,
10930
10983
  ...path53 ? { path: path53 } : {},
10931
10984
  ...typeof statusCode === "number" ? { statusCode } : {},