@stacksjs/buddy 0.70.125 → 0.70.126

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.
@@ -84,6 +84,16 @@ export declare function reconcileMailDns(res: MailTenantResult, ip: string, logg
84
84
  * verification records.
85
85
  */
86
86
  export declare function configDnsDomains(sites: Record<string, any>): string[];
87
+ /**
88
+ * Infer a DNS provider from a zone's authoritative nameservers.
89
+ *
90
+ * Provider API probes are intentionally the primary detection mechanism, but
91
+ * some registrars disable record API access per-domain. In that state the
92
+ * provider still owns the zone and should receive the attempted write so the
93
+ * deploy reports the real authorization error instead of incorrectly calling
94
+ * the zone externally managed.
95
+ */
96
+ export declare function dnsProviderNameFromNameservers(nameservers: string[]): 'porkbun' | 'cloudflare' | 'route53' | 'godaddy' | null;
87
97
  export declare function deploy(buddy: CLI): void;
88
98
  /**
89
99
  * Use console.log for clean output without timestamps
@@ -1079,6 +1079,18 @@ export function configDnsDomains(sites) {
1079
1079
  domains.add(site.domain.replace(/^www\./, ""));
1080
1080
  return [...domains];
1081
1081
  }
1082
+ export function dnsProviderNameFromNameservers(nameservers) {
1083
+ const normalized = nameservers.map((name) => name.toLowerCase().replace(/\.$/, ""));
1084
+ if (normalized.some((name) => name.endsWith(".porkbun.com")))
1085
+ return "porkbun";
1086
+ if (normalized.some((name) => name.endsWith(".ns.cloudflare.com")))
1087
+ return "cloudflare";
1088
+ if (normalized.some((name) => /(^|\.)awsdns-\d+\.(?:com|net|org|co\.uk)$/.test(name)))
1089
+ return "route53";
1090
+ if (normalized.some((name) => name.endsWith(".domaincontrol.com")))
1091
+ return "godaddy";
1092
+ return null;
1093
+ }
1082
1094
  async function reconcileConfigDns(sites, logger) {
1083
1095
  const projectDnsConfig = await loadProjectDnsConfig(dnsConfig);
1084
1096
  if (["a", "aaaa", "cname", "mx", "txt"].reduce((total, key) => total + (Array.isArray(projectDnsConfig?.[key]) ? projectDnsConfig[key].length : 0), 0) === 0)
@@ -1121,6 +1133,8 @@ async function reconcileHetznerDns(sites, ip, logger) {
1121
1133
  providerConfigs.push({ provider: "porkbun", apiKey: process.env.PORKBUN_API_KEY, secretKey: process.env.PORKBUN_SECRET_KEY });
1122
1134
  if (process.env.CLOUDFLARE_API_TOKEN)
1123
1135
  providerConfigs.push({ provider: "cloudflare", apiToken: process.env.CLOUDFLARE_API_TOKEN });
1136
+ if (process.env.GODADDY_API_KEY && process.env.GODADDY_API_SECRET)
1137
+ providerConfigs.push({ provider: "godaddy", apiKey: process.env.GODADDY_API_KEY, apiSecret: process.env.GODADDY_API_SECRET, environment: process.env.GODADDY_ENVIRONMENT });
1124
1138
  if (process.env.AWS_ACCESS_KEY_ID || process.env.AWS_PROFILE)
1125
1139
  providerConfigs.push({ provider: "route53" });
1126
1140
  if (providerConfigs.length === 0) {
@@ -1129,7 +1143,7 @@ async function reconcileHetznerDns(sites, ip, logger) {
1129
1143
  logger.info(` Point manually: A ${d} \u2192 ${ip} and A www.${d} \u2192 ${ip}`);
1130
1144
  return;
1131
1145
  }
1132
- const { detectDnsProvider } = await import("@stacksjs/ts-cloud");
1146
+ const { createDnsProvider, detectDnsProvider } = await import("@stacksjs/ts-cloud");
1133
1147
  logger.info("Reconciling DNS records...");
1134
1148
  const resolveA = async (fqdn) => {
1135
1149
  try {
@@ -1138,10 +1152,22 @@ async function reconcileHetznerDns(sites, ip, logger) {
1138
1152
  } catch {
1139
1153
  return [];
1140
1154
  }
1155
+ }, resolveAuthoritativeNameservers = async (domain) => {
1156
+ try {
1157
+ const { resolveNs } = await import("node:dns/promises");
1158
+ return await resolveNs(domain);
1159
+ } catch {
1160
+ return [];
1161
+ }
1141
1162
  };
1142
1163
  for (const domain of domains)
1143
1164
  try {
1144
- const provider = await detectDnsProvider(domain, providerConfigs);
1165
+ let provider = await detectDnsProvider(domain, providerConfigs);
1166
+ if (!provider) {
1167
+ const providerName = dnsProviderNameFromNameservers(await resolveAuthoritativeNameservers(domain)), providerConfig = providerConfigs.find((config) => config.provider === providerName);
1168
+ if (providerConfig)
1169
+ provider = createDnsProvider(providerConfig);
1170
+ }
1145
1171
  if (!provider) {
1146
1172
  for (const sub of ["", "www"]) {
1147
1173
  const fqdn = sub ? `${sub}.${domain}` : domain, current = await resolveA(fqdn);
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/buddy",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.125",
5
+ "version": "0.70.126",
6
6
  "description": "Meet Buddy. The Stacks runtime.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -92,51 +92,51 @@
92
92
  "prepublishOnly": "bun run build"
93
93
  },
94
94
  "dependencies": {
95
- "@stacksjs/actions": "^0.70.125",
96
- "@stacksjs/ai": "^0.70.125",
97
- "@stacksjs/alias": "^0.70.125",
98
- "@stacksjs/arrays": "^0.70.125",
99
- "@stacksjs/auth": "^0.70.125",
100
- "@stacksjs/build": "^0.70.125",
101
- "@stacksjs/cache": "^0.70.125",
102
- "@stacksjs/cli": "^0.70.125",
95
+ "@stacksjs/actions": "^0.70.126",
96
+ "@stacksjs/ai": "^0.70.126",
97
+ "@stacksjs/alias": "^0.70.126",
98
+ "@stacksjs/arrays": "^0.70.126",
99
+ "@stacksjs/auth": "^0.70.126",
100
+ "@stacksjs/build": "^0.70.126",
101
+ "@stacksjs/cache": "^0.70.126",
102
+ "@stacksjs/cli": "^0.70.126",
103
103
  "@stacksjs/clapp": "^0.2.10",
104
- "@stacksjs/cloud": "^0.70.125",
105
- "@stacksjs/collections": "^0.70.125",
106
- "@stacksjs/config": "^0.70.125",
107
- "@stacksjs/database": "^0.70.125",
108
- "@stacksjs/desktop": "^0.70.125",
109
- "@stacksjs/dns": "^0.70.125",
110
- "@stacksjs/email": "^0.70.125",
111
- "@stacksjs/enums": "^0.70.125",
112
- "@stacksjs/error-handling": "^0.70.125",
113
- "@stacksjs/events": "^0.70.125",
114
- "@stacksjs/git": "^0.70.125",
104
+ "@stacksjs/cloud": "^0.70.126",
105
+ "@stacksjs/collections": "^0.70.126",
106
+ "@stacksjs/config": "^0.70.126",
107
+ "@stacksjs/database": "^0.70.126",
108
+ "@stacksjs/desktop": "^0.70.126",
109
+ "@stacksjs/dns": "^0.70.126",
110
+ "@stacksjs/email": "^0.70.126",
111
+ "@stacksjs/enums": "^0.70.126",
112
+ "@stacksjs/error-handling": "^0.70.126",
113
+ "@stacksjs/events": "^0.70.126",
114
+ "@stacksjs/git": "^0.70.126",
115
115
  "@stacksjs/gitit": "^0.2.5",
116
- "@stacksjs/health": "^0.70.125",
116
+ "@stacksjs/health": "^0.70.126",
117
117
  "@stacksjs/dnsx": "^0.2.3",
118
118
  "@stacksjs/httx": "^0.1.10",
119
- "@stacksjs/lint": "^0.70.125",
120
- "@stacksjs/logging": "^0.70.125",
121
- "@stacksjs/notifications": "^0.70.125",
122
- "@stacksjs/objects": "^0.70.125",
123
- "@stacksjs/orm": "^0.70.125",
124
- "@stacksjs/path": "^0.70.125",
125
- "@stacksjs/payments": "^0.70.125",
126
- "@stacksjs/realtime": "^0.70.125",
127
- "@stacksjs/router": "^0.70.125",
119
+ "@stacksjs/lint": "^0.70.126",
120
+ "@stacksjs/logging": "^0.70.126",
121
+ "@stacksjs/notifications": "^0.70.126",
122
+ "@stacksjs/objects": "^0.70.126",
123
+ "@stacksjs/orm": "^0.70.126",
124
+ "@stacksjs/path": "^0.70.126",
125
+ "@stacksjs/payments": "^0.70.126",
126
+ "@stacksjs/realtime": "^0.70.126",
127
+ "@stacksjs/router": "^0.70.126",
128
128
  "@stacksjs/rpx": "^0.11.29",
129
- "@stacksjs/search-engine": "^0.70.125",
130
- "@stacksjs/security": "^0.70.125",
131
- "@stacksjs/server": "^0.70.125",
132
- "@stacksjs/storage": "^0.70.125",
133
- "@stacksjs/strings": "^0.70.125",
134
- "@stacksjs/testing": "^0.70.125",
135
- "@stacksjs/tunnel": "^0.70.125",
136
- "@stacksjs/types": "^0.70.125",
137
- "@stacksjs/ui": "^0.70.125",
138
- "@stacksjs/utils": "^0.70.125",
139
- "@stacksjs/validation": "^0.70.125",
129
+ "@stacksjs/search-engine": "^0.70.126",
130
+ "@stacksjs/security": "^0.70.126",
131
+ "@stacksjs/server": "^0.70.126",
132
+ "@stacksjs/storage": "^0.70.126",
133
+ "@stacksjs/strings": "^0.70.126",
134
+ "@stacksjs/testing": "^0.70.126",
135
+ "@stacksjs/tunnel": "^0.70.126",
136
+ "@stacksjs/types": "^0.70.126",
137
+ "@stacksjs/ui": "^0.70.126",
138
+ "@stacksjs/utils": "^0.70.126",
139
+ "@stacksjs/validation": "^0.70.126",
140
140
  "@stacksjs/ts-cloud": "^0.7.36"
141
141
  },
142
142
  "devDependencies": {