@geekmidas/cli 10.0.0-alpha.88 → 10.0.0-alpha.89
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/GoDaddyProvider--36rw8cP.mjs +387 -0
- package/dist/GoDaddyProvider--36rw8cP.mjs.map +1 -0
- package/dist/GoDaddyProvider-DnRor066.cjs +387 -0
- package/dist/GoDaddyProvider-DnRor066.cjs.map +1 -0
- package/dist/{HostingerProvider-CVc3rLPB.mjs → HostingerProvider-BI6J7oJr.mjs} +2 -2
- package/dist/{HostingerProvider-CVc3rLPB.mjs.map → HostingerProvider-BI6J7oJr.mjs.map} +1 -1
- package/dist/{HostingerProvider-BCB1QJj1.cjs → HostingerProvider-CyTpG_jy.cjs} +2 -2
- package/dist/{HostingerProvider-BCB1QJj1.cjs.map → HostingerProvider-CyTpG_jy.cjs.map} +1 -1
- package/dist/{LegacyStateStore-CWG_HVC0.cjs → LegacyStateStore-BaBoYl59.cjs} +2 -2
- package/dist/{LegacyStateStore-CWG_HVC0.cjs.map → LegacyStateStore-BaBoYl59.cjs.map} +1 -1
- package/dist/{LegacyStateStore-B0R4LlX_.mjs → LegacyStateStore-CO7bzJCU.mjs} +2 -2
- package/dist/{LegacyStateStore-B0R4LlX_.mjs.map → LegacyStateStore-CO7bzJCU.mjs.map} +1 -1
- package/dist/{LocalStateStore-CLwa2DpK.cjs → LocalStateStore-CUWh2BWU.cjs} +2 -2
- package/dist/{LocalStateStore-CLwa2DpK.cjs.map → LocalStateStore-CUWh2BWU.cjs.map} +1 -1
- package/dist/{LocalStateStore-Q4vXg2ua.mjs → LocalStateStore-C_hYDv6I.mjs} +2 -2
- package/dist/{LocalStateStore-Q4vXg2ua.mjs.map → LocalStateStore-C_hYDv6I.mjs.map} +1 -1
- package/dist/{S3StateStore-Cea9_5gF.cjs → S3StateStore-O8EYfjfG.cjs} +2 -2
- package/dist/{S3StateStore-Cea9_5gF.cjs.map → S3StateStore-O8EYfjfG.cjs.map} +1 -1
- package/dist/{S3StateStore-CksKYKRa.mjs → S3StateStore-hIm8Rrmu.mjs} +2 -2
- package/dist/{S3StateStore-CksKYKRa.mjs.map → S3StateStore-hIm8Rrmu.mjs.map} +1 -1
- package/dist/{SSMStateStore-aBOTF018.cjs → SSMStateStore-DIzbiqCz.cjs} +2 -2
- package/dist/{SSMStateStore-aBOTF018.cjs.map → SSMStateStore-DIzbiqCz.cjs.map} +1 -1
- package/dist/{SSMStateStore-BszSCAS2.mjs → SSMStateStore-IvcjTk8h.mjs} +2 -2
- package/dist/{SSMStateStore-BszSCAS2.mjs.map → SSMStateStore-IvcjTk8h.mjs.map} +1 -1
- package/dist/SubscriberGenerator-BPqQf8fB.mjs.map +1 -1
- package/dist/SubscriberGenerator-BVn7cQ-2.cjs.map +1 -1
- package/dist/{add-5MZAXybv.cjs → add-C9qX4Juc.cjs} +30 -7
- package/dist/add-C9qX4Juc.cjs.map +1 -0
- package/dist/{add-D_jNqnfZ.mjs → add-v3tCbrpE.mjs} +30 -7
- package/dist/add-v3tCbrpE.mjs.map +1 -0
- package/dist/{bundler-1REMhKps.cjs → bundler-C4NmpRTD.cjs} +5 -5
- package/dist/{bundler-1REMhKps.cjs.map → bundler-C4NmpRTD.cjs.map} +1 -1
- package/dist/{bundler-BMo-JP5s.mjs → bundler-C_fCgcVO.mjs} +5 -5
- package/dist/{bundler-BMo-JP5s.mjs.map → bundler-C_fCgcVO.mjs.map} +1 -1
- package/dist/{cli-BL8ZHsLQ.cjs → cli-C85Dut8K.cjs} +6 -5
- package/dist/cli-C85Dut8K.cjs.map +1 -0
- package/dist/{cli-7edNFwGk.mjs → cli-REdO9X5b.mjs} +7 -6
- package/dist/cli-REdO9X5b.mjs.map +1 -0
- package/dist/{compose-xw86kVYi.cjs → compose-BvrhDwJ6.cjs} +556 -30
- package/dist/compose-BvrhDwJ6.cjs.map +1 -0
- package/dist/{compose-DbJhRQlh.mjs → compose-Dn0oAgQ0.mjs} +509 -31
- package/dist/compose-Dn0oAgQ0.mjs.map +1 -0
- package/dist/{config-DrCAyoH5.d.mts → config-CdEcTrjG.d.mts} +3 -3
- package/dist/{config-CpjsVxru.d.cts.map → config-CdEcTrjG.d.mts.map} +1 -1
- package/dist/{config-CpjsVxru.d.cts → config-pST7E0CS.d.cts} +3 -3
- package/dist/{config-DrCAyoH5.d.mts.map → config-pST7E0CS.d.cts.map} +1 -1
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +3 -3
- package/dist/config.d.mts +3 -3
- package/dist/config.mjs +1 -1
- package/dist/{credentials-tr26-KML.cjs → credentials-BKfIugu2.cjs} +47 -2
- package/dist/credentials-BKfIugu2.cjs.map +1 -0
- package/dist/{credentials-BgJ5mS_d.mjs → credentials-CnVqoXMb.mjs} +30 -3
- package/dist/credentials-CnVqoXMb.mjs.map +1 -0
- package/dist/deploy/public.cjs +10 -10
- package/dist/deploy/public.d.cts +9 -3
- package/dist/deploy/public.d.cts.map +1 -1
- package/dist/deploy/public.d.mts +9 -3
- package/dist/deploy/public.d.mts.map +1 -1
- package/dist/deploy/public.mjs +10 -10
- package/dist/{deploy-BTfmXd3g.mjs → deploy-BaERRh0Q.mjs} +10 -8
- package/dist/deploy-BaERRh0Q.mjs.map +1 -0
- package/dist/{deploy-CtbZj4zN.cjs → deploy-DbBGo3a6.cjs} +10 -8
- package/dist/deploy-DbBGo3a6.cjs.map +1 -0
- package/dist/{dokploy-r69yZaIt.mjs → dokploy-CMmD_ddX.mjs} +2 -2
- package/dist/{dokploy-r69yZaIt.mjs.map → dokploy-CMmD_ddX.mjs.map} +1 -1
- package/dist/{dokploy-TGk3oPwr.cjs → dokploy-DwAaKA9B.cjs} +2 -2
- package/dist/{dokploy-TGk3oPwr.cjs.map → dokploy-DwAaKA9B.cjs.map} +1 -1
- package/dist/{encryption-C-8Tt5Hh.mjs → encryption-BQmhq9_y.mjs} +3 -3
- package/dist/{encryption-C-8Tt5Hh.mjs.map → encryption-BQmhq9_y.mjs.map} +1 -1
- package/dist/{encryption-CDn7BH5O.cjs → encryption-BrN_9_CM.cjs} +3 -3
- package/dist/{encryption-CDn7BH5O.cjs.map → encryption-BrN_9_CM.cjs.map} +1 -1
- package/dist/{engine-jAINgiOB.mjs → engine-DILocOOH.mjs} +23 -404
- package/dist/engine-DILocOOH.mjs.map +1 -0
- package/dist/{engine-Bt5k_UMq.cjs → engine-DgHoFBMw.cjs} +25 -406
- package/dist/engine-DgHoFBMw.cjs.map +1 -0
- package/dist/{github-DFhuJQlp.cjs → github-Bf7pz6AV.cjs} +3 -3
- package/dist/{github-DFhuJQlp.cjs.map → github-Bf7pz6AV.cjs.map} +1 -1
- package/dist/{github-CZHAtwPT.mjs → github-xzg99wz8.mjs} +3 -3
- package/dist/{github-CZHAtwPT.mjs.map → github-xzg99wz8.mjs.map} +1 -1
- package/dist/{index-MnUJuUlj.d.mts → index-D-F_hTDz.d.cts} +21 -4
- package/dist/index-D-F_hTDz.d.cts.map +1 -0
- package/dist/{index-elsLJTUv.d.cts → index-YFNxR5Ns.d.mts} +21 -4
- package/dist/index-YFNxR5Ns.d.mts.map +1 -0
- package/dist/index.cjs +246 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +247 -65
- package/dist/index.mjs.map +1 -1
- package/dist/{local-Cq8qdgNX.cjs → local-BjxDfPvy.cjs} +2 -2
- package/dist/{local-Cq8qdgNX.cjs.map → local-BjxDfPvy.cjs.map} +1 -1
- package/dist/{local-Ciq-bTPr.mjs → local-IuoIF3CT.mjs} +2 -2
- package/dist/{local-Ciq-bTPr.mjs.map → local-IuoIF3CT.mjs.map} +1 -1
- package/dist/{migrate-B1rVlwj1.cjs → migrate-7xayVtzL.cjs} +3 -3
- package/dist/{migrate-B1rVlwj1.cjs.map → migrate-7xayVtzL.cjs.map} +1 -1
- package/dist/{migrate-ggkPVJRC.mjs → migrate-CKLJ73OO.mjs} +4 -4
- package/dist/{migrate-ggkPVJRC.mjs.map → migrate-CKLJ73OO.mjs.map} +1 -1
- package/dist/{migrate-Dn7nK6sh.mjs → migrate-CpmO5qnl.mjs} +3 -3
- package/dist/{migrate-Dn7nK6sh.mjs.map → migrate-CpmO5qnl.mjs.map} +1 -1
- package/dist/{migrate-B16qgYTn.cjs → migrate-DPF7ZF8M.cjs} +3 -3
- package/dist/{migrate-B16qgYTn.cjs.map → migrate-DPF7ZF8M.cjs.map} +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/reconcile/public.d.cts +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/{reconcile--I7V4Klj.mjs → reconcile-Dh1Jk7WE.mjs} +2 -2
- package/dist/{reconcile--I7V4Klj.mjs.map → reconcile-Dh1Jk7WE.mjs.map} +1 -1
- package/dist/{resolve-BSke45k6.mjs → resolve-Dv_weZoh.mjs} +4 -4
- package/dist/{resolve-BSke45k6.mjs.map → resolve-Dv_weZoh.mjs.map} +1 -1
- package/dist/{resolve-BXeXzpmU.cjs → resolve-dlKPFNgv.cjs} +4 -4
- package/dist/{resolve-BXeXzpmU.cjs.map → resolve-dlKPFNgv.cjs.map} +1 -1
- package/dist/{rollback-DFMiBWf0.cjs → rollback-65VVIdBM.cjs} +6 -6
- package/dist/{rollback-DFMiBWf0.cjs.map → rollback-65VVIdBM.cjs.map} +1 -1
- package/dist/{rollback-CEE6dse4.mjs → rollback-DpSU2DsD.mjs} +6 -6
- package/dist/{rollback-CEE6dse4.mjs.map → rollback-DpSU2DsD.mjs.map} +1 -1
- package/dist/{runtime-HabiNBtJ.d.mts → runtime-CN_kmqxo.d.cts} +2 -2
- package/dist/{runtime-D48ZKk8_.d.cts.map → runtime-CN_kmqxo.d.cts.map} +1 -1
- package/dist/{runtime-D48ZKk8_.d.cts → runtime-Cjvon3oj.d.mts} +2 -2
- package/dist/{runtime-HabiNBtJ.d.mts.map → runtime-Cjvon3oj.d.mts.map} +1 -1
- package/dist/{seeds-CsI0A_Ef.cjs → seeds-CN6tB-va.cjs} +646 -187
- package/dist/{seeds-CsI0A_Ef.cjs.map → seeds-CN6tB-va.cjs.map} +1 -1
- package/dist/{seeds-BYdrtZsC.mjs → seeds-perzdN81.mjs} +599 -164
- package/dist/seeds-perzdN81.mjs.map +1 -0
- package/dist/{sniffer-B0EU73bj.mjs → sniffer-BTtX3NUM.mjs} +3 -3
- package/dist/{sniffer-B0EU73bj.mjs.map → sniffer-BTtX3NUM.mjs.map} +1 -1
- package/dist/{sniffer-DJYupBeK.cjs → sniffer-IAQEpsQb.cjs} +3 -3
- package/dist/{sniffer-DJYupBeK.cjs.map → sniffer-IAQEpsQb.cjs.map} +1 -1
- package/dist/{sst-DAqUoZKG.cjs → sst-BgcOsaBi.cjs} +3 -3
- package/dist/{sst-DAqUoZKG.cjs.map → sst-BgcOsaBi.cjs.map} +1 -1
- package/dist/{sst-D1Qj4sIs.mjs → sst-CJzvyrEz.mjs} +3 -3
- package/dist/{sst-D1Qj4sIs.mjs.map → sst-CJzvyrEz.mjs.map} +1 -1
- package/dist/{stages-Brn3vcdy.cjs → stages-CUn6gvXL.cjs} +2 -2
- package/dist/{stages-Brn3vcdy.cjs.map → stages-CUn6gvXL.cjs.map} +1 -1
- package/dist/{stages-DoHHz6pS.mjs → stages-CnZRYmkI.mjs} +2 -2
- package/dist/{stages-DoHHz6pS.mjs.map → stages-CnZRYmkI.mjs.map} +1 -1
- package/dist/target/public.cjs +1 -1
- package/dist/target/public.d.cts +2 -2
- package/dist/target/public.d.mts +2 -2
- package/dist/target/public.mjs +1 -1
- package/dist/{terminal-BTbZlrFV.mjs → terminal-D8TPK7o9.mjs} +3 -3
- package/dist/{terminal-BTbZlrFV.mjs.map → terminal-D8TPK7o9.mjs.map} +1 -1
- package/dist/{terminal-COv23heb.cjs → terminal-DuapRxh6.cjs} +2 -2
- package/dist/{terminal-COv23heb.cjs.map → terminal-DuapRxh6.cjs.map} +1 -1
- package/dist/{types-0oAyFOfR.d.cts → types-NqX1Hz4P.d.cts} +210 -205
- package/dist/types-NqX1Hz4P.d.cts.map +1 -0
- package/dist/{types-BZ01tZs-.d.mts → types-ZHuZ89hv.d.mts} +210 -205
- package/dist/types-ZHuZ89hv.d.mts.map +1 -0
- package/dist/workspace/index.cjs +3 -1
- package/dist/workspace/index.d.cts +3 -3
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +2 -2
- package/dist/{workspace-D2CYLMCW.mjs → workspace-CJ0lKFq-.mjs} +231 -10
- package/dist/workspace-CJ0lKFq-.mjs.map +1 -0
- package/dist/{workspace-CT0JM3Y8.cjs → workspace-CwW3Gkru.cjs} +266 -9
- package/dist/workspace-CwW3Gkru.cjs.map +1 -0
- package/package.json +15 -15
- package/dist/add-5MZAXybv.cjs.map +0 -1
- package/dist/add-D_jNqnfZ.mjs.map +0 -1
- package/dist/cli-7edNFwGk.mjs.map +0 -1
- package/dist/cli-BL8ZHsLQ.cjs.map +0 -1
- package/dist/compose-DbJhRQlh.mjs.map +0 -1
- package/dist/compose-xw86kVYi.cjs.map +0 -1
- package/dist/credentials-BgJ5mS_d.mjs.map +0 -1
- package/dist/credentials-tr26-KML.cjs.map +0 -1
- package/dist/deploy-BTfmXd3g.mjs.map +0 -1
- package/dist/deploy-CtbZj4zN.cjs.map +0 -1
- package/dist/engine-Bt5k_UMq.cjs.map +0 -1
- package/dist/engine-jAINgiOB.mjs.map +0 -1
- package/dist/index-MnUJuUlj.d.mts.map +0 -1
- package/dist/index-elsLJTUv.d.cts.map +0 -1
- package/dist/seeds-BYdrtZsC.mjs.map +0 -1
- package/dist/types-0oAyFOfR.d.cts.map +0 -1
- package/dist/types-BZ01tZs-.d.mts.map +0 -1
- package/dist/workspace-CT0JM3Y8.cjs.map +0 -1
- package/dist/workspace-D2CYLMCW.mjs.map +0 -1
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { r as storedCredentials, t as MissingCredential } from "./credentials-CnVqoXMb.mjs";
|
|
2
|
+
import { P as DnsRecordsUnreadable } from "./seeds-perzdN81.mjs";
|
|
3
|
+
/** The record types gkm writes. Never MX, TXT, NS, SOA, SRV or CAA. */
|
|
4
|
+
const GODADDY_MANAGED_TYPES = [
|
|
5
|
+
"A",
|
|
6
|
+
"AAAA",
|
|
7
|
+
"CNAME"
|
|
8
|
+
];
|
|
9
|
+
/**
|
|
10
|
+
* The token is good, and GoDaddy will not let it use the API: since 2024 the
|
|
11
|
+
* Domains and DNS APIs answer only accounts with 10 or more domains, or a
|
|
12
|
+
* Discount Domain Club Premier membership.
|
|
13
|
+
*/
|
|
14
|
+
var GoDaddyApiAccessDenied = class extends Error {
|
|
15
|
+
domain;
|
|
16
|
+
detail;
|
|
17
|
+
constructor(domain, detail) {
|
|
18
|
+
super(`GoDaddy refused API access for ${domain} (403 ACCESS_DENIED${detail ? `: ${detail}` : ""}). GoDaddy only opens its DNS API to accounts with 10 or more domains, or with a Discount Domain Club Premier membership, so a valid token on a smaller account is refused. Either qualify the account, move the domain's DNS hosting to Route53 (provider: 'route53') or Cloudflare by changing its nameservers at GoDaddy, or set provider: 'manual' and create the records gkm prints yourself. (A scoped token without domains.dns:update is refused the same way — check its scopes too.)`);
|
|
19
|
+
this.domain = domain;
|
|
20
|
+
this.detail = detail;
|
|
21
|
+
this.name = "GoDaddyApiAccessDenied";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
/** The token lacks the scope a records call needs. */
|
|
25
|
+
var GoDaddyScopeMissing = class extends Error {
|
|
26
|
+
method;
|
|
27
|
+
domain;
|
|
28
|
+
scope;
|
|
29
|
+
detail;
|
|
30
|
+
constructor(method, domain, scope, detail) {
|
|
31
|
+
super(`GoDaddy refused ${method} on ${domain}'s DNS records (403${detail ? `: ${detail}` : ""}): the token lacks the ${scope} scope. Create a Personal Access Token in the GoDaddy developer dashboard with domains.dns:update — no domain or account scope is needed — and set GODADDY_API_TOKEN or run \`gkm login --provider godaddy\` again.`);
|
|
32
|
+
this.method = method;
|
|
33
|
+
this.domain = domain;
|
|
34
|
+
this.scope = scope;
|
|
35
|
+
this.detail = detail;
|
|
36
|
+
this.name = "GoDaddyScopeMissing";
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
/** GoDaddy did not accept the token at all. */
|
|
40
|
+
var GoDaddyCredentialsInvalid = class extends Error {
|
|
41
|
+
code;
|
|
42
|
+
constructor(code) {
|
|
43
|
+
super(`GoDaddy did not accept the API token (401${code ? ` ${code}` : ""}). Check GODADDY_API_TOKEN, or run \`gkm login --provider godaddy\` again with a Personal Access Token from the GoDaddy developer dashboard that has not expired or been revoked.`);
|
|
44
|
+
this.code = code;
|
|
45
|
+
this.name = "GoDaddyCredentialsInvalid";
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/** The domain is not in the account the token belongs to. */
|
|
49
|
+
var GoDaddyDomainNotFound = class extends Error {
|
|
50
|
+
domain;
|
|
51
|
+
code;
|
|
52
|
+
constructor(domain, code) {
|
|
53
|
+
super(`GoDaddy has no domain ${domain} in this token's account${code ? ` (${code})` : ""}. Check the root domain in dns, and that the token belongs to the account the domain is registered in.`);
|
|
54
|
+
this.domain = domain;
|
|
55
|
+
this.code = code;
|
|
56
|
+
this.name = "GoDaddyDomainNotFound";
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
/** Still rate limited after waiting it out. */
|
|
60
|
+
var GoDaddyRateLimited = class extends Error {
|
|
61
|
+
attempts;
|
|
62
|
+
retryAfterSec;
|
|
63
|
+
constructor(attempts, retryAfterSec) {
|
|
64
|
+
super(`GoDaddy is still rate limiting this token after ${attempts} attempts (429 TOO_MANY_REQUESTS — about 60 requests a minute are allowed). Wait${retryAfterSec ? ` ${retryAfterSec} seconds` : " a minute"} and run it again; records already written are left as they are.`);
|
|
65
|
+
this.attempts = attempts;
|
|
66
|
+
this.retryAfterSec = retryAfterSec;
|
|
67
|
+
this.name = "GoDaddyRateLimited";
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
/** Any other failure from GoDaddy. */
|
|
71
|
+
var GoDaddyRequestFailed = class extends Error {
|
|
72
|
+
method;
|
|
73
|
+
path;
|
|
74
|
+
status;
|
|
75
|
+
code;
|
|
76
|
+
detail;
|
|
77
|
+
constructor(method, path, status, code, detail) {
|
|
78
|
+
super(`GoDaddy answered ${method} ${path} with ${status}${code ? ` ${code}` : ""}${detail ? `: ${detail}` : ""}.` + (status === 422 ? " A name with a CNAME cannot also have an A or AAAA record, and the reverse — remove the other one first." : ""));
|
|
79
|
+
this.method = method;
|
|
80
|
+
this.path = path;
|
|
81
|
+
this.status = status;
|
|
82
|
+
this.code = code;
|
|
83
|
+
this.detail = detail;
|
|
84
|
+
this.name = "GoDaddyRequestFailed";
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* A write gkm was about to make to a record type it never manages, or to a
|
|
89
|
+
* name it was not asked for.
|
|
90
|
+
*/
|
|
91
|
+
var GoDaddyRecordNotAllowed = class extends Error {
|
|
92
|
+
domain;
|
|
93
|
+
type;
|
|
94
|
+
recordName;
|
|
95
|
+
reason;
|
|
96
|
+
constructor(domain, type, recordName, reason) {
|
|
97
|
+
super(`Refused to change the ${type} record '${recordName}' on ${domain}: ${reason}. gkm only ever writes the A, AAAA and CNAME records of the hosts it serves.`);
|
|
98
|
+
this.domain = domain;
|
|
99
|
+
this.type = type;
|
|
100
|
+
this.recordName = recordName;
|
|
101
|
+
this.reason = reason;
|
|
102
|
+
this.name = "GoDaddyRecordNotAllowed";
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
/** A record name GoDaddy's path takes: `@` for the apex, else relative. */
|
|
106
|
+
function isRecordName(name) {
|
|
107
|
+
return name === "@" || /^(\*\.)?[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9])?(\.[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9])?)*$/i.test(name);
|
|
108
|
+
}
|
|
109
|
+
/** The client. Every method touches one record set, by type and name. */
|
|
110
|
+
var GoDaddyApi = class {
|
|
111
|
+
baseUrl;
|
|
112
|
+
sleep;
|
|
113
|
+
maxAttempts;
|
|
114
|
+
authorization;
|
|
115
|
+
/** Whether a read has succeeded: a later 403 is then the token's scope. */
|
|
116
|
+
readSucceeded = false;
|
|
117
|
+
constructor(options) {
|
|
118
|
+
this.baseUrl = (options.baseUrl ?? "https://api.godaddy.com").replace(/\/$/, "");
|
|
119
|
+
this.sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
120
|
+
this.maxAttempts = options.maxAttempts ?? 4;
|
|
121
|
+
this.authorization = `Bearer ${options.credential.token}`;
|
|
122
|
+
}
|
|
123
|
+
/** The records of one name and type — empty when there are none. */
|
|
124
|
+
async getRecordSet(domain, type, name) {
|
|
125
|
+
this.guard(domain, type, name);
|
|
126
|
+
const records = await this.request("GET", domain, this.recordPath(domain, type, name));
|
|
127
|
+
return Array.isArray(records) ? records : [];
|
|
128
|
+
}
|
|
129
|
+
/** Replace one name's records of one type with `values`. */
|
|
130
|
+
async replaceRecordSet(domain, type, name, values, ttl) {
|
|
131
|
+
this.guard(domain, type, name);
|
|
132
|
+
await this.request("PUT", domain, this.recordPath(domain, type, name), values.map((data) => ({
|
|
133
|
+
data,
|
|
134
|
+
ttl: Math.max(ttl, 600)
|
|
135
|
+
})));
|
|
136
|
+
}
|
|
137
|
+
/** Delete one name's records of one type. */
|
|
138
|
+
async deleteRecordSet(domain, type, name) {
|
|
139
|
+
this.guard(domain, type, name);
|
|
140
|
+
await this.request("DELETE", domain, this.recordPath(domain, type, name));
|
|
141
|
+
}
|
|
142
|
+
recordPath(domain, type, name) {
|
|
143
|
+
return `/v1/domains/${encodeURIComponent(domain)}/records/${type}/${encodeURIComponent(name)}`;
|
|
144
|
+
}
|
|
145
|
+
/** Only A, AAAA and CNAME, at a real record name. */
|
|
146
|
+
guard(domain, type, name) {
|
|
147
|
+
if (!GODADDY_MANAGED_TYPES.includes(type)) throw new GoDaddyRecordNotAllowed(domain, type, name, "it is not a type gkm manages");
|
|
148
|
+
if (!isRecordName(name)) throw new GoDaddyRecordNotAllowed(domain, type, name, "it is not a record name relative to the domain");
|
|
149
|
+
}
|
|
150
|
+
async request(method, domain, path, body) {
|
|
151
|
+
let retryAfterSec;
|
|
152
|
+
for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {
|
|
153
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
154
|
+
method,
|
|
155
|
+
headers: {
|
|
156
|
+
Authorization: this.authorization,
|
|
157
|
+
Accept: "application/json",
|
|
158
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {}
|
|
159
|
+
},
|
|
160
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
161
|
+
});
|
|
162
|
+
if (response.ok) {
|
|
163
|
+
if (method === "GET") this.readSucceeded = true;
|
|
164
|
+
if (response.status === 204) return void 0;
|
|
165
|
+
const text = await response.text();
|
|
166
|
+
return text ? JSON.parse(text) : void 0;
|
|
167
|
+
}
|
|
168
|
+
const error = await errorBody(response);
|
|
169
|
+
if (response.status === 504 && attempt < this.maxAttempts) {
|
|
170
|
+
await this.sleep(Math.min(2 ** attempt * 1e3, 3e4));
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (response.status === 429) {
|
|
174
|
+
retryAfterSec = error.retryAfterSec;
|
|
175
|
+
if (attempt === this.maxAttempts) break;
|
|
176
|
+
const waitMs = retryAfterSec !== void 0 ? Math.min(retryAfterSec, 60) * 1e3 : Math.min(2 ** attempt * 1e3, 6e4);
|
|
177
|
+
await this.sleep(waitMs);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (response.status === 401) throw new GoDaddyCredentialsInvalid(error.code);
|
|
181
|
+
if (response.status === 403) {
|
|
182
|
+
if (/scope/i.test(`${error.code ?? ""} ${error.message ?? ""}`) || method !== "GET" && this.readSucceeded) throw new GoDaddyScopeMissing(method, domain, method === "GET" ? "DNS records read" : "domains.dns:update", error.message ?? error.code);
|
|
183
|
+
throw new GoDaddyApiAccessDenied(domain, error.message ?? error.code);
|
|
184
|
+
}
|
|
185
|
+
if (response.status === 404) throw new GoDaddyDomainNotFound(domain, error.code);
|
|
186
|
+
if (response.status === 422 && /domain/i.test(error.code ?? "") && !/record/i.test(`${error.code ?? ""} ${error.message ?? ""}`)) throw new GoDaddyDomainNotFound(domain, error.code);
|
|
187
|
+
throw new GoDaddyRequestFailed(method, path, response.status, error.code, error.message);
|
|
188
|
+
}
|
|
189
|
+
throw new GoDaddyRateLimited(this.maxAttempts, retryAfterSec);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
async function errorBody(response) {
|
|
193
|
+
try {
|
|
194
|
+
const parsed = await response.json();
|
|
195
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
196
|
+
} catch {
|
|
197
|
+
return {};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region src/target/dokploy/dns/GoDaddyProvider.ts
|
|
202
|
+
/**
|
|
203
|
+
* GoDaddy DNS Provider
|
|
204
|
+
*
|
|
205
|
+
* Implements DnsProvider against GoDaddy's v1 API, one record set — a name
|
|
206
|
+
* and a type — at a time: it reads and writes only the A, AAAA and CNAME
|
|
207
|
+
* records of the names it is handed, and never the zone as a whole, a domain
|
|
208
|
+
* or the account. A Personal Access Token scoped to `domains.dns:update` is all it needs.
|
|
209
|
+
*
|
|
210
|
+
* A token that may write records and not read them puts the provider in
|
|
211
|
+
* write-only mode: every record is PUT — idempotent, so one that already has
|
|
212
|
+
* its value is left as it was — and nothing is compared or deleted.
|
|
213
|
+
*
|
|
214
|
+
* Credentials: `GODADDY_API_TOKEN`, else what `gkm login --provider godaddy`
|
|
215
|
+
* stored. Never logged.
|
|
216
|
+
*/
|
|
217
|
+
/** GoDaddy cannot list a zone through the records-by-name endpoints. */
|
|
218
|
+
var GoDaddyZoneListingUnsupported = class extends Error {
|
|
219
|
+
domain;
|
|
220
|
+
constructor(domain) {
|
|
221
|
+
super(`gkm reads GoDaddy records by name and type only — it never lists ${domain}'s whole zone, so a token scoped to DNS updates is enough. Use readRecords(domain, [{ name, type }]) instead of getRecords.`);
|
|
222
|
+
this.domain = domain;
|
|
223
|
+
this.name = "GoDaddyZoneListingUnsupported";
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
/** A value compared the way DNS does: case-insensitive, no trailing dot. */
|
|
227
|
+
function normalize(value) {
|
|
228
|
+
return value.trim().replace(/\.$/, "").toLowerCase();
|
|
229
|
+
}
|
|
230
|
+
function managed(type) {
|
|
231
|
+
return GODADDY_MANAGED_TYPES.includes(type);
|
|
232
|
+
}
|
|
233
|
+
/** A read GoDaddy refused: write-only, rather than a failure. */
|
|
234
|
+
function readDenied(error) {
|
|
235
|
+
return error instanceof GoDaddyScopeMissing || error instanceof GoDaddyApiAccessDenied;
|
|
236
|
+
}
|
|
237
|
+
var GoDaddyProvider = class {
|
|
238
|
+
options;
|
|
239
|
+
name = "godaddy";
|
|
240
|
+
api = null;
|
|
241
|
+
/** Set once a read is refused: every write is then a blind PUT. */
|
|
242
|
+
writeOnly = false;
|
|
243
|
+
constructor(options = {}) {
|
|
244
|
+
this.options = options;
|
|
245
|
+
}
|
|
246
|
+
/** Whether the token turned out unable to read records. */
|
|
247
|
+
get readsDenied() {
|
|
248
|
+
return this.writeOnly;
|
|
249
|
+
}
|
|
250
|
+
async getApi() {
|
|
251
|
+
if (this.api) return this.api;
|
|
252
|
+
const credential = this.options.credential ?? await storedCredentials({
|
|
253
|
+
env: this.options.env ?? process.env,
|
|
254
|
+
...this.options.home ? { home: this.options.home } : {}
|
|
255
|
+
}).get({ kind: "godaddy" });
|
|
256
|
+
if (!credential) throw new MissingCredential("godaddy", void 0);
|
|
257
|
+
this.api = new GoDaddyApi({
|
|
258
|
+
credential,
|
|
259
|
+
...this.options.baseUrl ? { baseUrl: this.options.baseUrl } : {},
|
|
260
|
+
...this.options.sleep ? { sleep: this.options.sleep } : {},
|
|
261
|
+
...this.options.maxAttempts ? { maxAttempts: this.options.maxAttempts } : {}
|
|
262
|
+
});
|
|
263
|
+
return this.api;
|
|
264
|
+
}
|
|
265
|
+
assertManaged(domain, type, name) {
|
|
266
|
+
if (!managed(type)) throw new GoDaddyRecordNotAllowed(domain, type, name, "it is not a type gkm manages");
|
|
267
|
+
}
|
|
268
|
+
/** Never: the whole zone is not read. See {@link GoDaddyZoneListingUnsupported}. */
|
|
269
|
+
async getRecords(domain) {
|
|
270
|
+
throw new GoDaddyZoneListingUnsupported(domain);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* The records of exactly these names and types, one request each.
|
|
274
|
+
*
|
|
275
|
+
* @throws {DnsRecordsUnreadable} when the token may not read records
|
|
276
|
+
*/
|
|
277
|
+
async readRecords(domain, wanted) {
|
|
278
|
+
for (const { name, type } of wanted) this.assertManaged(domain, type, name);
|
|
279
|
+
const api = await this.getApi();
|
|
280
|
+
const found = [];
|
|
281
|
+
for (const { name, type } of wanted) {
|
|
282
|
+
let records;
|
|
283
|
+
try {
|
|
284
|
+
records = await api.getRecordSet(domain, type, name);
|
|
285
|
+
} catch (error) {
|
|
286
|
+
if (!readDenied(error)) throw error;
|
|
287
|
+
this.writeOnly = true;
|
|
288
|
+
throw new DnsRecordsUnreadable(this.name, domain, error.name);
|
|
289
|
+
}
|
|
290
|
+
if (records.length === 0) continue;
|
|
291
|
+
found.push({
|
|
292
|
+
name,
|
|
293
|
+
type,
|
|
294
|
+
ttl: records[0].ttl ?? 600,
|
|
295
|
+
values: records.map((r) => r.data)
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return found;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Each record set to exactly its one value: read it, and write it only
|
|
302
|
+
* when it differs — or, with a token that cannot read, write it. Only the
|
|
303
|
+
* name and type of each record handed in is touched.
|
|
304
|
+
*/
|
|
305
|
+
async upsertRecords(domain, records) {
|
|
306
|
+
for (const record of records) this.assertManaged(domain, record.type, record.name);
|
|
307
|
+
const api = await this.getApi();
|
|
308
|
+
const results = [];
|
|
309
|
+
for (const record of records) {
|
|
310
|
+
const type = record.type;
|
|
311
|
+
let existing;
|
|
312
|
+
if (!this.writeOnly) try {
|
|
313
|
+
existing = await api.getRecordSet(domain, type, record.name);
|
|
314
|
+
} catch (error) {
|
|
315
|
+
if (!readDenied(error)) throw error;
|
|
316
|
+
this.writeOnly = true;
|
|
317
|
+
(this.options.log ?? console.log)(` ℹ The GoDaddy token cannot read ${domain}'s DNS records, so changes cannot be diffed: writing each record (idempotent).`);
|
|
318
|
+
}
|
|
319
|
+
if (existing) {
|
|
320
|
+
const values = existing.map((r) => normalize(r.data));
|
|
321
|
+
if (values.length === 1 && values[0] === normalize(record.value)) {
|
|
322
|
+
results.push({
|
|
323
|
+
record,
|
|
324
|
+
created: false,
|
|
325
|
+
unchanged: true
|
|
326
|
+
});
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
await api.replaceRecordSet(domain, type, record.name, [record.value], Math.max(record.ttl, 600));
|
|
331
|
+
results.push({
|
|
332
|
+
record,
|
|
333
|
+
created: existing !== void 0 && existing.length === 0,
|
|
334
|
+
unchanged: false
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
return results;
|
|
338
|
+
}
|
|
339
|
+
async deleteRecords(domain, records) {
|
|
340
|
+
for (const record of records) this.assertManaged(domain, record.type, record.name);
|
|
341
|
+
const api = await this.getApi();
|
|
342
|
+
const results = [];
|
|
343
|
+
for (const record of records) {
|
|
344
|
+
const type = record.type;
|
|
345
|
+
if (!this.writeOnly) {
|
|
346
|
+
let existing;
|
|
347
|
+
try {
|
|
348
|
+
existing = await api.getRecordSet(domain, type, record.name);
|
|
349
|
+
} catch (error) {
|
|
350
|
+
if (!readDenied(error)) throw error;
|
|
351
|
+
this.writeOnly = true;
|
|
352
|
+
}
|
|
353
|
+
if (existing && existing.length === 0) {
|
|
354
|
+
results.push({
|
|
355
|
+
record,
|
|
356
|
+
deleted: false,
|
|
357
|
+
notFound: true
|
|
358
|
+
});
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
try {
|
|
363
|
+
await api.deleteRecordSet(domain, type, record.name);
|
|
364
|
+
} catch (error) {
|
|
365
|
+
if (this.writeOnly && error instanceof GoDaddyDomainNotFound) {
|
|
366
|
+
results.push({
|
|
367
|
+
record,
|
|
368
|
+
deleted: false,
|
|
369
|
+
notFound: true
|
|
370
|
+
});
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
throw error;
|
|
374
|
+
}
|
|
375
|
+
results.push({
|
|
376
|
+
record,
|
|
377
|
+
deleted: true,
|
|
378
|
+
notFound: false
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
return results;
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
//#endregion
|
|
385
|
+
export { GoDaddyProvider };
|
|
386
|
+
|
|
387
|
+
//# sourceMappingURL=GoDaddyProvider--36rw8cP.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GoDaddyProvider--36rw8cP.mjs","names":[],"sources":["../src/target/dokploy/dns/godaddy-api.ts","../src/target/dokploy/dns/GoDaddyProvider.ts"],"sourcesContent":["/**\n * GoDaddy's v1 DNS API, as gkm uses it: one record set — a name and a type —\n * at a time.\n *\n * - read: `GET /v1/domains/{domain}/records/{type}/{name}`\n * - write: `PUT /v1/domains/{domain}/records/{type}/{name}` with `[{ data, ttl }]`,\n * which replaces that one name's records of that one type\n * - delete: `DELETE /v1/domains/{domain}/records/{type}/{name}`\n *\n * Never the zone-wide `PUT /v1/domains/{domain}/records`, which replaces every\n * record the domain has — mail, verification TXT records and all — and never\n * a domain or account endpoint (`GET /v1/domains`, `GET /v1/domains/{domain}`):\n * a token scoped to `domains.dns:update` alone is enough. A domain that is not\n * in the token's account is told apart by the records endpoint's own 404 or 422.\n *\n * Authenticated with a Personal Access Token — `Authorization: Bearer <token>`,\n * the API's one security scheme. GoDaddy allows about 60 requests a minute per\n * token; a 429 carries `retryAfterSec`, which is waited out a few times before\n * the run gives up with {@link GoDaddyRateLimited}. A 504 is retried the same\n * way. GoDaddy refuses a TTL under 600 seconds (a 422), so every write is\n * sent with at least that.\n */\n\nimport type { GoDaddyCredential } from '../../../deploy/credentials';\n\nexport const GODADDY_API_BASE = 'https://api.godaddy.com';\n\n/** GoDaddy refuses a TTL below this. */\nexport const GODADDY_MIN_TTL = 600;\n\n/** The record types gkm writes. Never MX, TXT, NS, SOA, SRV or CAA. */\nexport const GODADDY_MANAGED_TYPES = ['A', 'AAAA', 'CNAME'] as const;\n\nexport type GoDaddyRecordType = (typeof GODADDY_MANAGED_TYPES)[number];\n\n/** One record as GoDaddy returns it. */\nexport interface GoDaddyRecord {\n\ttype: string;\n\tname: string;\n\tdata: string;\n\tttl?: number;\n}\n\n/** GoDaddy's error body. */\ninterface GoDaddyErrorBody {\n\tcode?: string;\n\tmessage?: string;\n\tretryAfterSec?: number;\n}\n\n/**\n * The token is good, and GoDaddy will not let it use the API: since 2024 the\n * Domains and DNS APIs answer only accounts with 10 or more domains, or a\n * Discount Domain Club Premier membership.\n */\nexport class GoDaddyApiAccessDenied extends Error {\n\tconstructor(\n\t\treadonly domain: string,\n\t\treadonly detail?: string,\n\t) {\n\t\tsuper(\n\t\t\t`GoDaddy refused API access for ${domain} (403 ACCESS_DENIED${detail ? `: ${detail}` : ''}). ` +\n\t\t\t\t'GoDaddy only opens its DNS API to accounts with 10 or more domains, or ' +\n\t\t\t\t'with a Discount Domain Club Premier membership, so a valid token on a ' +\n\t\t\t\t'smaller account is refused. Either qualify the account, move the ' +\n\t\t\t\t\"domain's DNS hosting to Route53 (provider: 'route53') or Cloudflare \" +\n\t\t\t\t\"by changing its nameservers at GoDaddy, or set provider: 'manual' \" +\n\t\t\t\t'and create the records gkm prints yourself. (A scoped token without ' +\n\t\t\t\t'domains.dns:update is refused the same way — check its scopes too.)',\n\t\t);\n\t\tthis.name = 'GoDaddyApiAccessDenied';\n\t}\n}\n\n/** The token lacks the scope a records call needs. */\nexport class GoDaddyScopeMissing extends Error {\n\tconstructor(\n\t\treadonly method: string,\n\t\treadonly domain: string,\n\t\treadonly scope: string,\n\t\treadonly detail?: string,\n\t) {\n\t\tsuper(\n\t\t\t`GoDaddy refused ${method} on ${domain}'s DNS records (403${detail ? `: ${detail}` : ''}): ` +\n\t\t\t\t`the token lacks the ${scope} scope. Create a Personal Access Token ` +\n\t\t\t\t'in the GoDaddy developer dashboard with domains.dns:update — no ' +\n\t\t\t\t'domain or account scope is needed — and set GODADDY_API_TOKEN or ' +\n\t\t\t\t'run `gkm login --provider godaddy` again.',\n\t\t);\n\t\tthis.name = 'GoDaddyScopeMissing';\n\t}\n}\n\n/** GoDaddy did not accept the token at all. */\nexport class GoDaddyCredentialsInvalid extends Error {\n\tconstructor(readonly code?: string) {\n\t\tsuper(\n\t\t\t`GoDaddy did not accept the API token (401${code ? ` ${code}` : ''}). ` +\n\t\t\t\t'Check GODADDY_API_TOKEN, or run `gkm login --provider godaddy` ' +\n\t\t\t\t'again with a Personal Access Token from the GoDaddy developer ' +\n\t\t\t\t'dashboard that has not expired or been revoked.',\n\t\t);\n\t\tthis.name = 'GoDaddyCredentialsInvalid';\n\t}\n}\n\n/** The domain is not in the account the token belongs to. */\nexport class GoDaddyDomainNotFound extends Error {\n\tconstructor(\n\t\treadonly domain: string,\n\t\treadonly code?: string,\n\t) {\n\t\tsuper(\n\t\t\t`GoDaddy has no domain ${domain} in this token's account${code ? ` (${code})` : ''}. ` +\n\t\t\t\t'Check the root domain in dns, and that the token belongs to the account the domain is registered in.',\n\t\t);\n\t\tthis.name = 'GoDaddyDomainNotFound';\n\t}\n}\n\n/** Still rate limited after waiting it out. */\nexport class GoDaddyRateLimited extends Error {\n\tconstructor(\n\t\treadonly attempts: number,\n\t\treadonly retryAfterSec?: number,\n\t) {\n\t\tsuper(\n\t\t\t`GoDaddy is still rate limiting this token after ${attempts} attempts ` +\n\t\t\t\t'(429 TOO_MANY_REQUESTS — about 60 requests a minute are allowed). ' +\n\t\t\t\t`Wait${retryAfterSec ? ` ${retryAfterSec} seconds` : ' a minute'} and run it again; ` +\n\t\t\t\t'records already written are left as they are.',\n\t\t);\n\t\tthis.name = 'GoDaddyRateLimited';\n\t}\n}\n\n/** Any other failure from GoDaddy. */\nexport class GoDaddyRequestFailed extends Error {\n\tconstructor(\n\t\treadonly method: string,\n\t\treadonly path: string,\n\t\treadonly status: number,\n\t\treadonly code?: string,\n\t\treadonly detail?: string,\n\t) {\n\t\tsuper(\n\t\t\t`GoDaddy answered ${method} ${path} with ${status}${code ? ` ${code}` : ''}` +\n\t\t\t\t`${detail ? `: ${detail}` : ''}.` +\n\t\t\t\t(status === 422\n\t\t\t\t\t? ' A name with a CNAME cannot also have an A or AAAA record, and the reverse — remove the other one first.'\n\t\t\t\t\t: ''),\n\t\t);\n\t\tthis.name = 'GoDaddyRequestFailed';\n\t}\n}\n\n/**\n * A write gkm was about to make to a record type it never manages, or to a\n * name it was not asked for.\n */\nexport class GoDaddyRecordNotAllowed extends Error {\n\tconstructor(\n\t\treadonly domain: string,\n\t\treadonly type: string,\n\t\treadonly recordName: string,\n\t\treadonly reason: string,\n\t) {\n\t\tsuper(\n\t\t\t`Refused to change the ${type} record '${recordName}' on ${domain}: ${reason}. ` +\n\t\t\t\t'gkm only ever writes the A, AAAA and CNAME records of the hosts it serves.',\n\t\t);\n\t\tthis.name = 'GoDaddyRecordNotAllowed';\n\t}\n}\n\nexport interface GoDaddyApiOptions {\n\tcredential: GoDaddyCredential;\n\t/** The API's base URL. GoDaddy's production API by default. */\n\tbaseUrl?: string;\n\t/** How a 429 or 504 is waited out — `setTimeout` by default; tests pass their own. */\n\tsleep?: (ms: number) => Promise<void>;\n\t/** How many times one request is sent before a 429 or 504 is final. Default 4. */\n\tmaxAttempts?: number;\n}\n\n/** A record name GoDaddy's path takes: `@` for the apex, else relative. */\nfunction isRecordName(name: string): boolean {\n\treturn (\n\t\tname === '@' ||\n\t\t/^(\\*\\.)?[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9])?(\\.[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9])?)*$/i.test(\n\t\t\tname,\n\t\t)\n\t);\n}\n\n/** The client. Every method touches one record set, by type and name. */\nexport class GoDaddyApi {\n\tprivate readonly baseUrl: string;\n\tprivate readonly sleep: (ms: number) => Promise<void>;\n\tprivate readonly maxAttempts: number;\n\tprivate readonly authorization: string;\n\t/** Whether a read has succeeded: a later 403 is then the token's scope. */\n\tprivate readSucceeded = false;\n\n\tconstructor(options: GoDaddyApiOptions) {\n\t\tthis.baseUrl = (options.baseUrl ?? GODADDY_API_BASE).replace(/\\/$/, '');\n\t\tthis.sleep =\n\t\t\toptions.sleep ??\n\t\t\t((ms) => new Promise((resolve) => setTimeout(resolve, ms)));\n\t\tthis.maxAttempts = options.maxAttempts ?? 4;\n\t\tthis.authorization = `Bearer ${options.credential.token}`;\n\t}\n\n\t/** The records of one name and type — empty when there are none. */\n\tasync getRecordSet(\n\t\tdomain: string,\n\t\ttype: GoDaddyRecordType,\n\t\tname: string,\n\t): Promise<GoDaddyRecord[]> {\n\t\tthis.guard(domain, type, name);\n\t\tconst records = await this.request<GoDaddyRecord[]>(\n\t\t\t'GET',\n\t\t\tdomain,\n\t\t\tthis.recordPath(domain, type, name),\n\t\t);\n\t\treturn Array.isArray(records) ? records : [];\n\t}\n\n\t/** Replace one name's records of one type with `values`. */\n\tasync replaceRecordSet(\n\t\tdomain: string,\n\t\ttype: GoDaddyRecordType,\n\t\tname: string,\n\t\tvalues: readonly string[],\n\t\tttl: number,\n\t): Promise<void> {\n\t\tthis.guard(domain, type, name);\n\t\tawait this.request(\n\t\t\t'PUT',\n\t\t\tdomain,\n\t\t\tthis.recordPath(domain, type, name),\n\t\t\tvalues.map((data) => ({\n\t\t\t\tdata,\n\t\t\t\tttl: Math.max(ttl, GODADDY_MIN_TTL),\n\t\t\t})),\n\t\t);\n\t}\n\n\t/** Delete one name's records of one type. */\n\tasync deleteRecordSet(\n\t\tdomain: string,\n\t\ttype: GoDaddyRecordType,\n\t\tname: string,\n\t): Promise<void> {\n\t\tthis.guard(domain, type, name);\n\t\tawait this.request('DELETE', domain, this.recordPath(domain, type, name));\n\t}\n\n\tprivate recordPath(domain: string, type: string, name: string): string {\n\t\treturn `/v1/domains/${encodeURIComponent(domain)}/records/${type}/${encodeURIComponent(name)}`;\n\t}\n\n\t/** Only A, AAAA and CNAME, at a real record name. */\n\tprivate guard(domain: string, type: string, name: string): void {\n\t\tif (!(GODADDY_MANAGED_TYPES as readonly string[]).includes(type)) {\n\t\t\tthrow new GoDaddyRecordNotAllowed(\n\t\t\t\tdomain,\n\t\t\t\ttype,\n\t\t\t\tname,\n\t\t\t\t'it is not a type gkm manages',\n\t\t\t);\n\t\t}\n\t\tif (!isRecordName(name)) {\n\t\t\tthrow new GoDaddyRecordNotAllowed(\n\t\t\t\tdomain,\n\t\t\t\ttype,\n\t\t\t\tname,\n\t\t\t\t'it is not a record name relative to the domain',\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async request<T = unknown>(\n\t\tmethod: 'GET' | 'PUT' | 'DELETE',\n\t\tdomain: string,\n\t\tpath: string,\n\t\tbody?: unknown,\n\t): Promise<T> {\n\t\tlet retryAfterSec: number | undefined;\n\t\tfor (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n\t\t\tconst response = await fetch(`${this.baseUrl}${path}`, {\n\t\t\t\tmethod,\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: this.authorization,\n\t\t\t\t\tAccept: 'application/json',\n\t\t\t\t\t...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n\t\t\t\t},\n\t\t\t\t...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n\t\t\t});\n\n\t\t\tif (response.ok) {\n\t\t\t\tif (method === 'GET') this.readSucceeded = true;\n\t\t\t\tif (response.status === 204) return undefined as T;\n\t\t\t\tconst text = await response.text();\n\t\t\t\treturn (text ? JSON.parse(text) : undefined) as T;\n\t\t\t}\n\n\t\t\tconst error = await errorBody(response);\n\t\t\tif (response.status === 504 && attempt < this.maxAttempts) {\n\t\t\t\tawait this.sleep(Math.min(2 ** attempt * 1000, 30_000));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (response.status === 429) {\n\t\t\t\tretryAfterSec = error.retryAfterSec;\n\t\t\t\tif (attempt === this.maxAttempts) break;\n\t\t\t\t// GoDaddy says how long; without it, back off exponentially.\n\t\t\t\tconst waitMs =\n\t\t\t\t\tretryAfterSec !== undefined\n\t\t\t\t\t\t? Math.min(retryAfterSec, 60) * 1000\n\t\t\t\t\t\t: Math.min(2 ** attempt * 1000, 60_000);\n\t\t\t\tawait this.sleep(waitMs);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (response.status === 401) {\n\t\t\t\tthrow new GoDaddyCredentialsInvalid(error.code);\n\t\t\t}\n\t\t\tif (response.status === 403) {\n\t\t\t\t// The account restriction says ACCESS_DENIED; a scoped token that\n\t\t\t\t// may not make this call says so, or — after a read went\n\t\t\t\t// through — can only be that.\n\t\t\t\tconst scoped =\n\t\t\t\t\t/scope/i.test(`${error.code ?? ''} ${error.message ?? ''}`) ||\n\t\t\t\t\t(method !== 'GET' && this.readSucceeded);\n\t\t\t\tif (scoped) {\n\t\t\t\t\tthrow new GoDaddyScopeMissing(\n\t\t\t\t\t\tmethod,\n\t\t\t\t\t\tdomain,\n\t\t\t\t\t\tmethod === 'GET' ? 'DNS records read' : 'domains.dns:update',\n\t\t\t\t\t\terror.message ?? error.code,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthrow new GoDaddyApiAccessDenied(domain, error.message ?? error.code);\n\t\t\t}\n\t\t\tif (response.status === 404) {\n\t\t\t\tthrow new GoDaddyDomainNotFound(domain, error.code);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tresponse.status === 422 &&\n\t\t\t\t/domain/i.test(error.code ?? '') &&\n\t\t\t\t!/record/i.test(`${error.code ?? ''} ${error.message ?? ''}`)\n\t\t\t) {\n\t\t\t\tthrow new GoDaddyDomainNotFound(domain, error.code);\n\t\t\t}\n\t\t\tthrow new GoDaddyRequestFailed(\n\t\t\t\tmethod,\n\t\t\t\tpath,\n\t\t\t\tresponse.status,\n\t\t\t\terror.code,\n\t\t\t\terror.message,\n\t\t\t);\n\t\t}\n\t\tthrow new GoDaddyRateLimited(this.maxAttempts, retryAfterSec);\n\t}\n}\n\nasync function errorBody(response: Response): Promise<GoDaddyErrorBody> {\n\ttry {\n\t\tconst parsed = (await response.json()) as GoDaddyErrorBody;\n\t\treturn parsed && typeof parsed === 'object' ? parsed : {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n","/**\n * GoDaddy DNS Provider\n *\n * Implements DnsProvider against GoDaddy's v1 API, one record set — a name\n * and a type — at a time: it reads and writes only the A, AAAA and CNAME\n * records of the names it is handed, and never the zone as a whole, a domain\n * or the account. A Personal Access Token scoped to `domains.dns:update` is all it needs.\n *\n * A token that may write records and not read them puts the provider in\n * write-only mode: every record is PUT — idempotent, so one that already has\n * its value is left as it was — and nothing is compared or deleted.\n *\n * Credentials: `GODADDY_API_TOKEN`, else what `gkm login --provider godaddy`\n * stored. Never logged.\n */\n\nimport {\n\ttype GoDaddyCredential,\n\tMissingCredential,\n\tstoredCredentials,\n} from '../../../deploy/credentials';\nimport {\n\ttype DeleteDnsRecord,\n\ttype DeleteResult,\n\ttype DnsProvider,\n\ttype DnsRecord,\n\tDnsRecordsUnreadable,\n\ttype UpsertDnsRecord,\n\ttype UpsertResult,\n} from './DnsProvider';\nimport {\n\tGODADDY_MANAGED_TYPES,\n\tGODADDY_MIN_TTL,\n\tGoDaddyApi,\n\tGoDaddyApiAccessDenied,\n\ttype GoDaddyApiOptions,\n\tGoDaddyDomainNotFound,\n\ttype GoDaddyRecord,\n\tGoDaddyRecordNotAllowed,\n\ttype GoDaddyRecordType,\n\tGoDaddyScopeMissing,\n} from './godaddy-api';\n\nexport interface GoDaddyProviderOptions {\n\t/** The token, when the caller already has it. */\n\tcredential?: GoDaddyCredential;\n\t/** Where the variables are read — `process.env` by default. */\n\tenv?: NodeJS.ProcessEnv;\n\t/** The CLI's home, whose `credentials.json` holds a stored login. */\n\thome?: string;\n\t/** The API's base URL, for tests. */\n\tbaseUrl?: string;\n\t/** How a 429 is waited out, for tests. */\n\tsleep?: GoDaddyApiOptions['sleep'];\n\tmaxAttempts?: number;\n\t/** Where the write-only notice goes — `console.log` by default. */\n\tlog?: (line: string) => void;\n}\n\n/** GoDaddy cannot list a zone through the records-by-name endpoints. */\nexport class GoDaddyZoneListingUnsupported extends Error {\n\tconstructor(readonly domain: string) {\n\t\tsuper(\n\t\t\t`gkm reads GoDaddy records by name and type only — it never lists ` +\n\t\t\t\t`${domain}'s whole zone, so a token scoped to DNS updates is enough. ` +\n\t\t\t\t'Use readRecords(domain, [{ name, type }]) instead of getRecords.',\n\t\t);\n\t\tthis.name = 'GoDaddyZoneListingUnsupported';\n\t}\n}\n\n/** A value compared the way DNS does: case-insensitive, no trailing dot. */\nfunction normalize(value: string): string {\n\treturn value.trim().replace(/\\.$/, '').toLowerCase();\n}\n\nfunction managed(type: string): type is GoDaddyRecordType {\n\treturn (GODADDY_MANAGED_TYPES as readonly string[]).includes(type);\n}\n\n/** A read GoDaddy refused: write-only, rather than a failure. */\nfunction readDenied(error: unknown): boolean {\n\treturn (\n\t\terror instanceof GoDaddyScopeMissing ||\n\t\terror instanceof GoDaddyApiAccessDenied\n\t);\n}\n\nexport class GoDaddyProvider implements DnsProvider {\n\treadonly name = 'godaddy';\n\tprivate api: GoDaddyApi | null = null;\n\t/** Set once a read is refused: every write is then a blind PUT. */\n\tprivate writeOnly = false;\n\n\tconstructor(private readonly options: GoDaddyProviderOptions = {}) {}\n\n\t/** Whether the token turned out unable to read records. */\n\tget readsDenied(): boolean {\n\t\treturn this.writeOnly;\n\t}\n\n\tprivate async getApi(): Promise<GoDaddyApi> {\n\t\tif (this.api) return this.api;\n\t\tconst credential =\n\t\t\tthis.options.credential ??\n\t\t\t(await storedCredentials({\n\t\t\t\tenv: this.options.env ?? process.env,\n\t\t\t\t...(this.options.home ? { home: this.options.home } : {}),\n\t\t\t}).get({ kind: 'godaddy' }));\n\t\tif (!credential) throw new MissingCredential('godaddy', undefined);\n\t\tthis.api = new GoDaddyApi({\n\t\t\tcredential,\n\t\t\t...(this.options.baseUrl ? { baseUrl: this.options.baseUrl } : {}),\n\t\t\t...(this.options.sleep ? { sleep: this.options.sleep } : {}),\n\t\t\t...(this.options.maxAttempts\n\t\t\t\t? { maxAttempts: this.options.maxAttempts }\n\t\t\t\t: {}),\n\t\t});\n\t\treturn this.api;\n\t}\n\n\tprivate assertManaged(domain: string, type: string, name: string): void {\n\t\tif (!managed(type)) {\n\t\t\tthrow new GoDaddyRecordNotAllowed(\n\t\t\t\tdomain,\n\t\t\t\ttype,\n\t\t\t\tname,\n\t\t\t\t'it is not a type gkm manages',\n\t\t\t);\n\t\t}\n\t}\n\n\t/** Never: the whole zone is not read. See {@link GoDaddyZoneListingUnsupported}. */\n\tasync getRecords(domain: string): Promise<DnsRecord[]> {\n\t\tthrow new GoDaddyZoneListingUnsupported(domain);\n\t}\n\n\t/**\n\t * The records of exactly these names and types, one request each.\n\t *\n\t * @throws {DnsRecordsUnreadable} when the token may not read records\n\t */\n\tasync readRecords(\n\t\tdomain: string,\n\t\twanted: readonly DeleteDnsRecord[],\n\t): Promise<DnsRecord[]> {\n\t\tfor (const { name, type } of wanted) this.assertManaged(domain, type, name);\n\t\tconst api = await this.getApi();\n\t\tconst found: DnsRecord[] = [];\n\t\tfor (const { name, type } of wanted) {\n\t\t\tlet records: GoDaddyRecord[];\n\t\t\ttry {\n\t\t\t\trecords = await api.getRecordSet(\n\t\t\t\t\tdomain,\n\t\t\t\t\ttype as GoDaddyRecordType,\n\t\t\t\t\tname,\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tif (!readDenied(error)) throw error;\n\t\t\t\tthis.writeOnly = true;\n\t\t\t\tthrow new DnsRecordsUnreadable(\n\t\t\t\t\tthis.name,\n\t\t\t\t\tdomain,\n\t\t\t\t\t(error as Error).name,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (records.length === 0) continue;\n\t\t\tfound.push({\n\t\t\t\tname,\n\t\t\t\ttype,\n\t\t\t\tttl: records[0]!.ttl ?? GODADDY_MIN_TTL,\n\t\t\t\tvalues: records.map((r) => r.data),\n\t\t\t});\n\t\t}\n\t\treturn found;\n\t}\n\n\t/**\n\t * Each record set to exactly its one value: read it, and write it only\n\t * when it differs — or, with a token that cannot read, write it. Only the\n\t * name and type of each record handed in is touched.\n\t */\n\tasync upsertRecords(\n\t\tdomain: string,\n\t\trecords: UpsertDnsRecord[],\n\t): Promise<UpsertResult[]> {\n\t\t// Every record is checked before any is written, so a refused one\n\t\t// leaves the zone as it was.\n\t\tfor (const record of records) {\n\t\t\tthis.assertManaged(domain, record.type, record.name);\n\t\t}\n\t\tconst api = await this.getApi();\n\n\t\tconst results: UpsertResult[] = [];\n\t\tfor (const record of records) {\n\t\t\tconst type = record.type as GoDaddyRecordType;\n\t\t\tlet existing: GoDaddyRecord[] | undefined;\n\t\t\tif (!this.writeOnly) {\n\t\t\t\ttry {\n\t\t\t\t\texisting = await api.getRecordSet(domain, type, record.name);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!readDenied(error)) throw error;\n\t\t\t\t\tthis.writeOnly = true;\n\t\t\t\t\t(this.options.log ?? console.log)(\n\t\t\t\t\t\t` ℹ The GoDaddy token cannot read ${domain}'s DNS records, so changes cannot be diffed: writing each record (idempotent).`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (existing) {\n\t\t\t\tconst values = existing.map((r) => normalize(r.data));\n\t\t\t\tif (values.length === 1 && values[0] === normalize(record.value)) {\n\t\t\t\t\tresults.push({ record, created: false, unchanged: true });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait api.replaceRecordSet(\n\t\t\t\tdomain,\n\t\t\t\ttype,\n\t\t\t\trecord.name,\n\t\t\t\t[record.value],\n\t\t\t\tMath.max(record.ttl, GODADDY_MIN_TTL),\n\t\t\t);\n\t\t\tresults.push({\n\t\t\t\trecord,\n\t\t\t\tcreated: existing !== undefined && existing.length === 0,\n\t\t\t\tunchanged: false,\n\t\t\t});\n\t\t}\n\t\treturn results;\n\t}\n\n\tasync deleteRecords(\n\t\tdomain: string,\n\t\trecords: DeleteDnsRecord[],\n\t): Promise<DeleteResult[]> {\n\t\tfor (const record of records) {\n\t\t\tthis.assertManaged(domain, record.type, record.name);\n\t\t}\n\t\tconst api = await this.getApi();\n\t\tconst results: DeleteResult[] = [];\n\t\tfor (const record of records) {\n\t\t\tconst type = record.type as GoDaddyRecordType;\n\t\t\tif (!this.writeOnly) {\n\t\t\t\tlet existing: GoDaddyRecord[] | undefined;\n\t\t\t\ttry {\n\t\t\t\t\texisting = await api.getRecordSet(domain, type, record.name);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!readDenied(error)) throw error;\n\t\t\t\t\tthis.writeOnly = true;\n\t\t\t\t}\n\t\t\t\tif (existing && existing.length === 0) {\n\t\t\t\t\tresults.push({ record, deleted: false, notFound: true });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait api.deleteRecordSet(domain, type, record.name);\n\t\t\t} catch (error) {\n\t\t\t\t// Write-only, nothing was read: a record that is not there is a 404.\n\t\t\t\tif (this.writeOnly && error instanceof GoDaddyDomainNotFound) {\n\t\t\t\t\tresults.push({ record, deleted: false, notFound: true });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tresults.push({ record, deleted: true, notFound: false });\n\t\t}\n\t\treturn results;\n\t}\n}\n"],"mappings":"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"}
|