@neat.is/core 0.10.5 → 0.10.6-dev.20261007

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.
@@ -14,6 +14,7 @@ import {
14
14
  listProjects,
15
15
  loadGraphFromDisk,
16
16
  makeErrorSpanWriter,
17
+ maybeStartRepoSync,
17
18
  nodeContext,
18
19
  pathsForProject,
19
20
  promoteFrontierEdges,
@@ -33,7 +34,7 @@ import {
33
34
  startStalenessLoop,
34
35
  touchLastSeen,
35
36
  writeAtomically
36
- } from "./chunk-DVCGDMTZ.js";
37
+ } from "./chunk-KTJK2PAH.js";
37
38
  import {
38
39
  assertBindAuthority,
39
40
  buildOtelReceiver,
@@ -49,7 +50,7 @@ import {
49
50
  unlinkSync,
50
51
  writeFileSync
51
52
  } from "fs";
52
- import path4 from "path";
53
+ import path3 from "path";
53
54
  import { createRequire } from "module";
54
55
 
55
56
  // src/hang-sensor.ts
@@ -117,13 +118,13 @@ function decodeRailwayTargetRef(ref) {
117
118
  var CREDENTIAL_REFRESH_SKEW_MS = 6e4;
118
119
  var CP_REQUEST_TIMEOUT_MS = 1e4;
119
120
  var DEFAULT_RELIST_INTERVAL_MS = 6e4;
120
- async function cpGet(path5, deps) {
121
+ async function cpGet(path4, deps) {
121
122
  const f = deps.fetchImpl ?? fetch;
122
- const res = await f(`${deps.cpUrl.replace(/\/+$/, "")}${path5}`, {
123
+ const res = await f(`${deps.cpUrl.replace(/\/+$/, "")}${path4}`, {
123
124
  headers: { authorization: `Bearer ${deps.daemonToken}`, accept: "application/json" },
124
125
  signal: AbortSignal.timeout(CP_REQUEST_TIMEOUT_MS)
125
126
  });
126
- if (!res.ok) throw new Error(`control plane ${path5} \u2192 HTTP ${res.status}`);
127
+ if (!res.ok) throw new Error(`control plane ${path4} \u2192 HTTP ${res.status}`);
127
128
  return await res.json();
128
129
  }
129
130
  function credentialRecord(provider, cred) {
@@ -195,14 +196,14 @@ async function readPushHandles(projectDir) {
195
196
  }
196
197
  }
197
198
  async function writePushHandle(projectDir, provider, handle) {
198
- const path5 = pushHandlesPath(projectDir);
199
+ const path4 = pushHandlesPath(projectDir);
199
200
  const handles = await readPushHandles(projectDir);
200
201
  handles[provider] = handle;
201
- await mkdir(dirname(path5), { recursive: true });
202
- const tmp = `${path5}.${process.pid}.tmp`;
202
+ await mkdir(dirname(path4), { recursive: true });
203
+ const tmp = `${path4}.${process.pid}.tmp`;
203
204
  await writeFile(tmp, `${JSON.stringify(handles, null, 2)}
204
205
  `, "utf8");
205
- await rename(tmp, path5);
206
+ await rename(tmp, path4);
206
207
  }
207
208
  function pushCredentialRecord(provider, cred, deps) {
208
209
  switch (provider) {
@@ -420,190 +421,6 @@ async function maybeStartHostedConnectors(input) {
420
421
  });
421
422
  }
422
423
 
423
- // src/connectors/hosted-repos.ts
424
- import os from "os";
425
- import path from "path";
426
- import { mkdtemp, rm } from "fs/promises";
427
- var CP_REQUEST_TIMEOUT_MS2 = 1e4;
428
- var DEFAULT_SYNC_INTERVAL_MS = 5 * 6e4;
429
- var CLONE_TIMEOUT_MS = 5 * 6e4;
430
- function scrubToken(s) {
431
- return s.replace(/x-access-token:[^@\s]+@/g, "x-access-token:***@");
432
- }
433
- async function cpGet2(pathname, deps) {
434
- const f = deps.fetchImpl ?? fetch;
435
- const res = await f(`${deps.cpUrl.replace(/\/+$/, "")}${pathname}`, {
436
- headers: { authorization: `Bearer ${deps.daemonToken}`, accept: "application/json" },
437
- signal: AbortSignal.timeout(CP_REQUEST_TIMEOUT_MS2)
438
- });
439
- if (!res.ok) throw new Error(`control plane ${pathname} \u2192 HTTP ${res.status}`);
440
- return await res.json();
441
- }
442
- async function cpPostStatus(deps, owner, name, body) {
443
- const f = deps.fetchImpl ?? fetch;
444
- const url = `${deps.cpUrl.replace(/\/+$/, "")}/internal/projects/${deps.projectId}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}/status`;
445
- const res = await f(url, {
446
- method: "POST",
447
- headers: { authorization: `Bearer ${deps.daemonToken}`, "content-type": "application/json" },
448
- body: JSON.stringify(body),
449
- signal: AbortSignal.timeout(CP_REQUEST_TIMEOUT_MS2)
450
- });
451
- if (!res.ok && res.status !== 404) throw new Error(`control plane status POST \u2192 HTTP ${res.status}`);
452
- }
453
- var defaultCloneRepo = async (cloneUrl, ref, destDir) => {
454
- const [{ default: git }, httpMod, fs3] = await Promise.all([
455
- import("isomorphic-git"),
456
- import("isomorphic-git/http/node"),
457
- import("fs")
458
- ]);
459
- const http = httpMod.default ?? httpMod;
460
- const parsed = new URL(cloneUrl);
461
- const password = parsed.password || parsed.username;
462
- const username = parsed.password ? parsed.username : "x-access-token";
463
- const cleanUrl = `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
464
- const clone = git.clone({
465
- fs: fs3,
466
- http,
467
- dir: destDir,
468
- url: cleanUrl,
469
- // Absent ref → isomorphic-git clones the remote's default branch.
470
- ...ref ? { ref } : {},
471
- singleBranch: true,
472
- depth: 1,
473
- onAuth: () => ({ username, password })
474
- });
475
- let timer;
476
- const timeout = new Promise((_, reject) => {
477
- timer = setTimeout(() => reject(new Error(`clone timed out after ${CLONE_TIMEOUT_MS}ms`)), CLONE_TIMEOUT_MS);
478
- });
479
- try {
480
- await Promise.race([clone, timeout]);
481
- } finally {
482
- if (timer) clearTimeout(timer);
483
- }
484
- };
485
- function needsSync(r) {
486
- return r.syncStatus === void 0 || r.syncStatus === "syncing";
487
- }
488
- async function syncOneRepo(r, input) {
489
- const { deps, graph } = input;
490
- const cloneRepo = input.cloneRepo ?? defaultCloneRepo;
491
- const extract = input.extract ?? extractFromDirectory;
492
- const label = `${r.owner}/${r.name}`;
493
- const tmpRoot = input.tmpRoot ?? os.tmpdir();
494
- let dir;
495
- try {
496
- dir = await mkdtemp(path.join(tmpRoot, "neat-repo-"));
497
- await cpPostStatus(deps, r.owner, r.name, { syncStatus: "syncing", detail: "cloning" }).catch(() => {
498
- });
499
- await cloneRepo(r.cloneUrl, r.defaultBranch, dir);
500
- const extracted = await extract(graph, dir, { source: label });
501
- const nodes = extracted?.nodesAdded ?? 0;
502
- const edges = extracted?.edgesAdded ?? 0;
503
- await cpPostStatus(deps, r.owner, r.name, {
504
- syncStatus: "synced",
505
- detail: `extracted ${nodes} node${nodes === 1 ? "" : "s"}, ${edges} edge${edges === 1 ? "" : "s"}`,
506
- lastSyncAt: new Date(input.now?.() ?? Date.now()).toISOString()
507
- });
508
- return true;
509
- } catch (err) {
510
- input.onError?.(label, err);
511
- await cpPostStatus(deps, r.owner, r.name, {
512
- syncStatus: "failed",
513
- detail: scrubToken(err.message).slice(0, 300)
514
- }).catch(() => {
515
- });
516
- return false;
517
- } finally {
518
- if (dir) await rm(dir, { recursive: true, force: true }).catch(() => {
519
- });
520
- }
521
- }
522
- async function runRepoSyncPassCounted(input) {
523
- const counts = { listed: false, synced: 0, failed: 0 };
524
- let repos;
525
- try {
526
- repos = await cpGet2(`/internal/projects/${input.deps.projectId}/repos`, input.deps);
527
- } catch (err) {
528
- input.onSkip?.("(all)", `control plane repo list unreadable \u2014 ${err.message}`);
529
- return counts;
530
- }
531
- if (!Array.isArray(repos)) return counts;
532
- counts.listed = true;
533
- for (const r of repos) {
534
- if (!input.forceResync && !needsSync(r)) continue;
535
- if (await syncOneRepo(r, input)) counts.synced++;
536
- else counts.failed++;
537
- }
538
- return counts;
539
- }
540
- async function startRepoSync(input) {
541
- const intervalMs = input.intervalMs ?? DEFAULT_SYNC_INTERVAL_MS;
542
- const now = () => input.now?.() ?? Date.now();
543
- let stopped = false;
544
- let inFlight = null;
545
- let again = false;
546
- let lastPass;
547
- let bootResyncDone = false;
548
- const run = async () => {
549
- try {
550
- do {
551
- again = false;
552
- const startedAt = new Date(now()).toISOString();
553
- const counts = await runRepoSyncPassCounted({ ...input, forceResync: !bootResyncDone });
554
- if (counts.listed) bootResyncDone = true;
555
- lastPass = { ...counts, startedAt, finishedAt: new Date(now()).toISOString() };
556
- } while (again && !stopped);
557
- } finally {
558
- inFlight = null;
559
- }
560
- };
561
- const tick = () => {
562
- if (stopped || inFlight) return;
563
- inFlight = run();
564
- };
565
- tick();
566
- const timer = setInterval(tick, intervalMs);
567
- if (typeof timer.unref === "function") timer.unref();
568
- const stop = () => {
569
- stopped = true;
570
- clearInterval(timer);
571
- };
572
- return Object.assign(stop, {
573
- syncNow: () => {
574
- const summary = lastPass ? { lastPass } : {};
575
- if (inFlight) {
576
- again = true;
577
- return { status: "queued", ...summary };
578
- }
579
- inFlight = run();
580
- return { status: "started", ...summary };
581
- },
582
- settled: async () => {
583
- while (inFlight) await inFlight;
584
- }
585
- });
586
- }
587
- async function maybeStartRepoSync(input) {
588
- const env = input.env ?? process.env;
589
- const cpUrl = env.NEAT_CP_URL;
590
- const projectId = env.NEAT_CP_PROJECT_ID;
591
- const daemonToken = env.NEAT_AUTH_TOKEN;
592
- if (!cpUrl || !projectId || !daemonToken) return () => {
593
- };
594
- return startRepoSync({
595
- deps: { cpUrl, projectId, daemonToken, ...input.fetchImpl ? { fetchImpl: input.fetchImpl } : {} },
596
- graph: input.graph,
597
- project: input.project,
598
- ...input.cloneRepo ? { cloneRepo: input.cloneRepo } : {},
599
- ...input.extract ? { extract: input.extract } : {},
600
- ...input.intervalMs !== void 0 ? { intervalMs: input.intervalMs } : {},
601
- ...input.tmpRoot ? { tmpRoot: input.tmpRoot } : {},
602
- ...input.onSkip ? { onSkip: input.onSkip } : {},
603
- ...input.onError ? { onError: input.onError } : {}
604
- });
605
- }
606
-
607
424
  // src/connectors/kubernetes/client.ts
608
425
  import { Agent, request as httpsRequest } from "https";
609
426
  function deploymentsPath(namespace) {
@@ -653,9 +470,9 @@ function makeK8sFetchImpl(transport) {
653
470
  req.end();
654
471
  }));
655
472
  }
656
- async function listResource(transport, namespace, path5, opts = {}) {
473
+ async function listResource(transport, namespace, path4, opts = {}) {
657
474
  const base = opts.apiUrl ?? transport.server;
658
- const url = `${base.replace(/\/$/, "")}${path5}`;
475
+ const url = `${base.replace(/\/$/, "")}${path4}`;
659
476
  const fetchImpl = opts.fetchImpl ?? makeK8sFetchImpl(transport);
660
477
  const res = await junctionFetch(
661
478
  url,
@@ -665,7 +482,7 @@ async function listResource(transport, namespace, path5, opts = {}) {
665
482
  { provider: "kubernetes", accountKey: `${safeHost(transport.server)}/${namespace}`, fetchImpl }
666
483
  );
667
484
  if (!res.ok) {
668
- throw new Error(`kubernetes ${path5} failed: ${res.status} ${res.statusText}`);
485
+ throw new Error(`kubernetes ${path4} failed: ${res.status} ${res.statusText}`);
669
486
  }
670
487
  const json = await res.json();
671
488
  return Array.isArray(json.items) ? json.items : [];
@@ -961,15 +778,15 @@ function createK8sResolveTarget(graph) {
961
778
 
962
779
  // src/connectors/kubernetes/substrate.ts
963
780
  import { readFile as readFile2 } from "fs/promises";
964
- import os2 from "os";
965
- import path2 from "path";
781
+ import os from "os";
782
+ import path from "path";
966
783
  function defaultHome() {
967
784
  const override = process.env.NEAT_HOME;
968
- if (override && override.length > 0) return path2.resolve(override);
969
- return path2.join(os2.homedir(), ".neat");
785
+ if (override && override.length > 0) return path.resolve(override);
786
+ return path.join(os.homedir(), ".neat");
970
787
  }
971
788
  function k8sSubstrateConfigPath(home = defaultHome()) {
972
- return path2.join(home, "k8s.json");
789
+ return path.join(home, "k8s.json");
973
790
  }
974
791
  async function readK8sSubstrateConfig(home = defaultHome()) {
975
792
  let raw;
@@ -1065,7 +882,7 @@ function createKubernetesConnector(graph, config, fetchImpl) {
1065
882
 
1066
883
  // src/unrouted.ts
1067
884
  import { promises as fs } from "fs";
1068
- import path3 from "path";
885
+ import path2 from "path";
1069
886
  function buildUnroutedSpanRecord(serviceName, traceId, now = /* @__PURE__ */ new Date()) {
1070
887
  return {
1071
888
  timestamp: now.toISOString(),
@@ -1075,34 +892,34 @@ function buildUnroutedSpanRecord(serviceName, traceId, now = /* @__PURE__ */ new
1075
892
  };
1076
893
  }
1077
894
  async function appendUnroutedSpan(neatHome, record) {
1078
- const target = path3.join(neatHome, "errors.ndjson");
895
+ const target = path2.join(neatHome, "errors.ndjson");
1079
896
  await fs.mkdir(neatHome, { recursive: true });
1080
897
  await fs.appendFile(target, JSON.stringify(record) + "\n", "utf8");
1081
898
  }
1082
899
  function unroutedErrorsPath(neatHome) {
1083
- return path3.join(neatHome, "errors.ndjson");
900
+ return path2.join(neatHome, "errors.ndjson");
1084
901
  }
1085
902
 
1086
903
  // src/daemon.ts
1087
904
  import { NodeType } from "@neat.is/types";
1088
905
  function daemonJsonPath(scanPath) {
1089
- return path4.join(scanPath, "neat-out", "daemon.json");
906
+ return path3.join(scanPath, "neat-out", "daemon.json");
1090
907
  }
1091
908
  function daemonsDiscoveryDir(home) {
1092
909
  const base = home && home.length > 0 ? home : neatHomeFromEnv();
1093
- return path4.join(base, "daemons");
910
+ return path3.join(base, "daemons");
1094
911
  }
1095
912
  function daemonDiscoveryPath(project, home) {
1096
- return path4.join(daemonsDiscoveryDir(home), `${sanitizeDiscoveryName(project)}.json`);
913
+ return path3.join(daemonsDiscoveryDir(home), `${sanitizeDiscoveryName(project)}.json`);
1097
914
  }
1098
915
  function sanitizeDiscoveryName(project) {
1099
916
  return project.replace(/[^A-Za-z0-9._-]/g, "_");
1100
917
  }
1101
918
  function neatHomeFromEnv() {
1102
919
  const env = process.env.NEAT_HOME;
1103
- if (env && env.length > 0) return path4.resolve(env);
920
+ if (env && env.length > 0) return path3.resolve(env);
1104
921
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
1105
- return path4.join(home, ".neat");
922
+ return path3.join(home, ".neat");
1106
923
  }
1107
924
  async function readDaemonRecord(scanPath) {
1108
925
  try {
@@ -1195,11 +1012,11 @@ function teardownSlot(slot) {
1195
1012
  }
1196
1013
  }
1197
1014
  function neatHomeFor(opts) {
1198
- if (opts.neatHome && opts.neatHome.length > 0) return path4.resolve(opts.neatHome);
1015
+ if (opts.neatHome && opts.neatHome.length > 0) return path3.resolve(opts.neatHome);
1199
1016
  const env = process.env.NEAT_HOME;
1200
- if (env && env.length > 0) return path4.resolve(env);
1017
+ if (env && env.length > 0) return path3.resolve(env);
1201
1018
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
1202
- return path4.join(home, ".neat");
1019
+ return path3.join(home, ".neat");
1203
1020
  }
1204
1021
  function routeSpanToProject(serviceName, projects) {
1205
1022
  if (!serviceName) return DEFAULT_PROJECT;
@@ -1251,7 +1068,7 @@ function spanBelongsToSingleProject(graph, project, serviceName) {
1251
1068
  );
1252
1069
  }
1253
1070
  async function bootstrapProject(entry, connectors = [], neatHome) {
1254
- const paths = pathsForProject(entry.name, path4.join(entry.path, "neat-out"));
1071
+ const paths = pathsForProject(entry.name, path3.join(entry.path, "neat-out"));
1255
1072
  try {
1256
1073
  const stat = await fs2.stat(entry.path);
1257
1074
  if (!stat.isDirectory()) {
@@ -1406,7 +1223,7 @@ async function startDaemon(opts = {}) {
1406
1223
  const projectArg = typeof opts.project === "string" && opts.project.length > 0 ? opts.project : process.env.NEAT_PROJECT && process.env.NEAT_PROJECT.length > 0 ? process.env.NEAT_PROJECT : null;
1407
1224
  const projectPathArg = opts.projectPath && opts.projectPath.length > 0 ? opts.projectPath : process.env.NEAT_PROJECT_PATH && process.env.NEAT_PROJECT_PATH.length > 0 ? process.env.NEAT_PROJECT_PATH : null;
1408
1225
  const singleProject = projectArg;
1409
- const singleProjectPath = singleProject && projectPathArg ? path4.resolve(projectPathArg) : null;
1226
+ const singleProjectPath = singleProject && projectPathArg ? path3.resolve(projectPathArg) : null;
1410
1227
  if (singleProject && !singleProjectPath) {
1411
1228
  throw new Error(
1412
1229
  `neatd: project "${singleProject}" given without a projectPath; pass NEAT_PROJECT_PATH alongside NEAT_PROJECT.`
@@ -1421,7 +1238,7 @@ async function startDaemon(opts = {}) {
1421
1238
  );
1422
1239
  }
1423
1240
  }
1424
- const pidPath = path4.join(home, "neatd.pid");
1241
+ const pidPath = path3.join(home, "neatd.pid");
1425
1242
  await writeAtomically(pidPath, `${process.pid}
1426
1243
  `);
1427
1244
  const slots = /* @__PURE__ */ new Map();
@@ -1902,8 +1719,8 @@ async function startDaemon(opts = {}) {
1902
1719
  let registryWatcher = null;
1903
1720
  let reloadTimer = null;
1904
1721
  if (!singleProject) try {
1905
- const regDir = path4.dirname(regPath);
1906
- const regBase = path4.basename(regPath);
1722
+ const regDir = path3.dirname(regPath);
1723
+ const regBase = path3.basename(regPath);
1907
1724
  registryWatcher = watch(regDir, (_eventType, filename) => {
1908
1725
  if (filename !== null && filename !== regBase) return;
1909
1726
  if (reloadTimer) clearTimeout(reloadTimer);
@@ -1983,4 +1800,4 @@ export {
1983
1800
  resolveHost,
1984
1801
  startDaemon
1985
1802
  };
1986
- //# sourceMappingURL=chunk-Q2SL2SVH.js.map
1803
+ //# sourceMappingURL=chunk-VL7ANDPI.js.map