supbuddy 3.0.10 → 3.0.11

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.
@@ -37777,11 +37777,14 @@ function projectsNeedingVmMigration(projects) {
37777
37777
  return projects.filter((p) => p.isolation === "vm");
37778
37778
  }
37779
37779
  const ALL_SCOPE_KEYS = Object.keys(McpScopesSchema.shape);
37780
- function dnsResolverRepairNeeded(resolver) {
37781
- if (resolver.in_sync !== false) return false;
37782
- const hasMissing = Array.isArray(resolver.missing) && resolver.missing.length > 0;
37783
- const hasExtra = Array.isArray(resolver.extra) && resolver.extra.length > 0;
37784
- return hasMissing || hasExtra;
37780
+ function dnsResolverRepairNeeded(resolver, os2) {
37781
+ if (resolver.in_sync === false) {
37782
+ const hasMissing = Array.isArray(resolver.missing) && resolver.missing.length > 0;
37783
+ const hasExtra = Array.isArray(resolver.extra) && resolver.extra.length > 0;
37784
+ if (hasMissing || hasExtra) return true;
37785
+ }
37786
+ if (resolver.in_sync === true && os2?.serverUp && os2.loaded === false) return true;
37787
+ return false;
37785
37788
  }
37786
37789
  const readTools = {
37787
37790
  list_pending_vm_migrations: async () => {
@@ -37810,9 +37813,9 @@ const readTools = {
37810
37813
  },
37811
37814
  get_settings: async () => useStore.getState().settings,
37812
37815
  get_health: async () => {
37813
- const { auditResolverState: auditResolverState2, probeLocalDnsServer: probeLocalDnsServer2, probeProxyReachability: probeProxyReachability2 } = await __vitePreload(async () => {
37814
- const { auditResolverState: auditResolverState3, probeLocalDnsServer: probeLocalDnsServer3, probeProxyReachability: probeProxyReachability3 } = await Promise.resolve().then(() => dnsPlatform);
37815
- return { auditResolverState: auditResolverState3, probeLocalDnsServer: probeLocalDnsServer3, probeProxyReachability: probeProxyReachability3 };
37816
+ const { auditResolverState: auditResolverState2, probeLocalDnsServer: probeLocalDnsServer2, probeProxyReachability: probeProxyReachability2, probeOsResolverLoaded: probeOsResolverLoaded2 } = await __vitePreload(async () => {
37817
+ const { auditResolverState: auditResolverState3, probeLocalDnsServer: probeLocalDnsServer3, probeProxyReachability: probeProxyReachability3, probeOsResolverLoaded: probeOsResolverLoaded3 } = await Promise.resolve().then(() => dnsPlatform);
37818
+ return { auditResolverState: auditResolverState3, probeLocalDnsServer: probeLocalDnsServer3, probeProxyReachability: probeProxyReachability3, probeOsResolverLoaded: probeOsResolverLoaded3 };
37816
37819
  }, false ? __VITE_PRELOAD__ : void 0);
37817
37820
  const { getLanInterfaces: getLanInterfaces2 } = await __vitePreload(async () => {
37818
37821
  const { getLanInterfaces: getLanInterfaces3 } = await Promise.resolve().then(() => mdnsResponder);
@@ -37823,7 +37826,7 @@ const readTools = {
37823
37826
  const ownIps = getLanInterfaces2().map((i2) => i2.address);
37824
37827
  const liveness = await probeProxyLiveness();
37825
37828
  const proxyStatus = deriveReportedStatus(s.proxyState.status, liveness, { restartInFlight: isCaddyRestartInFlight() });
37826
- const [resolver, probe, reachability] = await Promise.all([
37829
+ const [resolver, probe, reachability, osResolver] = await Promise.all([
37827
37830
  auditResolverState2().catch((e) => ({ in_sync: null, missing: [], extra: [], expected: [], error: e.message })),
37828
37831
  s.dnsState.status === "running" ? probeLocalDnsServer2(dnsPort).catch((e) => ({ ok: false, error: e.message })) : Promise.resolve({ ok: false, error: `dns server not running (status=${s.dnsState.status})` }),
37829
37832
  // Gate the reachability probe on a LIVE liveness check, not the tracked status —
@@ -37833,9 +37836,17 @@ const readTools = {
37833
37836
  resolved: [],
37834
37837
  reachable: [],
37835
37838
  error: e.message
37836
- })) : Promise.resolve({ ok: false, resolved: [], reachable: [], error: `caddy not alive (status=${proxyStatus})` })
37839
+ })) : Promise.resolve({ ok: false, resolved: [], reachable: [], error: `caddy not alive (status=${proxyStatus})` }),
37840
+ // Did the OS actually LOAD /etc/resolver? The file audit above only checks
37841
+ // presence on disk — on Sonoma+ the files can be correct yet unloaded, so a
37842
+ // managed domain won't resolve while `in_sync` reports healthy. getaddrinfo
37843
+ // is the direct test of the loaded state.
37844
+ probeOsResolverLoaded2().catch((e) => ({ loaded: null, error: e.message }))
37837
37845
  ]);
37838
- const resolverRepairNeeded = dnsResolverRepairNeeded(resolver);
37846
+ const resolverRepairNeeded = dnsResolverRepairNeeded(resolver, {
37847
+ loaded: osResolver.loaded,
37848
+ serverUp: probe.ok === true
37849
+ });
37839
37850
  return {
37840
37851
  worker: { running: true, uptime_ms: process.uptime() * 1e3 },
37841
37852
  mcp_server: s.mcpServerState,
@@ -37847,7 +37858,17 @@ const readTools = {
37847
37858
  },
37848
37859
  dns: {
37849
37860
  server: { ...s.dnsState, probe },
37850
- resolver: { ...resolver, repairNeeded: resolverRepairNeeded },
37861
+ resolver: {
37862
+ ...resolver,
37863
+ repairNeeded: resolverRepairNeeded,
37864
+ // Whether the OS actually loaded the resolver files (getaddrinfo of a
37865
+ // managed domain). Distinct from `in_sync` (files on disk): on Sonoma+
37866
+ // `in_sync` can be true while `os_loaded` is false — a privileged reload
37867
+ // (restart_proxy) heals it.
37868
+ os_loaded: osResolver.loaded,
37869
+ ...osResolver.domain ? { os_probe_domain: osResolver.domain } : {},
37870
+ ...osResolver.error ? { os_probe_error: osResolver.error } : {}
37871
+ },
37851
37872
  reachability
37852
37873
  }
37853
37874
  };
@@ -48460,6 +48481,23 @@ async function probeLocalDnsServer(port, timeoutMs = 1e3) {
48460
48481
  });
48461
48482
  });
48462
48483
  }
48484
+ async function probeOsResolverLoaded(timeoutMs = 1500) {
48485
+ const store2 = useStore.getState();
48486
+ const target = store2.mappings.find((m) => m.enabled)?.domain;
48487
+ if (!target) return { loaded: null };
48488
+ try {
48489
+ const addrs = await Promise.race([
48490
+ dns$2.lookup(target, { all: true }),
48491
+ new Promise(
48492
+ (_, reject) => setTimeout(() => reject(Object.assign(new Error("getaddrinfo timeout"), { code: "ETIMEDOUT" })), timeoutMs)
48493
+ )
48494
+ ]);
48495
+ return { loaded: Array.isArray(addrs) && addrs.length > 0, domain: target };
48496
+ } catch (err) {
48497
+ const e = err;
48498
+ return { loaded: false, domain: target, error: e.code || e.message };
48499
+ }
48500
+ }
48463
48501
  function resolveReachabilityHint(rawHint, lanSharing) {
48464
48502
  if (rawHint === "mdns_hijack" && !lanSharing) return "resolved_but_unreachable";
48465
48503
  return rawHint;
@@ -48572,6 +48610,7 @@ const dnsPlatform = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
48572
48610
  buildPlatformDnsCommand,
48573
48611
  getManagedDomainSuffixes,
48574
48612
  probeLocalDnsServer,
48613
+ probeOsResolverLoaded,
48575
48614
  probeProxyReachability,
48576
48615
  resolveReachabilityHint
48577
48616
  }, Symbol.toStringTag, { value: "Module" }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supbuddy",
3
- "version": "3.0.10",
3
+ "version": "3.0.11",
4
4
  "description": "Run multiple Supabase projects at once on custom local domains with HTTPS. A headless CLI and daemon (proxy, DNS, Supabase/Compose lifecycle, MCP) for macOS and Linux.",
5
5
  "keywords": [
6
6
  "supabase",