supbuddy 3.0.9 → 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.
- package/dist/daemon/worker.cjs +53 -14
- package/package.json +1 -1
package/dist/daemon/worker.cjs
CHANGED
|
@@ -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
|
|
37782
|
-
|
|
37783
|
-
|
|
37784
|
-
|
|
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: {
|
|
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
|
};
|
|
@@ -48250,7 +48271,7 @@ port ${port}
|
|
|
48250
48271
|
commands.push(`cp "${tmpPath}" "${filePath}"`);
|
|
48251
48272
|
}
|
|
48252
48273
|
const writeChain = commands.join(" && ");
|
|
48253
|
-
const flush = "{ dscacheutil -flushcache; killall -HUP mDNSResponder 2>/dev/null; true; }";
|
|
48274
|
+
const flush = "{ dscacheutil -flushcache; launchctl kickstart -k system/com.apple.mDNSResponder.reloaded 2>/dev/null || launchctl kickstart -k system/com.apple.mDNSResponder 2>/dev/null || killall -HUP mDNSResponder 2>/dev/null; true; }";
|
|
48254
48275
|
return { command: `${writeChain} && ${flush}`, tmpFiles };
|
|
48255
48276
|
}
|
|
48256
48277
|
async function buildMacOsCleanupCommand() {
|
|
@@ -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" }));
|
|
@@ -50019,7 +50058,7 @@ async function checkProxyReachabilityAndSurface() {
|
|
|
50019
50058
|
const hintMessage = {
|
|
50020
50059
|
mdns_hijack: `Browser DNS for ${result.domain} returns ${result.resolved.join(", ")} (your own LAN IP) but Caddy isn't reachable on port ${result.port}. This usually means LAN sharing is publishing the name via Bonjour and pf rules need a re-apply — toggle the proxy off/on, or disable LAN sharing.`,
|
|
50021
50060
|
foreign_owner: `Another device on your LAN is responding for ${result.domain} (${result.resolved.join(", ")}) — Bonjour/mDNS race for the .local namespace. Switch this project's TLD to .test in Settings, or take the other device offline.`,
|
|
50022
|
-
no_resolution: `The OS resolver couldn't resolve ${result.domain}.
|
|
50061
|
+
no_resolution: `The OS resolver couldn't resolve ${result.domain}. The resolver files and DNS server on :${store2.dnsState.port} may be fine — on macOS Sonoma+ the OS often just hasn't loaded /etc/resolver yet. Click RETRY (or restart the proxy) to rewrite the resolver files and reload the OS DNS cache. If it persists, run get_health → dns.resolver to check for missing files.`,
|
|
50023
50062
|
resolved_but_unreachable: `${result.domain} resolves to ${result.resolved.join(", ")} but TCP connect to port ${result.port} fails. Likely a port-forwarding rule is missing for that IP — toggle the proxy off/on.`
|
|
50024
50063
|
};
|
|
50025
50064
|
const effectiveHint = resolveReachabilityHint2(result.hint, store2.settings.lanSharing);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supbuddy",
|
|
3
|
-
"version": "3.0.
|
|
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",
|