@neat.is/core 0.9.17 → 0.9.18-dev.20260918

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
@@ -19161,7 +19161,8 @@ function startConnectorPollLoop(connector, ctx, graph, resolveTarget, options =
19161
19161
  void (async () => {
19162
19162
  const tickStartedAt = (/* @__PURE__ */ new Date()).toISOString();
19163
19163
  try {
19164
- const result = await runConnectorPoll(connector, { ...ctx, since }, graph, resolveTarget);
19164
+ const credentials = options.refreshCredentials ? await options.refreshCredentials() : ctx.credentials;
19165
+ const result = await runConnectorPoll(connector, { ...ctx, credentials, since }, graph, resolveTarget);
19165
19166
  since = tickStartedAt;
19166
19167
  if (connectorId) {
19167
19168
  recordConnectorPoll(connectorId, {
@@ -23402,6 +23403,122 @@ async function reconcileFrontierSurfaces(graph, errorsPath) {
23402
23403
  stageHangSurfaces(graph, incidents);
23403
23404
  }
23404
23405
 
23406
+ // src/connectors/hosted.ts
23407
+ init_cjs_shims();
23408
+ var CREDENTIAL_REFRESH_SKEW_MS = 6e4;
23409
+ var CP_REQUEST_TIMEOUT_MS = 1e4;
23410
+ async function cpGet(path78, deps) {
23411
+ const f = deps.fetchImpl ?? fetch;
23412
+ const res = await f(`${deps.cpUrl.replace(/\/+$/, "")}${path78}`, {
23413
+ headers: { authorization: `Bearer ${deps.daemonToken}`, accept: "application/json" },
23414
+ signal: AbortSignal.timeout(CP_REQUEST_TIMEOUT_MS)
23415
+ });
23416
+ if (!res.ok) throw new Error(`control plane ${path78} \u2192 HTTP ${res.status}`);
23417
+ return await res.json();
23418
+ }
23419
+ function credentialRecord(provider, cred) {
23420
+ switch (provider) {
23421
+ case "supabase":
23422
+ return { managementToken: cred.accessToken };
23423
+ default:
23424
+ return { token: cred.accessToken };
23425
+ }
23426
+ }
23427
+ function hostedOptions(provider, summary, serviceName) {
23428
+ switch (provider) {
23429
+ case "supabase": {
23430
+ const ref = summary.projectRef;
23431
+ if (!ref) return null;
23432
+ return { apiProjectRef: ref, nodeRef: `${ref}.supabase.co`, serviceName };
23433
+ }
23434
+ default:
23435
+ return null;
23436
+ }
23437
+ }
23438
+ function createHostedCredentialSource(provider, deps) {
23439
+ let cached = null;
23440
+ return async () => {
23441
+ if (cached && cached.expiresAtMs - CREDENTIAL_REFRESH_SKEW_MS > Date.now()) return cached.record;
23442
+ const cred = await cpGet(
23443
+ `/internal/projects/${deps.projectId}/connections/${provider}/credential`,
23444
+ deps
23445
+ );
23446
+ const record = credentialRecord(provider, cred);
23447
+ const parsed = cred.expiresAt ? Date.parse(cred.expiresAt) : Number.NaN;
23448
+ cached = { record, expiresAtMs: Number.isFinite(parsed) ? parsed : Number.POSITIVE_INFINITY };
23449
+ return record;
23450
+ };
23451
+ }
23452
+ async function startHostedConnectors(input) {
23453
+ const { deps, graph, projectDir, project, errorsPath, onSkip } = input;
23454
+ const startLoop = input.startLoop ?? startConnectorPollLoop;
23455
+ let connections;
23456
+ try {
23457
+ connections = await cpGet(`/internal/projects/${deps.projectId}/connections`, deps);
23458
+ } catch (err) {
23459
+ onSkip?.("(all)", `control plane connection list unreadable \u2014 ${err.message}`);
23460
+ return () => {
23461
+ };
23462
+ }
23463
+ if (!Array.isArray(connections)) return () => {
23464
+ };
23465
+ const stops = [];
23466
+ for (const c of connections) {
23467
+ const dispatch = PROVIDER_DISPATCH[c.provider];
23468
+ if (!dispatch) {
23469
+ onSkip?.(c.provider, "no pull connector for this provider");
23470
+ continue;
23471
+ }
23472
+ if (c.needsProjectSelection || !c.projectRef) {
23473
+ onSkip?.(c.provider, "no project selected yet \u2014 not pullable");
23474
+ continue;
23475
+ }
23476
+ const options = hostedOptions(c.provider, c, project);
23477
+ if (!options) {
23478
+ onSkip?.(c.provider, "no hosted option mapping for this provider");
23479
+ continue;
23480
+ }
23481
+ let built;
23482
+ try {
23483
+ built = dispatch.build(graph, options);
23484
+ } catch (err) {
23485
+ onSkip?.(c.provider, err.message);
23486
+ continue;
23487
+ }
23488
+ stops.push(
23489
+ startLoop(
23490
+ built.connector,
23491
+ { projectDir, project, credentials: {}, ...errorsPath ? { errorsPath } : {} },
23492
+ graph,
23493
+ built.resolveTarget,
23494
+ {
23495
+ connectorId: `hosted:${c.provider}`,
23496
+ refreshCredentials: createHostedCredentialSource(c.provider, deps)
23497
+ }
23498
+ )
23499
+ );
23500
+ }
23501
+ return () => {
23502
+ for (const stop of stops) stop();
23503
+ };
23504
+ }
23505
+ async function maybeStartHostedConnectors(input) {
23506
+ const env = input.env ?? process.env;
23507
+ const cpUrl = env.NEAT_CP_URL;
23508
+ const projectId = env.NEAT_CP_PROJECT_ID;
23509
+ const daemonToken = env.NEAT_AUTH_TOKEN;
23510
+ if (!cpUrl || !projectId || !daemonToken) return () => {
23511
+ };
23512
+ return startHostedConnectors({
23513
+ deps: { cpUrl, projectId, daemonToken, ...input.fetchImpl ? { fetchImpl: input.fetchImpl } : {} },
23514
+ graph: input.graph,
23515
+ projectDir: input.projectDir,
23516
+ project: input.project,
23517
+ ...input.errorsPath ? { errorsPath: input.errorsPath } : {},
23518
+ ...input.onSkip ? { onSkip: input.onSkip } : {}
23519
+ });
23520
+ }
23521
+
23405
23522
  // src/connectors/kubernetes/index.ts
23406
23523
  init_cjs_shims();
23407
23524
 
@@ -23964,6 +24081,10 @@ function teardownSlot(slot) {
23964
24081
  slot.stopConnectors();
23965
24082
  } catch {
23966
24083
  }
24084
+ try {
24085
+ slot.stopHostedConnectors();
24086
+ } catch {
24087
+ }
23967
24088
  try {
23968
24089
  slot.stopK8sSubstrate();
23969
24090
  } catch {
@@ -24052,6 +24173,8 @@ async function bootstrapProject(entry, connectors = [], neatHome3) {
24052
24173
  },
24053
24174
  stopConnectors: () => {
24054
24175
  },
24176
+ stopHostedConnectors: () => {
24177
+ },
24055
24178
  stopK8sSubstrate: () => {
24056
24179
  },
24057
24180
  detachEvents: () => {
@@ -24090,6 +24213,13 @@ async function bootstrapProject(entry, connectors = [], neatHome3) {
24090
24213
  `neatd: connector "${skipped.id}" (${skipped.provider}) skipped for project "${entry.name}" \u2014 ${reason}`
24091
24214
  )
24092
24215
  });
24216
+ const stopHostedConnectors = await maybeStartHostedConnectors({
24217
+ project: entry.name,
24218
+ graph,
24219
+ projectDir: entry.path,
24220
+ errorsPath: paths.errorsPath,
24221
+ onSkip: (provider, reason) => console.warn(`neatd: hosted connector "${provider}" skipped for project "${entry.name}" \u2014 ${reason}`)
24222
+ });
24093
24223
  const stopK8sSubstrate = await startK8sSubstratePolling({
24094
24224
  project: entry.name,
24095
24225
  graph,
@@ -24108,6 +24238,7 @@ async function bootstrapProject(entry, connectors = [], neatHome3) {
24108
24238
  stopPersist,
24109
24239
  stopStaleness,
24110
24240
  stopConnectors,
24241
+ stopHostedConnectors,
24111
24242
  stopK8sSubstrate,
24112
24243
  detachEvents,
24113
24244
  status: "active"