@aoxborrow/registrar-client 0.8.0 → 0.9.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.
package/README.md CHANGED
@@ -43,18 +43,19 @@ npm install @aoxborrow/registrar-client
43
43
 
44
44
  ## Providers
45
45
 
46
- | id | Provider | Auth | Sandbox | Notes |
47
- | ------------ | ---------- | -------------------------- | ------- | -------------------------------------------- |
48
- | `cloudflare` | Cloudflare | API token + Account ID | — | manages existing domains only |
49
- | `dynadot` | Dynadot | API key | ✓ | `api-sandbox.dynadot.com`; key in query |
50
- | `gandi` | Gandi.net | API key | ✓ | `api.sandbox.gandi.net` |
51
- | `godaddy` | GoDaddy | PAT, or key + secret | ✓ | hybrid v3/v1; sandbox = OTE (v1 only) |
52
- | `namebright` | NameBright | client ID + secret | — | OAuth2 bearer; production-only |
53
- | `namecheap` | Namecheap | username + key + client IP | ✓ | XML API; IP allowlisting required |
54
- | `namecom` | Name.com | username + API token | ✓ | Core v1; separate sandbox host and token |
55
- | `namesilo` | NameSilo | API key | ✓ | JSON/XML API; key sent in query string |
56
- | `porkbun` | Porkbun | key + secret | ✓ | sandbox via `pk1_sb_` key; per-domain opt-in |
57
- | `spaceship` | Spaceship | key + secret | — | |
46
+ | id | Provider | Auth | Sandbox | Notes |
47
+ | ------------ | ---------- | -------------------------- | ------- | ------------------------------------------------- |
48
+ | `101domain` | 101domain | Bearer API key | — | Portfolio, DNS, nameservers, permanent forwarding |
49
+ | `cloudflare` | Cloudflare | API token + Account ID | — | manages existing domains only |
50
+ | `dynadot` | Dynadot | API key | ✓ | `api-sandbox.dynadot.com`; key in query |
51
+ | `gandi` | Gandi.net | API key | ✓ | `api.sandbox.gandi.net` |
52
+ | `godaddy` | GoDaddy | PAT, or key + secret | ✓ | hybrid v3/v1; sandbox = OTE (v1 only) |
53
+ | `namebright` | NameBright | client ID + secret | — | OAuth2 bearer; production-only |
54
+ | `namecheap` | Namecheap | username + key + client IP | ✓ | XML API; IP allowlisting required |
55
+ | `namecom` | Name.com | username + API token | ✓ | Core v1; separate sandbox host and token |
56
+ | `namesilo` | NameSilo | API key | ✓ | JSON/XML API; key sent in query string |
57
+ | `porkbun` | Porkbun | key + secret | ✓ | sandbox via `pk1_sb_` key; per-domain opt-in |
58
+ | `spaceship` | Spaceship | key + secret | — | |
58
59
 
59
60
  Each provider class exposes static discovery metadata — `displayName`,
60
61
  `website` (its public domain, e.g. `gandi.net`), `configFields` (the credential
@@ -162,39 +163,44 @@ are the guaranteed contract; **extended** methods are opt-in per provider.
162
163
  **Legend:** ✓ implemented · ✗ not available via the provider's API (throws
163
164
  `NotImplementedError`) · a superscript marks a caveat noted below.
164
165
 
165
- | Core method | CF | DY | GA | GD | NB | NC | NS | PB | SP | NM |
166
- | ------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
167
- | `testConnection` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
168
- | `listDomains` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
169
- | `getDomain` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
170
- | `checkAvailability` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
171
- | `getPricing` | ✓ | ✓ᵃ | ✓ | ✓ᵃ | ✗ᵇ | ✓ | ✓ | ✓ | ✗ᵇ | ✓ |
172
- | `registerDomain` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
173
- | `renewDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
174
- | `setAutoRenew` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
175
- | `transferIn` | ✗ᶜ | ✓ | ✓ | ✓ | ✗ᵈ | ✓ | ✓ | ✓ | ✓ | ✓ |
176
- | `updateNameservers` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
177
- | `getNameservers` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
178
- | `lockDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ |
179
- | `unlockDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ |
180
- | `setPrivacy` | ✓ | ✓ | ✓ᶠ | ✓ᵍ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ |
181
- | `getContacts` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ |
182
- | `updateContacts` | ✗ᶜ | ✓ | ✓ | ✓ | ✗ᵈ | ✓ | ✓ | ✓ | ✓ | ✓ |
183
- | `getDnsRecords` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
184
- | `setDnsRecords` | ✓ | ✓ʰ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ʰ | ✓ |
185
-
186
- | Extended method | CF | DY | GA | GD | NB | NC | NS | PB | SP | NM |
187
- | --------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
188
- | `getAuthCode` | ✗ | ✓ | ✓ | ✓ | ✓ | ✗ⁱ | ✗ⁱ | ✗ | ✓ | ✓ |
189
- | `getDnssec` | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ᵐ |
190
- | `disableDnssec` | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ᵐ |
191
- | `getEmailForwarding` | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ᵐ |
192
- | `setEmailForwarding` | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ᵐ |
193
- | `getDomainForwarding` | ✓ | ✓ʲ | ✓ᵏ | ✓ˡ | ✗ | ✓ | ✓ʲ | ✓ | ✗ | ✗ᵐ |
194
- | `setDomainForwarding` | ✓ | ✓ʲ | ✓ᵏ | ✓ˡ | ✗ | ✓ | ✓ʲ | ✓ | ✗ | ✗ᵐ |
166
+ | Core method | CF | DY | GA | GD | NB | NC | NS | PB | SP | NM | 101 |
167
+ | ------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
168
+ | `testConnection` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
169
+ | `listDomains` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
170
+ | `getDomain` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
171
+ | `checkAvailability` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
172
+ | `getPricing` | ✓ | ✓ᵃ | ✓ | ✓ᵃ | ✗ᵇ | ✓ | ✓ | ✓ | ✗ᵇ | ✓ | ✓ |
173
+ | `registerDomain` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
174
+ | `renewDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
175
+ | `setAutoRenew` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
176
+ | `transferIn` | ✗ᶜ | ✓ | ✓ | ✓ | ✗ᵈ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
177
+ | `updateNameservers` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
178
+ | `getNameservers` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
179
+ | `lockDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ | ✗ |
180
+ | `unlockDomain` | ✗ᶜ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ | ✗ |
181
+ | `setPrivacy` | ✓ | ✓ | ✓ᶠ | ✓ᵍ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ | ✗ |
182
+ | `getContacts` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ᵉ | ✓ | ✓ | ✗ |
183
+ | `updateContacts` | ✗ᶜ | ✓ | ✓ | ✓ | ✗ᵈ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
184
+ | `getDnsRecords` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
185
+ | `setDnsRecords` | ✓ | ✓ʰ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ʰ | ✓ | ✓ |
186
+
187
+ | Extended method | CF | DY | GA | GD | NB | NC | NS | PB | SP | NM | 101 |
188
+ | --------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
189
+ | `getAuthCode` | ✗ | ✓ | ✓ | ✓ | ✓ | ✗ⁱ | ✗ⁱ | ✗ | ✓ | ✓ | ✗ |
190
+ | `getDnssec` | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ᵐ | ✗ |
191
+ | `disableDnssec` | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ᵐ | ✗ |
192
+ | `getEmailForwarding` | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ᵐ | ✗ |
193
+ | `setEmailForwarding` | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ᵐ | ✗ |
194
+ | `getDomainForwarding` | ✓ | ✓ʲ | ✓ᵏ | ✓ˡ | ✗ | ✓ | ✓ʲ | ✓ | ✗ | ✗ᵐ | ✓ |
195
+ | `setDomainForwarding` | ✓ | ✓ʲ | ✓ᵏ | ✓ˡ | ✗ | ✓ | ✓ʲ | ✓ | ✗ | ✗ᵐ | ✓ |
195
196
 
196
197
  `CF` Cloudflare · `DY` Dynadot · `GA` Gandi · `GD` GoDaddy · `NB` NameBright ·
197
- `NC` Namecheap · `NS` NameSilo · `PB` Porkbun · `SP` Spaceship · `NM` Name.com.
198
+ `NC` Namecheap · `NS` NameSilo · `PB` Porkbun · `SP` Spaceship · `NM` Name.com · `101` 101domain.
199
+
200
+ 101domain API 1.1.0 supports portfolio/search/pricing reads, DNS and nameserver
201
+ writes, and permanent apex URL forwarding. Its unimplemented core methods throw
202
+ `NotImplementedError`; the inherited core feature list is the library contract,
203
+ not a claim of available API endpoints. See [101domain](docs/registrars/101domain.md).
198
204
 
199
205
  **Caveats**
200
206
 
@@ -419,6 +425,35 @@ sandbox (Name.com offers no domain deletion/reset there); it is excluded from th
419
425
  default offline suite. Transfer completion and production behavior need separate
420
426
  verification; sandbox transfers are not deterministic.
421
427
 
428
+ ## DNS record syntax
429
+
430
+ Pure functions for checking DNS record syntax and putting records in one
431
+ canonical form, with no network calls, so a UI can validate what someone types
432
+ before it reaches a registrar.
433
+
434
+ ```ts
435
+ import { findCnameConflicts, prepareEntry, toDnsEntry } from '@aoxborrow/registrar-client';
436
+
437
+ // throws DnsSyntaxError with a message safe to show a person
438
+ prepareEntry(toDnsEntry({ type: 'MX', name: '@', value: 'Mail.Example.net.', priority: 10 }));
439
+ // → { owner: '@', kind: 'MX', ttl: 3600, rdata: '10 mail.example.net' }
440
+
441
+ findCnameConflicts(records.map(r => toDnsEntry(r))); // [{ owner, kind, detail }]
442
+ ```
443
+
444
+ - Names are folded to lowercase with one trailing dot removed, and are never
445
+ joined to a zone: `www` and `www.example.com` are different owners, and `@`
446
+ stays `@`. Underscore labels (`_dmarc`) and one leftmost `*` are allowed.
447
+ - Data syntax is checked for A, AAAA, CNAME, NS, MX (including null MX), TXT,
448
+ SRV, CAA and DS. Any other type is trimmed and passed through, so a
449
+ provider-specific type still round-trips.
450
+ - `findCnameConflicts` and `findRepeatedRecords` check a whole set of records.
451
+ - `toDnsEntry` adapts a `DnsRecord` (separate MX/SRV number fields) to the
452
+ entry shape the checks take.
453
+
454
+ These are DNS rules only. Each provider still applies its own limits, such as
455
+ a minimum TTL or the record types it accepts.
456
+
422
457
  ## Sandbox environments
423
458
 
424
459
  Providers that offer a test environment accept `{ environment: 'sandbox' }` at