@neat.is/core 0.10.1-dev.20260927 → 0.10.1

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseOtlpRequest
3
- } from "./chunk-GDGUY4T6.js";
3
+ } from "./chunk-M7CGATVC.js";
4
4
 
5
5
  // src/otel-grpc.ts
6
6
  import { fileURLToPath } from "url";
@@ -138,4 +138,4 @@ export {
138
138
  reshapeGrpcRequest,
139
139
  startOtelGrpcReceiver
140
140
  };
141
- //# sourceMappingURL=chunk-ERE47MCR.js.map
141
+ //# sourceMappingURL=chunk-5SJHA5ZH.js.map
@@ -33,13 +33,13 @@ import {
33
33
  startStalenessLoop,
34
34
  touchLastSeen,
35
35
  writeAtomically
36
- } from "./chunk-J3VVEB45.js";
36
+ } from "./chunk-E3YFFIHE.js";
37
37
  import {
38
38
  assertBindAuthority,
39
39
  buildOtelReceiver,
40
40
  listenSteppingOtlp,
41
41
  readAuthEnv
42
- } from "./chunk-GDGUY4T6.js";
42
+ } from "./chunk-M7CGATVC.js";
43
43
 
44
44
  // src/daemon.ts
45
45
  import {
@@ -116,6 +116,7 @@ function decodeRailwayTargetRef(ref) {
116
116
  // src/connectors/hosted.ts
117
117
  var CREDENTIAL_REFRESH_SKEW_MS = 6e4;
118
118
  var CP_REQUEST_TIMEOUT_MS = 1e4;
119
+ var DEFAULT_RELIST_INTERVAL_MS = 6e4;
119
120
  async function cpGet(path5, deps) {
120
121
  const f = deps.fetchImpl ?? fetch;
121
122
  const res = await f(`${deps.cpUrl.replace(/\/+$/, "")}${path5}`, {
@@ -286,67 +287,111 @@ function createHostedCredentialSource(provider, deps) {
286
287
  return record;
287
288
  };
288
289
  }
289
- async function startHostedConnectors(input) {
290
+ function connectionSignature(c) {
291
+ return `${c.projectRef ?? ""}|${c.needsProjectSelection ? 1 : 0}`;
292
+ }
293
+ function startConnectionLoops(c, input, startLoop) {
290
294
  const { deps, graph, projectDir, project, errorsPath, onSkip } = input;
291
- const startLoop = input.startLoop ?? startConnectorPollLoop;
295
+ const stops = [];
296
+ const credentialSource = createHostedCredentialSource(c.provider, deps);
297
+ for (const name of HOSTED_CONNECTORS_FOR[c.provider] ?? [c.provider]) {
298
+ const dispatch = PROVIDER_DISPATCH[name];
299
+ if (!dispatch) {
300
+ onSkip?.(name, "no pull connector for this provider");
301
+ continue;
302
+ }
303
+ if (c.needsProjectSelection || !c.projectRef) {
304
+ onSkip?.(name, "no project selected yet \u2014 not pullable");
305
+ continue;
306
+ }
307
+ const options = hostedOptions(name, c, project, input.firebaseServiceMap);
308
+ if (!options) {
309
+ onSkip?.(name, "no hosted option mapping for this provider");
310
+ continue;
311
+ }
312
+ let built;
313
+ try {
314
+ built = dispatch.build(graph, options);
315
+ } catch (err) {
316
+ onSkip?.(name, err.message);
317
+ continue;
318
+ }
319
+ stops.push(
320
+ startLoop(
321
+ built.connector,
322
+ { projectDir, project, credentials: {}, ...errorsPath ? { errorsPath } : {} },
323
+ graph,
324
+ built.resolveTarget,
325
+ {
326
+ connectorId: `hosted:${name}`,
327
+ // The credential is fetched by the CONNECTION's provider (`gcp`), not the connector's name.
328
+ refreshCredentials: credentialSource
329
+ }
330
+ )
331
+ );
332
+ }
333
+ return () => {
334
+ for (const stop of stops) stop();
335
+ };
336
+ }
337
+ async function runHostedConnectorsPass(input, startLoop, running) {
338
+ const { deps, onSkip } = input;
292
339
  let connections;
293
340
  try {
294
341
  connections = await cpGet(`/internal/projects/${deps.projectId}/connections`, deps);
295
342
  } catch (err) {
296
343
  onSkip?.("(all)", `control plane connection list unreadable \u2014 ${err.message}`);
297
- return () => {
298
- };
344
+ return;
299
345
  }
300
- if (!Array.isArray(connections)) return () => {
301
- };
302
- const stops = [];
346
+ if (!Array.isArray(connections)) return;
303
347
  const lookupPush = input.pushDispatch ?? getPushProviderDispatch;
348
+ const seen = /* @__PURE__ */ new Set();
304
349
  for (const c of connections) {
350
+ seen.add(c.provider);
351
+ const signature = connectionSignature(c);
352
+ const existing = running.get(c.provider);
353
+ if (existing && existing.signature === signature) continue;
354
+ if (existing) existing.stop();
305
355
  const push = lookupPush(c.provider);
306
356
  if (push) {
307
357
  await provisionHostedPushProvider(c, push, input);
358
+ running.set(c.provider, { signature, stop: () => {
359
+ } });
308
360
  continue;
309
361
  }
310
- const credentialSource = createHostedCredentialSource(c.provider, deps);
311
- for (const name of HOSTED_CONNECTORS_FOR[c.provider] ?? [c.provider]) {
312
- const dispatch = PROVIDER_DISPATCH[name];
313
- if (!dispatch) {
314
- onSkip?.(name, "no pull connector for this provider");
315
- continue;
316
- }
317
- if (c.needsProjectSelection || !c.projectRef) {
318
- onSkip?.(name, "no project selected yet \u2014 not pullable");
319
- continue;
320
- }
321
- const options = hostedOptions(name, c, project, input.firebaseServiceMap);
322
- if (!options) {
323
- onSkip?.(name, "no hosted option mapping for this provider");
324
- continue;
325
- }
326
- let built;
327
- try {
328
- built = dispatch.build(graph, options);
329
- } catch (err) {
330
- onSkip?.(name, err.message);
331
- continue;
332
- }
333
- stops.push(
334
- startLoop(
335
- built.connector,
336
- { projectDir, project, credentials: {}, ...errorsPath ? { errorsPath } : {} },
337
- graph,
338
- built.resolveTarget,
339
- {
340
- connectorId: `hosted:${name}`,
341
- // The credential is fetched by the CONNECTION's provider (`gcp`), not the connector's name.
342
- refreshCredentials: credentialSource
343
- }
344
- )
345
- );
346
- }
362
+ running.set(c.provider, { signature, stop: startConnectionLoops(c, input, startLoop) });
363
+ }
364
+ for (const [provider, rc] of running) {
365
+ if (seen.has(provider)) continue;
366
+ rc.stop();
367
+ running.delete(provider);
347
368
  }
369
+ }
370
+ async function startHostedConnectors(input) {
371
+ const startLoop = input.startLoop ?? startConnectorPollLoop;
372
+ const intervalMs = input.intervalMs ?? DEFAULT_RELIST_INTERVAL_MS;
373
+ const running = /* @__PURE__ */ new Map();
374
+ let stopped = false;
375
+ let inPass = false;
376
+ const tick = async () => {
377
+ if (stopped || inPass) return;
378
+ inPass = true;
379
+ try {
380
+ await runHostedConnectorsPass(input, startLoop, running);
381
+ } finally {
382
+ inPass = false;
383
+ }
384
+ };
385
+ await tick();
386
+ const timer = setInterval(() => {
387
+ void tick();
388
+ }, intervalMs);
389
+ if (typeof timer.unref === "function") timer.unref();
348
390
  return () => {
349
- for (const stop of stops) stop();
391
+ stopped = true;
392
+ clearInterval(timer);
393
+ for (const rc of running.values()) rc.stop();
394
+ running.clear();
350
395
  };
351
396
  }
352
397
  async function maybeStartHostedConnectors(input) {
@@ -370,7 +415,8 @@ async function maybeStartHostedConnectors(input) {
370
415
  project: input.project,
371
416
  ...parseFirebaseServiceMap(env.NEAT_FIREBASE_SERVICE_MAP) ? { firebaseServiceMap: parseFirebaseServiceMap(env.NEAT_FIREBASE_SERVICE_MAP) } : {},
372
417
  ...input.errorsPath ? { errorsPath: input.errorsPath } : {},
373
- ...input.onSkip ? { onSkip: input.onSkip } : {}
418
+ ...input.onSkip ? { onSkip: input.onSkip } : {},
419
+ ...input.intervalMs !== void 0 ? { intervalMs: input.intervalMs } : {}
374
420
  });
375
421
  }
376
422
 
@@ -1900,4 +1946,4 @@ export {
1900
1946
  resolveHost,
1901
1947
  startDaemon
1902
1948
  };
1903
- //# sourceMappingURL=chunk-EJPNEEJA.js.map
1949
+ //# sourceMappingURL=chunk-AWIK6T3G.js.map