@fwgapps/namecheap 0.6.0 → 1.0.0
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 +314 -60
- package/dist/index.cjs +1660 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1211 -954
- package/dist/index.d.ts +1211 -954
- package/dist/index.js +1561 -1
- package/dist/index.js.map +1 -1
- package/package.json +31 -26
- package/dist/index.global.js +0 -5
- package/dist/index.global.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,98 +1,352 @@
|
|
|
1
1
|
# @fwgapps/namecheap
|
|
2
2
|
|
|
3
|
-
<!-- STATUS -->
|
|
4
3
|
[](https://github.com/fwgapps/namecheap/actions/workflows/publish.yml)
|
|
5
4
|
[](https://codecov.io/gh/fwgapps/namecheap)
|
|
6
|
-

|
|
7
|
-
|
|
8
|
-
<!-- NPM -->
|
|
9
5
|
[](https://www.npmjs.com/package/@fwgapps/namecheap)
|
|
10
|
-

|
|
11
|
-
[](https://bundlephobia.com/result?p=@fwgapps/namecheap)
|
|
12
|
-
[](https://libraries.io/npm/@fwgapps/namecheap)
|
|
13
|
-
|
|
14
|
-
<!-- META -->
|
|
15
6
|

|
|
16
7
|

|
|
17
|
-

|
|
18
|
-

|
|
19
|
-
[](http://commitizen.github.io/cz-cli/)
|
|
20
8
|
|
|
21
|
-
A
|
|
9
|
+
A typed, zero-dependency client for the [Namecheap XML API](https://www.namecheap.com/support/api/intro/). Every command returns a plain, fully typed object instead of raw XML.
|
|
10
|
+
|
|
11
|
+
> Upgrading from 0.x? Read [MIGRATION.md](./MIGRATION.md). Version 1.0 is a complete rewrite and is not backwards compatible.
|
|
22
12
|
|
|
23
|
-
## Table of
|
|
13
|
+
## Table of contents
|
|
24
14
|
|
|
25
|
-
- [Description](#description)
|
|
26
15
|
- [Features](#features)
|
|
27
16
|
- [Installation](#installation)
|
|
17
|
+
- [Quick start](#quick-start)
|
|
18
|
+
- [Configuration](#configuration)
|
|
28
19
|
- [Usage](#usage)
|
|
20
|
+
- [Using a single command (tree shaking)](#using-a-single-command-tree-shaking)
|
|
21
|
+
- [Error handling](#error-handling)
|
|
22
|
+
- [Safety notes](#safety-notes)
|
|
23
|
+
- [Testing with a fake fetch](#testing-with-a-fake-fetch)
|
|
24
|
+
- [Known gaps](#known-gaps)
|
|
29
25
|
- [Examples](#examples)
|
|
30
|
-
- [
|
|
31
|
-
- [
|
|
32
|
-
- [
|
|
33
|
-
- [License](#license)
|
|
34
|
-
- [Contributing](#contributing)
|
|
35
|
-
|
|
36
|
-
## Description
|
|
37
|
-
A lightweight and developer-friendly TypeScript client for the Namecheap API. Designed for both Node.js and browser environments, it provides full type safety with comprehensive TypeScript definitions. This library simplifies and automates domain management tasks, enabling developers to integrate Namecheap's services seamlessly into their applications.
|
|
26
|
+
- [API coverage](#api-coverage)
|
|
27
|
+
- [Contributing and license](#contributing-and-license)
|
|
28
|
+
- [Attribution](#attribution)
|
|
38
29
|
|
|
39
30
|
## Features
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
|
|
32
|
+
- Fully typed parameters and results for 59 Namecheap commands.
|
|
33
|
+
- Zero runtime dependencies: the XML parser is built in (no DTD or external entity support).
|
|
34
|
+
- ESM and CommonJS builds with bundled type declarations.
|
|
35
|
+
- Tree-shakeable: import just the commands you use (see [Using a single command](#using-a-single-command-tree-shaking)).
|
|
36
|
+
- Node.js >= 20 and edge runtimes that provide `fetch` (Cloudflare Workers, Deno, Bun, ...).
|
|
37
|
+
- No automatic retries and no logging.
|
|
38
|
+
- **No browser support, on purpose.** The API key must never reach a browser, and Namecheap only accepts requests from an allow-listed server IP. Call this library from your backend.
|
|
45
39
|
|
|
46
40
|
## Installation
|
|
47
|
-
You can install the library via npm or yarn:
|
|
48
41
|
|
|
49
|
-
### Using npm
|
|
50
42
|
```bash
|
|
51
43
|
npm install @fwgapps/namecheap
|
|
44
|
+
# or
|
|
45
|
+
yarn add @fwgapps/namecheap
|
|
52
46
|
```
|
|
53
47
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
## Quick start
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { Namecheap } from "@fwgapps/namecheap";
|
|
52
|
+
|
|
53
|
+
const nc = new Namecheap({
|
|
54
|
+
apiUser: "your-api-user",
|
|
55
|
+
apiKey: process.env.NAMECHEAP_API_KEY ?? "",
|
|
56
|
+
clientIp: "203.0.113.10", // the public IP you whitelisted at Namecheap
|
|
57
|
+
sandbox: true, // use the sandbox while you experiment
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const { domains, paging } = await nc.domains.getList({ pageSize: 20 });
|
|
61
|
+
console.log(paging.totalItems, domains.map((d) => d.name));
|
|
62
|
+
|
|
63
|
+
const results = await nc.domains.check({ domainList: "example.com,example.net" });
|
|
64
|
+
console.log(results.map((r) => `${r.domain}: ${r.available}`));
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`Namecheap` is both the default export and a named export.
|
|
68
|
+
|
|
69
|
+
## Configuration
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const nc = new Namecheap({
|
|
73
|
+
apiUser: "your-api-user", // string, required: your API user name
|
|
74
|
+
apiKey: "your-api-key", // string, required: your API key
|
|
75
|
+
clientIp: "203.0.113.10", // string, required: the whitelisted IP the requests come from
|
|
76
|
+
userName: "account-name", // string, optional: the account to act on, defaults to apiUser
|
|
77
|
+
sandbox: true, // boolean, optional: defaults to false (PRODUCTION)
|
|
78
|
+
fetch: globalThis.fetch, // optional: your own fetch implementation
|
|
79
|
+
timeoutMs: 15_000, // number, optional: abort a request after this many milliseconds
|
|
80
|
+
});
|
|
57
81
|
```
|
|
58
82
|
|
|
59
|
-
|
|
83
|
+
| Field | Type | Default | Notes |
|
|
84
|
+
| ----------- | --------------------- | ------------------ | --------------------------------------------------------------------------------------- |
|
|
85
|
+
| `apiUser` | `string` | required | Sent as `ApiUser`. |
|
|
86
|
+
| `apiKey` | `string` | required | Sent as `ApiKey`, in the POST body only. |
|
|
87
|
+
| `clientIp` | `string` | required | Sent as `ClientIp`. Must match an IP on your Namecheap API whitelist. |
|
|
88
|
+
| `userName` | `string` | `apiUser` | Sent as `UserName`. Use it when acting on a different account than the API user. |
|
|
89
|
+
| `sandbox` | `boolean` | `false` | Must be a boolean. `true` talks to `api.sandbox.namecheap.com`; `false` or omitted talks to **production**. Any other value throws a `TypeError`. |
|
|
90
|
+
| `fetch` | `typeof fetch` | `globalThis.fetch` | Inject a custom or fake `fetch` (tests, proxies, edge runtimes). |
|
|
91
|
+
| `timeoutMs` | `number` | no timeout | Implemented with `AbortSignal.timeout`; a timeout surfaces as a `NamecheapHttpError`. |
|
|
60
92
|
|
|
61
|
-
|
|
93
|
+
> **WARNING: `sandbox` defaults to `false`, which means PRODUCTION.** Forgetting it sends real, billed commands (registrations, renewals, transfers) and changes real DNS. Set `sandbox: true` explicitly while developing. `sandbox` must be a real boolean: a string such as `"true"` throws a `TypeError` at construction instead of silently selecting production, so convert environment variables yourself (`sandbox: process.env.NAMECHEAP_SANDBOX === "true"`).
|
|
62
94
|
|
|
63
|
-
|
|
95
|
+
> **IP whitelist.** Namecheap rejects requests from IP addresses that are not on your API whitelist, in the sandbox and in production. Enable API access and add your server's public IP in the Namecheap dashboard (Profile, Tools, Namecheap API Access), and pass the same address as `clientIp`.
|
|
64
96
|
|
|
65
|
-
|
|
66
|
-
|
|
97
|
+
## Usage
|
|
98
|
+
|
|
99
|
+
Every group is a property of the client, and every method takes a single params object. Optional parameters can be left out; a method with only optional parameters can be called with no argument.
|
|
100
|
+
|
|
101
|
+
The snippets below assume `nc` is the client from the [Quick start](#quick-start).
|
|
102
|
+
|
|
103
|
+
### domains
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
const { domains, paging } = await nc.domains.getList({ listType: "EXPIRING", page: 1, pageSize: 50 });
|
|
107
|
+
const availability = await nc.domains.check({ domainList: "example.com,example.org" });
|
|
108
|
+
const info = await nc.domains.getInfo({ domainName: "example.com" });
|
|
109
|
+
const lock = await nc.domains.getRegistrarLock({ domainName: "example.com" });
|
|
110
|
+
await nc.domains.setRegistrarLock({ domainName: "example.com", lockAction: "LOCK" });
|
|
111
|
+
const tlds = await nc.domains.getTldList();
|
|
112
|
+
console.log(domains.length, paging.totalItems, availability[0]?.available, info.domainName, lock.registrarLockStatus, tlds.length);
|
|
67
113
|
```
|
|
68
114
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
115
|
+
`domains.create`, `domains.renew`, `domains.reactivate` and `domains.setContacts` are billed or change ownership data; see the [API coverage](#api-coverage) table and the type definitions for their parameters.
|
|
116
|
+
|
|
117
|
+
### dns
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
const dnsList = await nc.dns.getList({ sld: "example", tld: "com" });
|
|
121
|
+
const current = await nc.dns.getHosts({ sld: "example", tld: "com" });
|
|
122
|
+
console.log(dnsList.nameservers, current.hosts.length);
|
|
123
|
+
|
|
124
|
+
// Replaces the WHOLE zone, see "Safety notes".
|
|
125
|
+
await nc.dns.setHosts({
|
|
126
|
+
sld: "example",
|
|
127
|
+
tld: "com",
|
|
128
|
+
emailType: "MX",
|
|
129
|
+
hosts: [
|
|
130
|
+
{ hostName: "@", recordType: "A", address: "203.0.113.5", ttl: 1800 },
|
|
131
|
+
{ hostName: "www", recordType: "CNAME", address: "example.com.", ttl: 1800 },
|
|
132
|
+
{ hostName: "@", recordType: "MX", address: "mail.example.com.", mxPref: 10 },
|
|
133
|
+
],
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
await nc.dns.setDefault({ sld: "example", tld: "com" });
|
|
137
|
+
await nc.dns.setCustom({ sld: "example", tld: "com", nameservers: "ns1.example.net,ns2.example.net" });
|
|
138
|
+
await nc.dns.setEmailForwarding({
|
|
139
|
+
domainName: "example.com",
|
|
140
|
+
forwards: [{ mailBox: "info", forwardTo: "me@example.net" }],
|
|
141
|
+
});
|
|
142
|
+
const forwarding = await nc.dns.getEmailForwarding({ domainName: "example.com" });
|
|
143
|
+
console.log(forwarding.forwards);
|
|
76
144
|
```
|
|
77
145
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
|
|
146
|
+
### ns
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
await nc.ns.create({ sld: "example", tld: "com", nameserver: "ns1.example.com", ip: "203.0.113.20" });
|
|
150
|
+
const ns = await nc.ns.getInfo({ sld: "example", tld: "com", nameserver: "ns1.example.com" });
|
|
151
|
+
await nc.ns.update({ sld: "example", tld: "com", nameserver: "ns1.example.com", oldIP: "203.0.113.20", ip: "203.0.113.21" });
|
|
152
|
+
await nc.ns.delete({ sld: "example", tld: "com", nameserver: "ns1.example.com" });
|
|
153
|
+
console.log(ns.ip);
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### transfer
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
const started = await nc.transfer.create({ domainName: "example.com", years: 1, eppCode: "the-epp-code" });
|
|
160
|
+
const status = await nc.transfer.getStatus({ transferID: started.transferID });
|
|
161
|
+
const { transfers } = await nc.transfer.getList({ listType: "INPROGRESS" });
|
|
162
|
+
await nc.transfer.updateStatus({ transferID: started.transferID, resubmit: true });
|
|
163
|
+
console.log(status.status, transfers.length);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### ssl
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
const csrInfo = await nc.ssl.parseCSR({ csr: "-----BEGIN CERTIFICATE REQUEST-----\n..." });
|
|
170
|
+
const { certificates } = await nc.ssl.getList({ listType: "Active" });
|
|
171
|
+
const emails = await nc.ssl.getApproverEmailList({ domainName: "example.com", certificateType: "PositiveSSL" });
|
|
172
|
+
const cert = await nc.ssl.getInfo({ certificateID: 12345 });
|
|
173
|
+
console.log(csrInfo.commonName, certificates.length, emails.genericEmails, cert.status);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Activation, reissue, renewal and purchase (`ssl.create`, `ssl.activate`, `ssl.reissue`, `ssl.renew`, `ssl.purchaseMoreSans`) are available too; see [Known gaps](#known-gaps) before relying on the activation flow.
|
|
177
|
+
|
|
178
|
+
### users
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
const balances = await nc.users.getBalances();
|
|
182
|
+
const pricing = await nc.users.getPricing({ productType: "DOMAIN", productCategory: "DOMAINS", actionName: "REGISTER", productName: "COM" });
|
|
183
|
+
const funds = await nc.users.createAddFundsRequest({ paymentType: "Creditcard", amount: 50, returnUrl: "https://example.com/funds-done" });
|
|
184
|
+
const fundsStatus = await nc.users.getAddFundsStatus({ tokenId: funds.tokenID });
|
|
185
|
+
console.log(balances.availableBalance, pricing.productTypes.length, fundsStatus.status);
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### usersAddress
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
const addresses = await nc.usersAddress.getList();
|
|
192
|
+
const first = addresses[0];
|
|
193
|
+
if (first) {
|
|
194
|
+
const address = await nc.usersAddress.getInfo({ addressId: first.addressId });
|
|
195
|
+
await nc.usersAddress.setDefault({ addressId: first.addressId });
|
|
196
|
+
console.log(address.addressName);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### whoisGuard
|
|
201
|
+
|
|
202
|
+
The client property is `whoisGuard`. The 0.x name `whoIsGuard` is gone; see the migration guide.
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
const { whoisguards } = await nc.whoisGuard.getList({ listType: "ALLOTED" });
|
|
206
|
+
const subscription = whoisguards[0];
|
|
207
|
+
if (subscription) {
|
|
208
|
+
await nc.whoisGuard.enable({ whoisguardID: subscription.id, forwardedToEmail: "me@example.net" });
|
|
209
|
+
await nc.whoisGuard.changeEmailAddress({ whoisguardID: subscription.id });
|
|
210
|
+
await nc.whoisGuard.disable({ whoisguardID: subscription.id });
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Using a single command (tree shaking)
|
|
215
|
+
|
|
216
|
+
`new Namecheap(...)` is the convenient entry point, but it carries all 59 commands, because the client object exposes every group. If you only need a few commands (a serverless function, an edge worker), import them one by one and run them with `run`. A bundler then keeps only what you use:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { createTransport, domainsCheck, run } from "@fwgapps/namecheap";
|
|
220
|
+
|
|
221
|
+
const send = createTransport({ apiUser: "user", apiKey: "key", clientIp: "203.0.113.10", sandbox: true });
|
|
222
|
+
|
|
223
|
+
const result = await run(domainsCheck, send, { domainList: "example.com,example.net" });
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Every command is also exported on its own, named `<group><Method>`: `domainsCheck`, `dnsSetHosts`, `nsDelete`, `transferGetList`, `sslGetList`, `sslParseCSR`, `usersGetBalances`, `usersAddressCreate`, `whoisGuardRenew`, and so on (the group is the same name you use on the client, with the method capitalized). `run` behaves exactly like the client methods: same validation, same errors, same typing of the parameters.
|
|
227
|
+
|
|
228
|
+
Approximate sizes of a minified bundle (esbuild, measured on this package):
|
|
229
|
+
|
|
230
|
+
| What you import | Minified | Gzip |
|
|
231
|
+
| ---------------------------------------------- | -------: | -----: |
|
|
232
|
+
| only the error classes | ~0.3 KB | ~0.2 KB |
|
|
233
|
+
| `createTransport` + one command + `run` | ~9.4 KB | ~3.8 KB |
|
|
234
|
+
| `createTransport` + two commands + `run` | ~9.9 KB | ~4.0 KB |
|
|
235
|
+
| the `Namecheap` class (any use of it) | ~29.6 KB | ~8.4 KB |
|
|
236
|
+
|
|
237
|
+
The package declares `"sideEffects": false`, and a test in this repository bundles a single-command consumer to make sure the other commands stay out of the bundle.
|
|
238
|
+
|
|
239
|
+
## Error handling
|
|
240
|
+
|
|
241
|
+
All API, HTTP and response failures are instances of one of three `Error` subclasses, exported from the package. Programmer or configuration mistakes (an invalid `sandbox`, `dns.setHosts` validation, serializer rejections, reserved parameter names) throw a plain `TypeError` instead.
|
|
242
|
+
|
|
243
|
+
| Class | Thrown when | Useful fields |
|
|
244
|
+
| ---------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------- |
|
|
245
|
+
| `NamecheapError` | The API answered with `Status="ERROR"`. | `code` (first error number), `errors` (all) |
|
|
246
|
+
| `NamecheapHttpError` | The request failed (network, timeout, redirect) or the HTTP status is not 2xx. | `status`, `statusText`, `cause` |
|
|
247
|
+
| `NamecheapParseError` | The body is not valid XML, is not a Namecheap envelope, or lacks a documented field. | `message`, `cause` |
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
import { Namecheap, NamecheapError, NamecheapHttpError, NamecheapParseError } from "@fwgapps/namecheap";
|
|
251
|
+
|
|
252
|
+
const nc = new Namecheap({ apiUser: "user", apiKey: "key", clientIp: "203.0.113.10", sandbox: true });
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
await nc.dns.getHosts({ sld: "example", tld: "com" });
|
|
256
|
+
} catch (error) {
|
|
257
|
+
if (error instanceof NamecheapError) {
|
|
258
|
+
console.error(error.code, error.message, error.errors);
|
|
259
|
+
} else if (error instanceof NamecheapHttpError) {
|
|
260
|
+
console.error(error.status, error.statusText);
|
|
261
|
+
} else if (error instanceof NamecheapParseError) {
|
|
262
|
+
console.error("Unexpected response shape:", error.message);
|
|
263
|
+
} else {
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Error messages never contain request data or credentials. Apart from `NamecheapError`, whose message is Namecheap's own error text, they contain at most short fragments of the response (element or attribute names, a truncated entity name).
|
|
270
|
+
|
|
271
|
+
**There are no automatic retries, on purpose.** Many commands are billed (register, renew, transfer, purchase). Retrying a request whose outcome is unknown could charge you twice. Decide per call whether a retry is safe; read-only commands such as `getList` or `check` usually are.
|
|
272
|
+
|
|
273
|
+
After a billed or account-changing command, a `NamecheapParseError` (Namecheap answered OK but the response could not be read) or a `timeoutMs` abort means the outcome is **unknown**: the action may have been performed. Reconcile with `getList` or `getInfo` before retrying.
|
|
274
|
+
|
|
275
|
+
**HTTP 405 means rate limiting.** Namecheap answers 405 when you exceed its request limits, so a `NamecheapHttpError` with `status === 405` is a signal to slow down, not a bug in your request.
|
|
276
|
+
|
|
277
|
+
## Safety notes
|
|
278
|
+
|
|
279
|
+
- `dns.setHosts` **replaces the whole zone**: every record you do not list is deleted. Read the current records with `dns.getHosts` first and send the complete desired list. The library rejects an empty `hosts` list with a `TypeError` before sending anything.
|
|
280
|
+
- `dns.setHosts` with `emailType` other than `MX`: the reference says MX records are silently discarded unless the resulting email mode is `MX`. Because `setHosts` replaces the whole zone, listing MX hosts under another mode loses your mail routing.
|
|
281
|
+
- Credentials travel in the POST body (`application/x-www-form-urlencoded`), never in the URL, so they do not end up in access logs or proxies that record URLs.
|
|
282
|
+
- The library never logs anything. Do not log the client config or error `cause` objects from your own code in production.
|
|
283
|
+
- `sandbox` defaults to production. See the [warning above](#configuration).
|
|
284
|
+
|
|
285
|
+
## Testing with a fake fetch
|
|
286
|
+
|
|
287
|
+
Pass your own `fetch` to test your code without network access or credentials:
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
import { Namecheap } from "@fwgapps/namecheap";
|
|
291
|
+
|
|
292
|
+
const xml = `<?xml version="1.0" encoding="utf-8"?>
|
|
293
|
+
<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
|
|
294
|
+
<Errors />
|
|
295
|
+
<RequestedCommand>namecheap.domains.dns.setDefault</RequestedCommand>
|
|
296
|
+
<CommandResponse Type="namecheap.domains.dns.setDefault">
|
|
297
|
+
<DomainDNSSetDefaultResult Domain="example.com" Updated="true" />
|
|
298
|
+
</CommandResponse>
|
|
299
|
+
</ApiResponse>`;
|
|
300
|
+
|
|
301
|
+
const calls: Array<{ url: string; body: string }> = [];
|
|
302
|
+
const fakeFetch: typeof fetch = async (input, init) => {
|
|
303
|
+
calls.push({ url: String(input), body: String(init?.body) });
|
|
304
|
+
return new Response(xml, { status: 200 });
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const nc = new Namecheap({ apiUser: "u", apiKey: "k", clientIp: "127.0.0.1", sandbox: true, fetch: fakeFetch });
|
|
308
|
+
const result = await nc.dns.setDefault({ sld: "example", tld: "com" });
|
|
309
|
+
console.log(result.updated, calls[0]?.url);
|
|
82
310
|
```
|
|
83
311
|
|
|
84
|
-
##
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
312
|
+
## Known gaps
|
|
313
|
+
|
|
314
|
+
1. `ssl.activate` and `ssl.reissue` do not expose domain control validation (DCV) parameters or the 0.6 OV/EV organisation option sets (organisation, department, admin address, company registration fields), because the API reference does not document them. Confirm the activation flow in the sandbox before relying on it.
|
|
315
|
+
2. `users.create`, `users.login`, `users.resetPassword`, `whoisGuard.renew`, `ssl.create`, `ssl.renew` and `ssl.purchaseMoreSans` have undocumented response shapes. They return loosely typed results parsed tolerantly: they never throw on an unexpected shape, and fields that cannot be read are simply absent.
|
|
316
|
+
3. `dns.setEmailForwarding` sends `MailBox<n>` as spelled in the API reference; the Go SDK sends lowercase. This is unverified against the live API.
|
|
317
|
+
4. CAA (`Flag`/`Tag`) records are not supported by `dns.setHosts`.
|
|
318
|
+
5. `ssl.getInfo` accepts `returnCertificate` and sends it, but 1.0 does not parse the certificate body (its response shape is undocumented), so the result never contains the certificate.
|
|
319
|
+
6. WhoisGuard `allot`, `unallot` and `discard` are not implemented.
|
|
320
|
+
7. `domains.create` no longer exposes `idnCode`, the billing contact and `extendedAttributes`, which 0.6 did. IDN registrations and some ccTLDs (such as .us, .ca, .eu) need them, and the API reference does not document them. Unknown extra keys still pass through the serializer, so you can try a workaround such as `nc.domains.create({ ...params, ExtendedAttributes: "..." } as never)`, unverified against the live API.
|
|
321
|
+
8. Test fixtures marked `source: docs` or `source: go-namecheap-sdk` have not all been verified against the live sandbox. `scripts/record-fixtures.mjs` re-records them from a real sandbox account.
|
|
322
|
+
|
|
323
|
+
## Examples
|
|
324
|
+
|
|
325
|
+
[`examples/express`](./examples/express) is a REST bridge that exposes the client through Express routes and maps the three error classes to HTTP status codes. It is an example, not a service: it has no authentication.
|
|
326
|
+
|
|
327
|
+
## API coverage
|
|
328
|
+
|
|
329
|
+
59 commands, all reachable as `nc.<group>.<method>`.
|
|
330
|
+
|
|
331
|
+
The package also exports the command tables behind each group (`domainsCommands`, `dnsCommands`, and so on) for custom integrations. They are advanced API: they are not covered by semver stability, so prefer `nc.<group>.<method>`.
|
|
332
|
+
|
|
333
|
+
| Group (`nc.`) | Methods | Count |
|
|
334
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----: |
|
|
335
|
+
| `domains` | `getList`, `check`, `getRegistrarLock`, `setRegistrarLock`, `reactivate`, `renew`, `setContacts`, `create`, `getTldList`, `getContacts`, `getInfo` | 11 |
|
|
336
|
+
| `dns` | `setDefault`, `setCustom`, `getList`, `getHosts`, `getEmailForwarding`, `setEmailForwarding`, `setHosts` | 7 |
|
|
337
|
+
| `ns` | `create`, `delete`, `getInfo`, `update` | 4 |
|
|
338
|
+
| `transfer` | `create`, `getStatus`, `updateStatus`, `getList` | 4 |
|
|
339
|
+
| `ssl` | `create`, `getList`, `parseCSR`, `getApproverEmailList`, `activate`, `resendApproverEmail`, `reissue`, `resendFulfillmentEmail`, `editDCVMethod`, `getInfo`, `renew`, `purchaseMoreSans`, `revokeCertificate` | 13 |
|
|
340
|
+
| `users` | `getBalances`, `getPricing`, `changePassword`, `update`, `createAddFundsRequest`, `getAddFundsStatus`, `create`, `login`, `resetPassword` | 9 |
|
|
341
|
+
| `usersAddress` | `create`, `delete`, `getInfo`, `getList`, `setDefault`, `update` | 6 |
|
|
342
|
+
| `whoisGuard` | `changeEmailAddress`, `enable`, `disable`, `getList`, `renew` | 5 |
|
|
343
|
+
|
|
344
|
+
## Contributing and license
|
|
89
345
|
|
|
90
|
-
|
|
91
|
-
Check the [API Docs](https://www.namecheap.com/support/api/methods) for full endpoint support. This library aims to cover the most-used endpoints first, with plans to expand.
|
|
346
|
+
Issues and pull requests are welcome. The project uses Conventional Commits (`yarn commit` starts Commitizen) and semantic-release. Before opening a pull request run `yarn lint && yarn typecheck && yarn test --run --coverage && yarn build`.
|
|
92
347
|
|
|
93
|
-
|
|
94
|
-
This project is licensed under the [ISC License](./LICENSE).
|
|
348
|
+
Licensed under the [ISC license](./LICENSE).
|
|
95
349
|
|
|
96
|
-
##
|
|
97
|
-
Feel free to open an issue or submit a pull request if you'd like to contribute!
|
|
350
|
+
## Attribution
|
|
98
351
|
|
|
352
|
+
Some test fixtures are copied or derived from [namecheap/go-namecheap-sdk](https://github.com/namecheap/go-namecheap-sdk), licensed under Apache-2.0. See [NOTICE](./NOTICE).
|