@neat.is/core 0.4.20-dev.20260620 → 0.4.20-dev.20260622

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-ZV7GHZ2D.js";
4
+ } from "./chunk-62ELQVIP.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-Q5EDVWKZ.js";
40
+ } from "./chunk-GNAX2CBF.js";
41
41
  import {
42
42
  startOtelGrpcReceiver
43
43
  } from "./chunk-MTXF77TN.js";
package/dist/neatd.cjs CHANGED
@@ -1888,13 +1888,14 @@ var parentSpanCache = /* @__PURE__ */ new Map();
1888
1888
  function parentSpanKey(traceId, spanId) {
1889
1889
  return `${traceId}:${spanId}`;
1890
1890
  }
1891
- function cacheSpanService(span, now) {
1891
+ function cacheSpanService(span, now, callSite) {
1892
1892
  if (!span.traceId || !span.spanId) return;
1893
1893
  const key = parentSpanKey(span.traceId, span.spanId);
1894
1894
  parentSpanCache.delete(key);
1895
1895
  parentSpanCache.set(key, {
1896
1896
  service: span.service,
1897
1897
  env: span.env ?? "unknown",
1898
+ ...callSite ? { callSite } : {},
1898
1899
  expiresAt: now + PARENT_SPAN_CACHE_TTL_MS
1899
1900
  });
1900
1901
  while (parentSpanCache.size > PARENT_SPAN_CACHE_SIZE) {
@@ -1910,7 +1911,11 @@ function lookupParentSpan(traceId, parentSpanId, now) {
1910
1911
  parentSpanCache.delete(parentSpanKey(traceId, parentSpanId));
1911
1912
  return null;
1912
1913
  }
1913
- return { service: entry2.service, env: entry2.env };
1914
+ return {
1915
+ service: entry2.service,
1916
+ env: entry2.env,
1917
+ ...entry2.callSite ? { callSite: entry2.callSite } : {}
1918
+ };
1914
1919
  }
1915
1920
  function resolveServiceId(graph, host, env) {
1916
1921
  const envTagged = (0, import_types3.serviceId)(host, env);
@@ -2183,9 +2188,9 @@ async function handleSpan(ctx, span) {
2183
2188
  }
2184
2189
  const sourceId = ensureServiceNode(ctx.graph, span.service, env);
2185
2190
  const isError = span.statusCode === 2;
2186
- cacheSpanService(span, nowMs);
2187
2191
  const sourceServiceNode = ctx.graph.getNodeAttributes(sourceId);
2188
2192
  const callSite = callSiteFromSpan(span, sourceServiceNode, ctx.scanPath);
2193
+ cacheSpanService(span, nowMs, callSite);
2189
2194
  const observedSource = () => callSite ? ensureObservedFileNode(ctx.graph, span.service, sourceId, callSite) : sourceId;
2190
2195
  const callSiteEvidence = callSite ? { file: callSite.relPath, ...callSite.line !== void 0 ? { line: callSite.line } : {} } : void 0;
2191
2196
  let affectedNode = sourceId;
@@ -2242,13 +2247,19 @@ async function handleSpan(ctx, span) {
2242
2247
  const parent = lookupParentSpan(span.traceId, span.parentSpanId, nowMs);
2243
2248
  if (parent && parent.service !== span.service) {
2244
2249
  const parentId = ensureServiceNode(ctx.graph, parent.service, parent.env);
2250
+ const fallbackSource = parent.callSite ? ensureObservedFileNode(ctx.graph, parent.service, parentId, parent.callSite) : parentId;
2251
+ const fallbackEvidence = parent.callSite ? {
2252
+ file: parent.callSite.relPath,
2253
+ ...parent.callSite.line !== void 0 ? { line: parent.callSite.line } : {}
2254
+ } : void 0;
2245
2255
  upsertObservedEdge(
2246
2256
  ctx.graph,
2247
2257
  import_types3.EdgeType.CALLS,
2248
- parentId,
2258
+ fallbackSource,
2249
2259
  sourceId,
2250
2260
  ts,
2251
- isError
2261
+ isError,
2262
+ fallbackEvidence
2252
2263
  );
2253
2264
  }
2254
2265
  }
@@ -2765,6 +2776,9 @@ function workspaceGlobs(pkg) {
2765
2776
  if (Array.isArray(ws.packages)) return ws.packages.length > 0 ? ws.packages : null;
2766
2777
  return null;
2767
2778
  }
2779
+ async function hasPythonManifest(dir) {
2780
+ return await exists(import_node_path8.default.join(dir, "pyproject.toml")) || await exists(import_node_path8.default.join(dir, "requirements.txt")) || await exists(import_node_path8.default.join(dir, "setup.py"));
2781
+ }
2768
2782
  async function loadGitignore(scanPath) {
2769
2783
  const gitignorePath = import_node_path8.default.join(scanPath, ".gitignore");
2770
2784
  if (!await exists(gitignorePath)) return null;
@@ -2831,6 +2845,13 @@ function detectJsFramework(pkg) {
2831
2845
  if (deps["astro"] !== void 0) return "astro";
2832
2846
  return void 0;
2833
2847
  }
2848
+ async function detectJsServiceLanguage(dir, pkg) {
2849
+ const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
2850
+ if (deps["typescript"] !== void 0) return "typescript";
2851
+ const entries = await import_node_fs8.promises.readdir(dir).catch(() => []);
2852
+ if (entries.some((name) => /^tsconfig(\..+)?\.json$/.test(name))) return "typescript";
2853
+ return "javascript";
2854
+ }
2834
2855
  async function discoverNodeService(scanPath, dir) {
2835
2856
  const pkgPath = import_node_path8.default.join(dir, "package.json");
2836
2857
  if (!await exists(pkgPath)) return null;
@@ -2843,11 +2864,12 @@ async function discoverNodeService(scanPath, dir) {
2843
2864
  }
2844
2865
  if (!pkg.name) return null;
2845
2866
  const framework = detectJsFramework(pkg);
2867
+ const language = await detectJsServiceLanguage(dir, pkg);
2846
2868
  const node = {
2847
2869
  id: (0, import_types5.serviceId)(pkg.name),
2848
2870
  type: import_types5.NodeType.ServiceNode,
2849
2871
  name: pkg.name,
2850
- language: "javascript",
2872
+ language,
2851
2873
  version: pkg.version,
2852
2874
  dependencies: pkg.dependencies ?? {},
2853
2875
  repoPath: import_node_path8.default.relative(scanPath, dir),
@@ -2890,7 +2912,11 @@ async function discoverServices(scanPath) {
2890
2912
  if (wsGlobs) {
2891
2913
  candidateDirs.push(...await expandWorkspaceGlobs(scanPath, wsGlobs));
2892
2914
  } else {
2893
- if (rootPkg && rootPkg.name) candidateDirs.push(scanPath);
2915
+ if (rootPkg && rootPkg.name) {
2916
+ candidateDirs.push(scanPath);
2917
+ } else if (await hasPythonManifest(scanPath)) {
2918
+ candidateDirs.push(scanPath);
2919
+ }
2894
2920
  const ig = await loadGitignore(scanPath);
2895
2921
  await walkDirs(
2896
2922
  scanPath,
@@ -2899,7 +2925,7 @@ async function discoverServices(scanPath) {
2899
2925
  async (dir) => {
2900
2926
  if (await exists(import_node_path8.default.join(dir, "package.json"))) {
2901
2927
  candidateDirs.push(dir);
2902
- } else if (await exists(import_node_path8.default.join(dir, "pyproject.toml")) || await exists(import_node_path8.default.join(dir, "requirements.txt")) || await exists(import_node_path8.default.join(dir, "setup.py"))) {
2928
+ } else if (await hasPythonManifest(dir)) {
2903
2929
  candidateDirs.push(dir);
2904
2930
  }
2905
2931
  }