@neat.is/core 0.9.5-dev.20260824 → 0.9.5

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.cjs CHANGED
@@ -16009,7 +16009,7 @@ function startPersistLoop(graph, outPath, opts = {}) {
16009
16009
  init_cjs_shims();
16010
16010
  var import_fastify2 = __toESM(require("fastify"), 1);
16011
16011
  var import_cors = __toESM(require("@fastify/cors"), 1);
16012
- var import_types93 = require("@neat.is/types");
16012
+ var import_types97 = require("@neat.is/types");
16013
16013
 
16014
16014
  // src/extend/index.ts
16015
16015
  init_cjs_shims();
@@ -20228,9 +20228,229 @@ function createCloudRunConnector(graph, config = {}) {
20228
20228
  };
20229
20229
  }
20230
20230
 
20231
+ // src/connectors/gcp-lb/index.ts
20232
+ init_cjs_shims();
20233
+
20234
+ // src/connectors/gcp-lb/client.ts
20235
+ init_cjs_shims();
20236
+ function gcpLbRequestLogName(projectId) {
20237
+ return `projects/${projectId}/logs/requests`;
20238
+ }
20239
+ function buildGcpLbEntriesFilter(projectId, sinceIso) {
20240
+ return [
20241
+ `logName = "${gcpLbRequestLogName(projectId)}"`,
20242
+ `resource.type = "${GCP_LB_RESOURCE_TYPE}"`,
20243
+ 'httpRequest.requestMethod != ""',
20244
+ `timestamp >= "${sinceIso}"`
20245
+ ].join(" AND ");
20246
+ }
20247
+ var GCP_LB_RESOURCE_TYPE = "http_load_balancer";
20248
+ var DEFAULT_LOOKBACK_MS3 = 24 * 60 * 60 * 1e3;
20249
+ var ENTRIES_LIST_URL3 = "https://logging.googleapis.com/v2/entries:list";
20250
+ var PAGE_SIZE3 = 1e3;
20251
+ var MAX_PAGES3 = 20;
20252
+ async function fetchGcpLbRequestLogEntries(creds, sinceIso, apiUrl = ENTRIES_LIST_URL3) {
20253
+ const filter = buildGcpLbEntriesFilter(creds.projectId, sinceIso);
20254
+ const out = [];
20255
+ let pageToken;
20256
+ for (let page = 0; page < MAX_PAGES3; page++) {
20257
+ const body = {
20258
+ resourceNames: [`projects/${creds.projectId}`],
20259
+ filter,
20260
+ orderBy: "timestamp asc",
20261
+ pageSize: PAGE_SIZE3,
20262
+ ...pageToken ? { pageToken } : {}
20263
+ };
20264
+ const res = await junctionFetch(
20265
+ apiUrl,
20266
+ {
20267
+ method: "POST",
20268
+ headers: {
20269
+ ...bearerAuthHeader(creds.accessToken),
20270
+ "Content-Type": "application/json"
20271
+ },
20272
+ body: JSON.stringify(body)
20273
+ },
20274
+ // accountKey: the GCP project id — one customer's Cloud Logging quota is
20275
+ // scoped per GCP project (ADR-131's per-(provider, accountKey) rate-limit
20276
+ // bucket), the same key Cloud Run's and Firebase's connectors use.
20277
+ { provider: "gcp-lb", accountKey: creds.projectId }
20278
+ );
20279
+ if (!res.ok) {
20280
+ throw new Error(`Cloud Logging entries.list failed: ${res.status} ${res.statusText}`);
20281
+ }
20282
+ const json = await res.json();
20283
+ if (Array.isArray(json.entries)) out.push(...json.entries);
20284
+ if (!json.nextPageToken) break;
20285
+ pageToken = json.nextPageToken;
20286
+ }
20287
+ return out;
20288
+ }
20289
+
20290
+ // src/connectors/gcp-lb/map.ts
20291
+ init_cjs_shims();
20292
+
20293
+ // src/connectors/gcp-lb/types.ts
20294
+ init_cjs_shims();
20295
+ function readGcpLbCredentials(raw) {
20296
+ const projectId = raw["projectId"];
20297
+ const accessToken = raw["accessToken"];
20298
+ if (typeof projectId !== "string" || projectId.length === 0) {
20299
+ throw new Error("gcp-lb connector: credentials.projectId must be a non-empty string");
20300
+ }
20301
+ if (typeof accessToken !== "string" || accessToken.length === 0) {
20302
+ throw new Error("gcp-lb connector: credentials.accessToken must be a non-empty string");
20303
+ }
20304
+ return { projectId, accessToken };
20305
+ }
20306
+ var GCP_LB_TARGET_KIND = "http_load_balancer";
20307
+ var FIELD_SEP3 = "\0";
20308
+ function packGcpLbTargetName(identity) {
20309
+ return [identity.backendServiceName, identity.method, identity.path].join(FIELD_SEP3);
20310
+ }
20311
+ function parseGcpLbTargetName(targetName) {
20312
+ const firstSep = targetName.indexOf(FIELD_SEP3);
20313
+ if (firstSep === -1) return null;
20314
+ const backendServiceName = targetName.slice(0, firstSep);
20315
+ const rest = targetName.slice(firstSep + 1);
20316
+ const secondSep = rest.indexOf(FIELD_SEP3);
20317
+ if (secondSep === -1) return null;
20318
+ const method = rest.slice(0, secondSep);
20319
+ const path76 = rest.slice(secondSep + 1);
20320
+ if (!backendServiceName || !method || !path76) return null;
20321
+ return { backendServiceName, method, path: path76 };
20322
+ }
20323
+
20324
+ // src/connectors/gcp-lb/map.ts
20325
+ var GCP_LB_RESOURCE_TYPE2 = "http_load_balancer";
20326
+ function pathFromRequestUrl3(requestUrl) {
20327
+ if (typeof requestUrl !== "string" || requestUrl.length === 0) return null;
20328
+ if (requestUrl.startsWith("/")) {
20329
+ const withoutQuery = requestUrl.split("?")[0];
20330
+ return withoutQuery && withoutQuery.length > 0 ? withoutQuery : "/";
20331
+ }
20332
+ try {
20333
+ const candidate = requestUrl.startsWith("//") ? `https:${requestUrl}` : requestUrl;
20334
+ const parsed = new URL(candidate);
20335
+ return parsed.pathname || "/";
20336
+ } catch {
20337
+ return null;
20338
+ }
20339
+ }
20340
+ var ERROR_STATUS_THRESHOLD5 = 500;
20341
+ function mapLogEntryToSignal3(entry) {
20342
+ if (!entry || typeof entry !== "object") return null;
20343
+ if (entry.resource?.type !== GCP_LB_RESOURCE_TYPE2) return null;
20344
+ const backendServiceName = entry.resource?.labels?.["backend_service_name"];
20345
+ if (typeof backendServiceName !== "string" || backendServiceName.length === 0) return null;
20346
+ const req = entry.httpRequest;
20347
+ if (!req) return null;
20348
+ if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
20349
+ const method = req.requestMethod.toUpperCase();
20350
+ const path76 = pathFromRequestUrl3(req.requestUrl);
20351
+ if (path76 === null) return null;
20352
+ const timestamp = entry.timestamp;
20353
+ if (typeof timestamp !== "string" || timestamp.length === 0) return null;
20354
+ const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD5;
20355
+ return {
20356
+ targetKind: GCP_LB_TARGET_KIND,
20357
+ targetName: packGcpLbTargetName({ backendServiceName, method, path: path76 }),
20358
+ callCount: 1,
20359
+ errorCount: isError ? 1 : 0,
20360
+ lastObservedIso: timestamp
20361
+ };
20362
+ }
20363
+ function mapLogEntriesToSignals3(entries) {
20364
+ const out = [];
20365
+ for (const entry of entries) {
20366
+ const signal = mapLogEntryToSignal3(entry);
20367
+ if (signal) out.push(signal);
20368
+ }
20369
+ return out;
20370
+ }
20371
+
20372
+ // src/connectors/gcp-lb/resolve.ts
20373
+ init_cjs_shims();
20374
+ var import_types82 = require("@neat.is/types");
20375
+ var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
20376
+ function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
20377
+ let found = null;
20378
+ graph.forEachNode((_id, attrs) => {
20379
+ if (found) return;
20380
+ const node = attrs;
20381
+ if (node.type !== import_types82.NodeType.RouteNode) return;
20382
+ const route = attrs;
20383
+ if (route.service !== serviceName || !route.pathTemplate) return;
20384
+ if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
20385
+ const routeMethod = route.method.toUpperCase();
20386
+ if (routeMethod !== "ALL" && routeMethod !== method) return;
20387
+ found = route.id;
20388
+ });
20389
+ return found;
20390
+ }
20391
+ function createGcpLbResolveTarget(graph, config) {
20392
+ return (signal) => {
20393
+ if (signal.targetKind !== GCP_LB_TARGET_KIND) return null;
20394
+ const identity = parseGcpLbTargetName(signal.targetName);
20395
+ if (!identity) return null;
20396
+ const { backendServiceName, method, path: path76 } = identity;
20397
+ const mappedService = config.backendServiceMap?.[backendServiceName];
20398
+ if (mappedService) {
20399
+ const routeNodeId = findMatchingRouteNode3(
20400
+ graph,
20401
+ mappedService,
20402
+ method,
20403
+ normalizePathTemplate(path76)
20404
+ );
20405
+ if (routeNodeId) {
20406
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types82.EdgeType.CALLS };
20407
+ }
20408
+ }
20409
+ return {
20410
+ targetNodeId: (0, import_types82.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
20411
+ serviceName: mappedService ?? backendServiceName,
20412
+ edgeType: import_types82.EdgeType.CALLS,
20413
+ ensureInfraNode: {
20414
+ kind: GCP_LB_BACKEND_INFRA_KIND,
20415
+ name: backendServiceName,
20416
+ provider: "gcp-lb"
20417
+ }
20418
+ };
20419
+ };
20420
+ }
20421
+
20422
+ // src/connectors/gcp-lb/index.ts
20423
+ var GcpLbConnector = class {
20424
+ constructor(config = {}) {
20425
+ this.config = config;
20426
+ }
20427
+ config;
20428
+ provider = "gcp-lb";
20429
+ async poll(ctx) {
20430
+ const creds = readGcpLbCredentials(ctx.credentials);
20431
+ const maxLookbackMs = this.config.maxLookbackMs ?? DEFAULT_LOOKBACK_MS3;
20432
+ const sinceIso = boundedSinceIso2(ctx.since, /* @__PURE__ */ new Date(), maxLookbackMs);
20433
+ const entries = await fetchGcpLbRequestLogEntries(creds, sinceIso, this.config.apiUrl);
20434
+ return mapLogEntriesToSignals3(entries);
20435
+ }
20436
+ };
20437
+ function boundedSinceIso2(since, now, maxLookbackMs) {
20438
+ const floor = new Date(now.getTime() - maxLookbackMs);
20439
+ if (!since) return floor.toISOString();
20440
+ const sinceMs = new Date(since).getTime();
20441
+ if (Number.isNaN(sinceMs)) return floor.toISOString();
20442
+ return sinceMs < floor.getTime() ? floor.toISOString() : new Date(sinceMs).toISOString();
20443
+ }
20444
+ function createGcpLbConnector(graph, config = {}) {
20445
+ return {
20446
+ connector: new GcpLbConnector(config),
20447
+ resolveTarget: createGcpLbResolveTarget(graph, config)
20448
+ };
20449
+ }
20450
+
20231
20451
  // src/connectors/render/index.ts
20232
20452
  init_cjs_shims();
20233
- var import_types81 = require("@neat.is/types");
20453
+ var import_types85 = require("@neat.is/types");
20234
20454
 
20235
20455
  // src/connectors/render/types.ts
20236
20456
  init_cjs_shims();
@@ -20308,7 +20528,7 @@ function buildRenderRouteIndex(graph, serviceName) {
20308
20528
  const out = [];
20309
20529
  graph.forEachNode((_id, attrs) => {
20310
20530
  const node = attrs;
20311
- if (node.type !== import_types81.NodeType.RouteNode) return;
20531
+ if (node.type !== import_types85.NodeType.RouteNode) return;
20312
20532
  const route = attrs;
20313
20533
  if (route.service !== serviceName) return;
20314
20534
  out.push({
@@ -20393,7 +20613,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
20393
20613
  function createRenderResolveTarget(config) {
20394
20614
  return (signal) => {
20395
20615
  if (signal.targetKind === ROUTE_TARGET_KIND2) {
20396
- return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types81.EdgeType.CALLS };
20616
+ return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types85.EdgeType.CALLS };
20397
20617
  }
20398
20618
  return null;
20399
20619
  };
@@ -20531,21 +20751,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
20531
20751
 
20532
20752
  // src/connectors/planetscale/resolve.ts
20533
20753
  init_cjs_shims();
20534
- var import_types85 = require("@neat.is/types");
20754
+ var import_types89 = require("@neat.is/types");
20535
20755
  var PLANETSCALE_DATABASE_KIND = "planetscale-database";
20536
20756
  function createPlanetscaleResolveTarget(graph, config) {
20537
20757
  const databaseName = `${config.organization}/${config.database}`;
20538
20758
  return (signal, _ctx) => {
20539
20759
  if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
20540
- const tableId = (0, import_types85.infraId)("sql-table", signal.targetName);
20760
+ const tableId = (0, import_types89.infraId)("sql-table", signal.targetName);
20541
20761
  if (graph.hasNode(tableId)) {
20542
- return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types85.EdgeType.CALLS };
20762
+ return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types89.EdgeType.CALLS };
20543
20763
  }
20544
- const providerId = (0, import_types85.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
20764
+ const providerId = (0, import_types89.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
20545
20765
  return {
20546
20766
  targetNodeId: providerId,
20547
20767
  serviceName: config.serviceName,
20548
- edgeType: import_types85.EdgeType.CALLS,
20768
+ edgeType: import_types89.EdgeType.CALLS,
20549
20769
  ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
20550
20770
  };
20551
20771
  };
@@ -20611,13 +20831,13 @@ function isTransientFailure(err) {
20611
20831
  if (code && INTERNAL_ERROR_CODE.test(code)) return true;
20612
20832
  return false;
20613
20833
  }
20614
- var FIELD_SEP3 = "\0";
20834
+ var FIELD_SEP4 = "\0";
20615
20835
  var EAS_TARGET_KIND = "eas-build";
20616
20836
  function packEasTargetName(identity) {
20617
- return [identity.serviceName, identity.phase].join(FIELD_SEP3);
20837
+ return [identity.serviceName, identity.phase].join(FIELD_SEP4);
20618
20838
  }
20619
20839
  function parseEasTargetName(targetName) {
20620
- const sep = targetName.indexOf(FIELD_SEP3);
20840
+ const sep = targetName.indexOf(FIELD_SEP4);
20621
20841
  if (sep === -1) return null;
20622
20842
  const serviceName = targetName.slice(0, sep);
20623
20843
  const phase = targetName.slice(sep + 1);
@@ -20810,7 +21030,7 @@ function mapBuildsToSignals(builds, serviceName) {
20810
21030
 
20811
21031
  // src/connectors/eas/resolve.ts
20812
21032
  init_cjs_shims();
20813
- var import_types90 = require("@neat.is/types");
21033
+ var import_types94 = require("@neat.is/types");
20814
21034
  var NO_ENV2 = "unknown";
20815
21035
  var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
20816
21036
  var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
@@ -20826,8 +21046,8 @@ function configBasenamesForPhase(phase) {
20826
21046
  function configNodeService(graph, configNodeId) {
20827
21047
  for (const edgeId of graph.inboundEdges(configNodeId)) {
20828
21048
  const edge = graph.getEdgeAttributes(edgeId);
20829
- if (edge.type !== import_types90.EdgeType.CONFIGURED_BY) continue;
20830
- const parsed = (0, import_types90.parseFileId)(edge.source);
21049
+ if (edge.type !== import_types94.EdgeType.CONFIGURED_BY) continue;
21050
+ const parsed = (0, import_types94.parseFileId)(edge.source);
20831
21051
  if (parsed) return parsed.service;
20832
21052
  }
20833
21053
  return null;
@@ -20838,7 +21058,7 @@ function findConfigNode(graph, basenames, serviceName) {
20838
21058
  graph.forEachNode((id, attrs) => {
20839
21059
  if (scoped) return;
20840
21060
  const node = attrs;
20841
- if (node.type !== import_types90.NodeType.ConfigNode) return;
21061
+ if (node.type !== import_types94.NodeType.ConfigNode) return;
20842
21062
  if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
20843
21063
  if (anyMatch === null) anyMatch = id;
20844
21064
  if (configNodeService(graph, id) === serviceName) scoped = id;
@@ -20855,13 +21075,13 @@ function createEasResolveTarget(graph) {
20855
21075
  if (basenames.length > 0) {
20856
21076
  const configNodeId = findConfigNode(graph, basenames, serviceName);
20857
21077
  if (configNodeId) {
20858
- return { targetNodeId: configNodeId, serviceName, edgeType: import_types90.EdgeType.CALLS };
21078
+ return { targetNodeId: configNodeId, serviceName, edgeType: import_types94.EdgeType.CALLS };
20859
21079
  }
20860
21080
  }
20861
21081
  return {
20862
21082
  targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
20863
21083
  serviceName,
20864
- edgeType: import_types90.EdgeType.CALLS
21084
+ edgeType: import_types94.EdgeType.CALLS
20865
21085
  };
20866
21086
  };
20867
21087
  }
@@ -20873,7 +21093,7 @@ function isBuildSince(build, sinceIso) {
20873
21093
  if (Number.isNaN(t) || Number.isNaN(s)) return true;
20874
21094
  return t > s;
20875
21095
  }
20876
- function boundedSinceIso2(since, now, maxLookbackMs) {
21096
+ function boundedSinceIso3(since, now, maxLookbackMs) {
20877
21097
  const floor = new Date(now.getTime() - maxLookbackMs);
20878
21098
  if (!since) return floor.toISOString();
20879
21099
  const sinceMs = new Date(since).getTime();
@@ -20892,7 +21112,7 @@ var EasConnector = class {
20892
21112
  const creds = readEasCredentials(ctx.credentials);
20893
21113
  const serviceName = this.config.serviceName ?? this.config.appId;
20894
21114
  const maxLookbackMs = this.config.maxLookbackMs ?? DEFAULT_MAX_LOOKBACK_MS6;
20895
- const sinceIso = boundedSinceIso2(ctx.since, /* @__PURE__ */ new Date(), maxLookbackMs);
21115
+ const sinceIso = boundedSinceIso3(ctx.since, /* @__PURE__ */ new Date(), maxLookbackMs);
20896
21116
  const builds = await fetchErroredBuilds(creds.token, this.config, this.fetchImpl);
20897
21117
  const fresh = builds.filter((b) => isBuildSince(b, sinceIso));
20898
21118
  const maxLogBytes = this.config.maxLogBytes ?? DEFAULT_MAX_LOG_BYTES;
@@ -21123,6 +21343,40 @@ var PROVIDER_DISPATCH = {
21123
21343
  });
21124
21344
  }
21125
21345
  },
21346
+ "gcp-lb": {
21347
+ provider: "gcp-lb",
21348
+ // Like cloud-run, gcp-lb reads both projectId and accessToken from the
21349
+ // credential; the single-string form maps to the secret (the token), and the
21350
+ // required-fields check below catches a projectId that was never supplied.
21351
+ primaryCredentialKey: "accessToken",
21352
+ requiredCredentialFields: ["projectId", "accessToken"],
21353
+ requiredOptionFields: [],
21354
+ build(graph, options) {
21355
+ return createGcpLbConnector(graph, options);
21356
+ },
21357
+ // POST entries:list with pageSize 1 — the exact surface poll() reads, so the
21358
+ // probe checks the actual `logging.logEntries.list` permission the connector
21359
+ // needs. This is the same Cloud Logging read-verdict cloud-run's validate
21360
+ // uses (a lighter GET on logs.list would instead check `logging.logs.list`,
21361
+ // falsely rejecting a correctly-scoped custom role carrying only
21362
+ // `logging.logEntries.list`). A 2xx means the token can list log entries;
21363
+ // 401/403 means the provider rejected it.
21364
+ validate({ credentials, fetchImpl }) {
21365
+ const projectId = String(credentials.projectId ?? "");
21366
+ return authProbe({
21367
+ provider: "gcp-lb",
21368
+ accountKey: projectId || "validate",
21369
+ url: "https://logging.googleapis.com/v2/entries:list",
21370
+ token: String(credentials.accessToken ?? ""),
21371
+ init: {
21372
+ method: "POST",
21373
+ headers: { "Content-Type": "application/json" },
21374
+ body: JSON.stringify({ resourceNames: [`projects/${projectId}`], pageSize: 1 })
21375
+ },
21376
+ ...fetchImpl ? { fetchImpl } : {}
21377
+ });
21378
+ }
21379
+ },
21126
21380
  render: {
21127
21381
  provider: "render",
21128
21382
  primaryCredentialKey: "token",
@@ -21588,11 +21842,11 @@ function registerRoutes(scope, ctx) {
21588
21842
  const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
21589
21843
  const parsed = [];
21590
21844
  for (const c of candidates) {
21591
- const r = import_types93.DivergenceTypeSchema.safeParse(c);
21845
+ const r = import_types97.DivergenceTypeSchema.safeParse(c);
21592
21846
  if (!r.success) {
21593
21847
  return reply.code(400).send({
21594
21848
  error: `unknown divergence type "${c}"`,
21595
- allowed: import_types93.DivergenceTypeSchema.options
21849
+ allowed: import_types97.DivergenceTypeSchema.options
21596
21850
  });
21597
21851
  }
21598
21852
  parsed.push(r.data);
@@ -21954,7 +22208,7 @@ function registerRoutes(scope, ctx) {
21954
22208
  const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
21955
22209
  let violations = await log.readAll();
21956
22210
  if (req.query.severity) {
21957
- const sev = import_types93.PolicySeveritySchema.safeParse(req.query.severity);
22211
+ const sev = import_types97.PolicySeveritySchema.safeParse(req.query.severity);
21958
22212
  if (!sev.success) {
21959
22213
  return reply.code(400).send({
21960
22214
  error: "invalid severity",
@@ -21993,7 +22247,7 @@ function registerRoutes(scope, ctx) {
21993
22247
  scope.post("/policies/check", async (req, reply) => {
21994
22248
  const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
21995
22249
  if (!proj) return;
21996
- const parsed = import_types93.PoliciesCheckBodySchema.safeParse(req.body ?? {});
22250
+ const parsed = import_types97.PoliciesCheckBodySchema.safeParse(req.body ?? {});
21997
22251
  if (!parsed.success) {
21998
22252
  return reply.code(400).send({
21999
22253
  error: "invalid /policies/check body",
@@ -22342,7 +22596,7 @@ function unroutedErrorsPath(neatHome3) {
22342
22596
  }
22343
22597
 
22344
22598
  // src/daemon.ts
22345
- var import_types94 = require("@neat.is/types");
22599
+ var import_types98 = require("@neat.is/types");
22346
22600
  function daemonJsonPath(scanPath) {
22347
22601
  return import_node_path75.default.join(scanPath, "neat-out", "daemon.json");
22348
22602
  }
@@ -22467,7 +22721,7 @@ function spanBelongsToSingleProject(graph, project, serviceName) {
22467
22721
  if (!serviceName) return true;
22468
22722
  if (serviceNameMatchesProject(serviceName, project)) return true;
22469
22723
  return graph.someNode(
22470
- (_id, attrs) => attrs.type === import_types94.NodeType.ServiceNode && attrs.name === serviceName
22724
+ (_id, attrs) => attrs.type === import_types98.NodeType.ServiceNode && attrs.name === serviceName
22471
22725
  );
22472
22726
  }
22473
22727
  async function bootstrapProject(entry, connectors = [], neatHome3) {