{"_id":"@aoxborrow/registrar-client","_rev":"7-05ccd57dfc0ad729e58247d7fa5fb658","name":"@aoxborrow/registrar-client","dist-tags":{"latest":"0.7.0"},"versions":{"0.1.0":{"name":"@aoxborrow/registrar-client","version":"0.1.0","keywords":["registrar","registrar-api","domains","domain-registration","domain-management","dns","epp","whois","rdap","typescript","cloudflare","godaddy","namecheap","gandi","porkbun","dynadot","namesilo","spaceship","namebright"],"author":{"url":"https://github.com/aoxborrow","name":"Aaron Oxborrow"},"license":"MIT","_id":"@aoxborrow/registrar-client@0.1.0","maintainers":[{"name":"aoxborrow","email":"aaron@oxborrow.com"}],"homepage":"https://github.com/aoxborrow/registrar-client","bugs":{"url":"https://github.com/aoxborrow/registrar-client/issues"},"dist":{"shasum":"acabe6d1993ec4ec72ae06b61f1b0c16c330004d","tarball":"https://registry.npmjs.org/@aoxborrow/registrar-client/-/registrar-client-0.1.0.tgz","fileCount":30,"integrity":"sha512-uxJSMoi5FuVZlS0i5e/2YjYoocFJd3CDdAlD4tLKG4lc2RGhrX1MB8hdS+VlLzpXs+9LGF7Z3acz3AQnRrN4Ug==","signatures":[{"sig":"MEQCIFYLqu5MEx9ba+c6C1bU9GCdDIs69B8qyx/3NXA8AY/ZAiAvTkitUVtzPrkVmRqPZqaDj8PezIycjJ3hSef1s+J2Yg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2217809},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"419f7760651c832dc098823370aea753a24ae01f","scripts":{"ts":"npm run lint","tsc":"tsc --noEmit","lint":"npm run tsc && npm run eslint && npm run prettier","test":"vitest run","build":"tsup","clear":"npm run clear:ts && npm run clear:eslint && rm -rf dist coverage","eslint":"eslint --cache --cache-location .eslintcache .","ts:fix":"npm run lint:fix","clear:ts":"rm -rf tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo","lint:fix":"npm run eslint:fix && npm run prettier:fix","prettier":"prettier --check .","typecheck":"npm run tsc","eslint:fix":"eslint --cache --cache-location .eslintcache . --fix","test:watch":"vitest","clear:eslint":"rm -rf .eslintcache","prettier:fix":"prettier --write --list-different .","release:major":"npm version major && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:minor":"npm version minor && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:patch":"npm version patch && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build","test:integration":"vitest run --config vitest.integration.config.ts","test:integration:watch":"vitest --config vitest.integration.config.ts"},"_npmUser":{"name":"aoxborrow","email":"aaron@oxborrow.com"},"repository":{"url":"git+https://github.com/aoxborrow/registrar-client.git","type":"git"},"_npmVersion":"11.11.0","description":"One consistent, fully-typed TypeScript interface to many domain registrar APIs (GoDaddy, Cloudflare, Namecheap, Spaceship, Dynadot, Porkbun, and more) behind a single pluggable multi-provider client","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","dependencies":{"fast-xml-parser":"^5.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","dotenv":"^17.4.2","eslint":"^10.9.0","vitest":"^4.1.11","globals":"^17.11.0","prettier":"^3.6.2","@eslint/js":"^10.0.1","typescript":"^5.9.3","@types/node":"^26.2.0","typescript-eslint":"^8.56.0","@vitest/coverage-v8":"^4.1.11","eslint-config-prettier":"^10.1.8","eslint-plugin-import-x":"^4.17.1","@typescript-eslint/parser":"^8.56.0","@typescript-eslint/eslint-plugin":"^8.56.0","eslint-import-resolver-typescript":"^4.4.4"},"_npmOperationalInternal":{"tmp":"tmp/registrar-client_0.1.0_1788196405093_0.0576355183893813","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@aoxborrow/registrar-client","version":"0.2.0","keywords":["registrar","registrar-api","domains","domain-registration","domain-management","dns","epp","whois","rdap","typescript","cloudflare","godaddy","namecheap","gandi","porkbun","dynadot","namesilo","spaceship","namebright"],"author":{"url":"https://github.com/aoxborrow","name":"Aaron Oxborrow"},"license":"MIT","_id":"@aoxborrow/registrar-client@0.2.0","maintainers":[{"name":"aoxborrow","email":"aaron@oxborrow.com"}],"homepage":"https://github.com/aoxborrow/registrar-client","bugs":{"url":"https://github.com/aoxborrow/registrar-client/issues"},"dist":{"shasum":"bf336a79ed87a8eef600439b1add846ddcdfb31e","tarball":"https://registry.npmjs.org/@aoxborrow/registrar-client/-/registrar-client-0.2.0.tgz","fileCount":30,"integrity":"sha512-MR+BUw8NeQ2iTMa0UccU/qVgEiK5gW1g+LLKLrdoFeeXlGvKkjFTYwknXyqq3ORk62e6h1281bQx3YXpJIkaVQ==","signatures":[{"sig":"MEQCIAw2S7cJyFNsF5yX2rlosFR7F6VJDDpimA9FXEUnncKAAiBoYstJc47V0DRzqPlR/WFeThYlmjkKWXaw1kyGO5sOvw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aoxborrow%2fregistrar-client@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":2221266},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"738409545663ab7e9d5b261eadcd68ae585acbb3","scripts":{"ts":"npm run lint","tsc":"tsc --noEmit","lint":"npm run tsc && npm run eslint && npm run prettier","test":"vitest run","build":"tsup","clear":"npm run clear:ts && npm run clear:eslint && rm -rf dist coverage","eslint":"eslint --cache --cache-location .eslintcache .","ts:fix":"npm run lint:fix","clear:ts":"rm -rf tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo","lint:fix":"npm run eslint:fix && npm run prettier:fix","prettier":"prettier --check .","typecheck":"npm run tsc","eslint:fix":"eslint --cache --cache-location .eslintcache . --fix","test:watch":"vitest","clear:eslint":"rm -rf .eslintcache","prettier:fix":"prettier --write --list-different .","release:major":"npm version major && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:minor":"npm version minor && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:patch":"npm version patch && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build","test:integration":"vitest run --config vitest.integration.config.ts","test:integration:watch":"vitest --config vitest.integration.config.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:00d83d77-e520-4a44-9015-a63038ebfa26"}},"repository":{"url":"git+https://github.com/aoxborrow/registrar-client.git","type":"git"},"_npmVersion":"11.19.1","description":"One consistent, fully-typed TypeScript interface to many domain registrar APIs (GoDaddy, Cloudflare, Namecheap, Spaceship, Dynadot, Porkbun, and more) behind a single pluggable multi-provider client","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"fast-xml-parser":"^5.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","dotenv":"^17.4.2","eslint":"^10.9.0","vitest":"^4.1.11","globals":"^17.11.0","prettier":"^3.6.2","@eslint/js":"^10.0.1","typescript":"^5.9.3","@types/node":"^26.2.0","typescript-eslint":"^8.56.0","@vitest/coverage-v8":"^4.1.11","eslint-config-prettier":"^10.1.8","eslint-plugin-import-x":"^4.17.1","@typescript-eslint/parser":"^8.56.0","@typescript-eslint/eslint-plugin":"^8.56.0","eslint-import-resolver-typescript":"^4.4.4"},"_npmOperationalInternal":{"tmp":"tmp/registrar-client_0.2.0_1788377804678_0.28883981915094403","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@aoxborrow/registrar-client","version":"0.3.0","keywords":["registrar","registrar-api","domains","domain-registration","domain-management","dns","epp","whois","rdap","typescript","cloudflare","godaddy","namecheap","gandi","porkbun","dynadot","namesilo","spaceship","namebright"],"author":{"url":"https://github.com/aoxborrow","name":"Aaron Oxborrow"},"license":"MIT","_id":"@aoxborrow/registrar-client@0.3.0","maintainers":[{"name":"aoxborrow","email":"aaron@oxborrow.com"}],"homepage":"https://github.com/aoxborrow/registrar-client","bugs":{"url":"https://github.com/aoxborrow/registrar-client/issues"},"dist":{"shasum":"b9ef5a60992b89a98741d373a86c8d0f86cd8680","tarball":"https://registry.npmjs.org/@aoxborrow/registrar-client/-/registrar-client-0.3.0.tgz","fileCount":30,"integrity":"sha512-X3sZuRSiR8WyACpSaxuzFiwgTTrN+uOdT+N0ShLhxrRpbzej1h6u2yajnvEpnP+KO3clzFHwMhXPPMm6EexRaw==","signatures":[{"sig":"MEQCIBt5LVj0wsmpwqVHCtpCS01f/kr6RiN+Zqm8K245jSdTAiBwtbwrqwQZ7Uqfw+qMK71g+FykT5G1/Z7TwZF/znqEHQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aoxborrow%2fregistrar-client@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":2229402},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs"}},"funding":"https://github.com/sponsors/aoxborrow","gitHead":"62c4a0dc583f302f49a46385765ac1fcbcc8be31","scripts":{"ts":"npm run lint","tsc":"tsc --noEmit","lint":"npm run tsc && npm run eslint && npm run prettier","test":"vitest run","build":"tsup","clear":"npm run clear:ts && npm run clear:eslint && rm -rf dist coverage","eslint":"eslint --cache --cache-location .eslintcache .","ts:fix":"npm run lint:fix","clear:ts":"rm -rf tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo","lint:fix":"npm run eslint:fix && npm run prettier:fix","prettier":"prettier --check .","typecheck":"npm run tsc","eslint:fix":"eslint --cache --cache-location .eslintcache . --fix","test:watch":"vitest","clear:eslint":"rm -rf .eslintcache","prettier:fix":"prettier --write --list-different .","release:major":"npm version major && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:minor":"npm version minor && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:patch":"npm version patch && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build","test:integration":"vitest run --config vitest.integration.config.ts","test:integration:watch":"vitest --config vitest.integration.config.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:00d83d77-e520-4a44-9015-a63038ebfa26"}},"repository":{"url":"git+https://github.com/aoxborrow/registrar-client.git","type":"git"},"_npmVersion":"11.19.1","description":"One consistent, fully-typed TypeScript interface to many domain registrar APIs (GoDaddy, Cloudflare, Namecheap, Spaceship, Dynadot, Porkbun, and more) behind a single pluggable multi-provider client","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"fast-xml-parser":"^5.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","dotenv":"^17.4.2","eslint":"^10.9.0","vitest":"^4.1.11","globals":"^17.11.0","prettier":"^3.6.2","@eslint/js":"^10.0.1","typescript":"^5.9.3","@types/node":"^26.2.0","typescript-eslint":"^8.56.0","@vitest/coverage-v8":"^4.1.11","eslint-config-prettier":"^10.1.8","eslint-plugin-import-x":"^4.17.1","@typescript-eslint/parser":"^8.56.0","@typescript-eslint/eslint-plugin":"^8.56.0","eslint-import-resolver-typescript":"^4.4.4"},"_npmOperationalInternal":{"tmp":"tmp/registrar-client_0.3.0_1788406340439_0.9372768031905048","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@aoxborrow/registrar-client","version":"0.4.0","keywords":["registrar","registrar-api","domains","domain-registration","domain-management","dns","epp","whois","rdap","typescript","cloudflare","godaddy","namecheap","gandi","porkbun","dynadot","namesilo","spaceship","namebright"],"author":{"url":"https://github.com/aoxborrow","name":"Aaron Oxborrow"},"license":"MIT","_id":"@aoxborrow/registrar-client@0.4.0","maintainers":[{"name":"aoxborrow","email":"aaron@oxborrow.com"}],"homepage":"https://github.com/aoxborrow/registrar-client","bugs":{"url":"https://github.com/aoxborrow/registrar-client/issues"},"dist":{"shasum":"1f5c400ba599b25c05d53f7bed59c63c443e2a70","tarball":"https://registry.npmjs.org/@aoxborrow/registrar-client/-/registrar-client-0.4.0.tgz","fileCount":30,"integrity":"sha512-Oz6U5+ctJ3htHUfGo/Ubw5brLqkmniHI+TmxPEGadfRb1pyPDiRCjWoveY0ReijJSXvFR+2g9XseyviHi5lFew==","signatures":[{"sig":"MEUCIByxBOSEbHD+kiX2qldisWHtXtr6C9XhSxH9LWxw+g2oAiEA37waXSbRbyaL6R736FzbSigiSC1aZud+oow+QyFDd7E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aoxborrow%2fregistrar-client@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":2231314},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs"}},"funding":"https://github.com/sponsors/aoxborrow","gitHead":"c15f7f1165cbded74a9439ae1bb94c9f071cad4c","scripts":{"ts":"npm run lint","tsc":"tsc --noEmit","lint":"npm run tsc && npm run eslint && npm run prettier","test":"vitest run","build":"tsup","clear":"npm run clear:ts && npm run clear:eslint && rm -rf dist coverage","eslint":"eslint --cache --cache-location .eslintcache .","ts:fix":"npm run lint:fix","clear:ts":"rm -rf tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo","lint:fix":"npm run eslint:fix && npm run prettier:fix","prettier":"prettier --check .","typecheck":"npm run tsc","eslint:fix":"eslint --cache --cache-location .eslintcache . --fix","test:watch":"vitest","clear:eslint":"rm -rf .eslintcache","prettier:fix":"prettier --write --list-different .","release:major":"npm version major && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:minor":"npm version minor && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:patch":"npm version patch && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build","test:integration":"vitest run --config vitest.integration.config.ts","test:integration:watch":"vitest --config vitest.integration.config.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:00d83d77-e520-4a44-9015-a63038ebfa26"}},"repository":{"url":"git+https://github.com/aoxborrow/registrar-client.git","type":"git"},"_npmVersion":"11.19.1","description":"One consistent, fully-typed TypeScript interface to many domain registrar APIs (GoDaddy, Cloudflare, Namecheap, Spaceship, Dynadot, Porkbun, and more) behind a single pluggable multi-provider client","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"fast-xml-parser":"^5.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","dotenv":"^17.4.2","eslint":"^10.9.0","vitest":"^4.1.11","globals":"^17.11.0","prettier":"^3.6.2","@eslint/js":"^10.0.1","typescript":"^5.9.3","@types/node":"^26.2.0","typescript-eslint":"^8.56.0","@vitest/coverage-v8":"^4.1.11","eslint-config-prettier":"^10.1.8","eslint-plugin-import-x":"^4.17.1","@typescript-eslint/parser":"^8.56.0","@typescript-eslint/eslint-plugin":"^8.56.0","eslint-import-resolver-typescript":"^4.4.4"},"_npmOperationalInternal":{"tmp":"tmp/registrar-client_0.4.0_1788411901188_0.10103816192257109","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@aoxborrow/registrar-client","version":"0.5.0","keywords":["registrar","registrar-api","domains","domain-registration","domain-management","dns","epp","whois","rdap","typescript","cloudflare","godaddy","namecheap","gandi","porkbun","dynadot","namesilo","spaceship","namebright"],"author":{"url":"https://github.com/aoxborrow","name":"Aaron Oxborrow"},"license":"MIT","_id":"@aoxborrow/registrar-client@0.5.0","maintainers":[{"name":"aoxborrow","email":"aaron@oxborrow.com"}],"homepage":"https://github.com/aoxborrow/registrar-client","bugs":{"url":"https://github.com/aoxborrow/registrar-client/issues"},"dist":{"shasum":"c7627e7e7a88db4a3e1bf22a5a3eee6cbb92ec03","tarball":"https://registry.npmjs.org/@aoxborrow/registrar-client/-/registrar-client-0.5.0.tgz","fileCount":30,"integrity":"sha512-MgsV9nkCAl4pQEV93fTNVQtY/bkCkZ9yqhQUTm4GRxPA4KX0lTtk/Yu+sn5HB0tUi/0UAe1orxuPoyfP4nZNZA==","signatures":[{"sig":"MEYCIQCfk2FwNaZwPyVev8M5jxoblbRQ7SFx283IvnRxbXjqPAIhAMu4/j1+aVMJBHMV5tTEKP8dZuNAi4cM+f99Q+WYPeBD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aoxborrow%2fregistrar-client@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":2232305},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs"}},"funding":"https://github.com/sponsors/aoxborrow","gitHead":"a61bf54191d696ef2aa4856cbc4d3f17cf04fcb1","scripts":{"ts":"npm run lint","tsc":"tsc --noEmit","lint":"npm run tsc && npm run eslint && npm run prettier","test":"vitest run","build":"tsup","clear":"npm run clear:ts && npm run clear:eslint && rm -rf dist coverage","eslint":"eslint --cache --cache-location .eslintcache .","ts:fix":"npm run lint:fix","clear:ts":"rm -rf tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo","lint:fix":"npm run eslint:fix && npm run prettier:fix","prettier":"prettier --check .","typecheck":"npm run tsc","eslint:fix":"eslint --cache --cache-location .eslintcache . --fix","test:watch":"vitest","clear:eslint":"rm -rf .eslintcache","prettier:fix":"prettier --write --list-different .","release:major":"npm version major && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:minor":"npm version minor && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:patch":"npm version patch && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build","test:integration":"vitest run --config vitest.integration.config.ts","test:integration:watch":"vitest --config vitest.integration.config.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:00d83d77-e520-4a44-9015-a63038ebfa26"}},"repository":{"url":"git+https://github.com/aoxborrow/registrar-client.git","type":"git"},"_npmVersion":"11.19.1","description":"One consistent, fully-typed TypeScript interface to many domain registrar APIs (GoDaddy, Cloudflare, Namecheap, Spaceship, Dynadot, Porkbun, and more) behind a single pluggable multi-provider client","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"fast-xml-parser":"^5.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","dotenv":"^17.4.2","eslint":"^10.9.0","vitest":"^4.1.11","globals":"^17.11.0","prettier":"^3.6.2","@eslint/js":"^10.0.1","typescript":"^5.9.3","@types/node":"^26.2.0","typescript-eslint":"^8.56.0","@vitest/coverage-v8":"^4.1.11","eslint-config-prettier":"^10.1.8","eslint-plugin-import-x":"^4.17.1","@typescript-eslint/parser":"^8.56.0","@typescript-eslint/eslint-plugin":"^8.56.0","eslint-import-resolver-typescript":"^4.4.4"},"_npmOperationalInternal":{"tmp":"tmp/registrar-client_0.5.0_1788416138974_0.002437214341112437","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@aoxborrow/registrar-client","version":"0.6.0","keywords":["registrar","registrar-api","domains","domain-registration","domain-management","dns","epp","whois","rdap","typescript","cloudflare","godaddy","namecheap","gandi","porkbun","dynadot","namesilo","spaceship","namebright"],"author":{"url":"https://github.com/aoxborrow","name":"Aaron Oxborrow"},"license":"MIT","_id":"@aoxborrow/registrar-client@0.6.0","maintainers":[{"name":"aoxborrow","email":"aaron@oxborrow.com"}],"homepage":"https://github.com/aoxborrow/registrar-client","bugs":{"url":"https://github.com/aoxborrow/registrar-client/issues"},"dist":{"shasum":"85b6a9312fb066d4b8d5194428ce18c9dac98ae5","tarball":"https://registry.npmjs.org/@aoxborrow/registrar-client/-/registrar-client-0.6.0.tgz","fileCount":31,"integrity":"sha512-1up5iZm5m0sN/5oEec7AWnFxxpWagxhihkhIEOY6RljYvOfdPCkhC/DFkF+QpqwaRos6ndWO+Wn+5r8hrlUJqg==","signatures":[{"sig":"MEUCICft84osYad70DR+3241zcE8C/HEYt+ACNU8/2Xt4uYNAiEA5kFwVA7Y9bm3igycDRv6GI9E4Qw7k1syCd/EKB/sWGM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aoxborrow%2fregistrar-client@0.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":2394366},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs"}},"funding":"https://github.com/sponsors/aoxborrow","gitHead":"540034806bb1ab964ffb710a8a6bad2b7881507b","scripts":{"ts":"npm run lint","tsc":"tsc --noEmit","lint":"npm run tsc && npm run eslint && npm run prettier","test":"vitest run","build":"tsup","clear":"npm run clear:ts && npm run clear:eslint && rm -rf dist coverage","eslint":"eslint --cache --cache-location .eslintcache .","ts:fix":"npm run lint:fix","clear:ts":"rm -rf tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo","lint:fix":"npm run eslint:fix && npm run prettier:fix","prettier":"prettier --check .","typecheck":"npm run tsc","eslint:fix":"eslint --cache --cache-location .eslintcache . --fix","test:watch":"vitest","clear:eslint":"rm -rf .eslintcache","prettier:fix":"prettier --write --list-different .","release:major":"npm version major && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:minor":"npm version minor && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:patch":"npm version patch && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build","test:integration":"vitest run --config vitest.integration.config.ts","test:integration:watch":"vitest --config vitest.integration.config.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:00d83d77-e520-4a44-9015-a63038ebfa26"}},"repository":{"url":"git+https://github.com/aoxborrow/registrar-client.git","type":"git"},"_npmVersion":"11.19.1","description":"One consistent, fully-typed TypeScript interface to many domain registrar APIs (GoDaddy, Cloudflare, Namecheap, Spaceship, Dynadot, Porkbun, and more) behind a single pluggable multi-provider client","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"fast-xml-parser":"^5.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","dotenv":"^17.4.2","eslint":"^10.9.0","vitest":"^4.1.11","globals":"^17.11.0","prettier":"^3.6.2","@eslint/js":"^10.0.1","typescript":"^5.9.3","@types/node":"^26.2.0","typescript-eslint":"^8.56.0","@vitest/coverage-v8":"^4.1.11","eslint-config-prettier":"^10.1.8","eslint-plugin-import-x":"^4.17.1","@typescript-eslint/parser":"^8.56.0","@typescript-eslint/eslint-plugin":"^8.56.0","eslint-import-resolver-typescript":"^4.4.4"},"_npmOperationalInternal":{"tmp":"tmp/registrar-client_0.6.0_1789008575851_0.2825232060772118","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"_id":"@aoxborrow/registrar-client@0.7.0","bugs":{"url":"https://github.com/aoxborrow/registrar-client/issues"},"dist":{"shasum":"87648f6ad62dd9d29690b4fe2e517c8face58625","tarball":"https://registry.npmjs.org/@aoxborrow/registrar-client/-/registrar-client-0.7.0.tgz","fileCount":31,"integrity":"sha512-j2N6/vDiSevTmvr5xIPI0OU/1mRNM6plSZYUXAfO2xKP8ed6xrz8h0kARsl65+VkZDEtbWx+o6ROhZojmKTgQA==","signatures":[{"sig":"MEUCIFyIXDtRXeT5hQVMAhhFSohw+4Ax08IpNegJCQ8lAITfAiEAsntAFWleJjIhsTpuz5jt/24iVhg+xJWQcwXCBcsHYD0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHWFyrAV3nu2mhTVjAvdCxGjH1gQ1EDBoo14it+7w2W5AiBZGRx8UzAibNQiTEICWUkTYHTCQchxFDjprzkk9tlVew=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aoxborrow%2fregistrar-client@0.7.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":2466505},"main":"./dist/index.cjs","name":"@aoxborrow/registrar-client","type":"module","types":"./dist/index.d.ts","author":{"url":"https://github.com/aoxborrow","name":"Aaron Oxborrow"},"module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs"}},"funding":"https://github.com/sponsors/aoxborrow","gitHead":"c545861a066442c390304708da1b00258bd86d39","license":"MIT","scripts":{"ts":"npm run lint","tsc":"tsc --noEmit","lint":"npm run tsc && npm run eslint && npm run prettier","test":"vitest run","build":"tsup","clear":"npm run clear:ts && npm run clear:eslint && rm -rf dist coverage","eslint":"eslint --cache --cache-location .eslintcache .","ts:fix":"npm run lint:fix","clear:ts":"rm -rf tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo","lint:fix":"npm run eslint:fix && npm run prettier:fix","prettier":"prettier --check .","typecheck":"npm run tsc","eslint:fix":"eslint --cache --cache-location .eslintcache . --fix","test:watch":"vitest","clear:eslint":"rm -rf .eslintcache","prettier:fix":"prettier --write --list-different .","release:major":"npm version major && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:minor":"npm version minor && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","release:patch":"npm version patch && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build","test:integration":"vitest run --config vitest.integration.config.ts","test:integration:watch":"vitest --config vitest.integration.config.ts"},"version":"0.7.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:00d83d77-e520-4a44-9015-a63038ebfa26"}},"homepage":"https://github.com/aoxborrow/registrar-client","keywords":["registrar","registrar-api","domains","domain-registration","domain-management","dns","epp","whois","rdap","typescript","cloudflare","godaddy","namecheap","gandi","porkbun","dynadot","namesilo","spaceship","namebright"],"repository":{"url":"git+https://github.com/aoxborrow/registrar-client.git","type":"git"},"_npmVersion":"11.19.1","description":"One consistent, fully-typed TypeScript interface to many domain registrar APIs (GoDaddy, Cloudflare, Namecheap, Spaceship, Dynadot, Porkbun, and more) behind a single pluggable multi-provider client","directories":{},"maintainers":[{"name":"aoxborrow","email":"aaron@oxborrow.com"}],"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"fast-xml-parser":"^5.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","dotenv":"^17.4.2","eslint":"^10.9.0","vitest":"^4.1.11","globals":"^17.11.0","prettier":"^3.6.2","@eslint/js":"^10.0.1","typescript":"^5.9.3","@types/node":"^26.2.0","typescript-eslint":"^8.56.0","@vitest/coverage-v8":"^4.1.11","eslint-config-prettier":"^10.1.8","eslint-plugin-import-x":"^4.17.1","@typescript-eslint/parser":"^8.56.0","@typescript-eslint/eslint-plugin":"^8.56.0","eslint-import-resolver-typescript":"^4.4.4"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/registrar-client_0.7.0_1789625389503_0.5309740634833082"}}},"time":{"created":"2026-08-31T17:13:24.892Z","modified":"2026-09-17T06:09:49.931Z","0.1.0":"2026-08-31T17:13:25.259Z","0.2.0":"2026-09-02T19:36:44.889Z","0.3.0":"2026-09-03T03:32:20.602Z","0.4.0":"2026-09-03T05:05:01.335Z","0.5.0":"2026-09-03T06:15:39.132Z","0.6.0":"2026-09-10T02:49:36.062Z","0.7.0":"2026-09-17T06:09:49.624Z"},"bugs":{"url":"https://github.com/aoxborrow/registrar-client/issues"},"author":{"url":"https://github.com/aoxborrow","name":"Aaron Oxborrow"},"license":"MIT","homepage":"https://github.com/aoxborrow/registrar-client","keywords":["registrar","registrar-api","domains","domain-registration","domain-management","dns","epp","whois","rdap","typescript","cloudflare","godaddy","namecheap","gandi","porkbun","dynadot","namesilo","spaceship","namebright"],"repository":{"url":"git+https://github.com/aoxborrow/registrar-client.git","type":"git"},"description":"One consistent, fully-typed TypeScript interface to many domain registrar APIs (GoDaddy, Cloudflare, Namecheap, Spaceship, Dynadot, Porkbun, and more) behind a single pluggable multi-provider client","maintainers":[{"name":"aoxborrow","email":"aaron@oxborrow.com"}],"readme":"# registrar-client\n\n[![npm version](https://img.shields.io/npm/v/@aoxborrow/registrar-client.svg)](https://www.npmjs.com/package/@aoxborrow/registrar-client)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen.svg)](https://nodejs.org)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org)\n[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-ea4aaa?logo=githubsponsors&logoColor=white)](https://github.com/sponsors/aoxborrow)\n\n> One consistent, fully-typed TypeScript interface to many domain registrar APIs.\n\nTalk to GoDaddy, Cloudflare, Namecheap, Spaceship, Dynadot, Porkbun, and more\nthrough a single pluggable `Registrar` contract — one typed API instead of a\ndifferent one for every registrar. It speaks both JSON and XML registrar APIs and\nnormalizes every provider's responses to the same shared models. The full list of\nsupported providers is [below](#providers).\n\n**PRs for additional registrars are welcome** — adding one means extending a base\nclass and overriding the operations that provider's API supports (see\n[Adding a provider](#adding-a-provider)).\n\nPowers **[DomBot](https://dombot.ai)**, a desktop app and MCP server for managing\na domain portfolio spread across many registrars from one place.\n\nPortable by design: its single runtime dependency\n([`fast-xml-parser`](https://github.com/NaturalIntelligence/fast-xml-parser),\npure JS) uses no Node built-ins, so it runs anywhere `fetch` is available —\nNode 20+, Deno, Bun, browsers, and edge runtimes.\n\n> **Status:** every bundled provider implements the full 18-method core\n> contract, plus their extended capabilities (auth code, DNSSEC, forwarding).\n> Where a registrar's API genuinely can't do something, that method throws\n> `NotImplementedError` with a specific reason — see\n> [Supported functionality](#supported-functionality). Most read and write paths\n> have been verified against live accounts or provider sandboxes (2026-08). Still\n> treat paid, irreversible operations (register / renew / transfer) as\n> use-at-your-own-risk: some remain documented-but-unrun on funded accounts.\n\n## Install\n\n```bash\nnpm install @aoxborrow/registrar-client\n```\n\n## Providers\n\n| id           | Provider   | Auth                       | Sandbox | Notes                                        |\n| ------------ | ---------- | -------------------------- | ------- | -------------------------------------------- |\n| `cloudflare` | Cloudflare | API token + Account ID     | —       | manages existing domains only                |\n| `dynadot`    | Dynadot    | API key                    | ✓       | `api-sandbox.dynadot.com`; key in query      |\n| `gandi`      | Gandi.net  | API key                    | ✓       | `api.sandbox.gandi.net`                      |\n| `godaddy`    | GoDaddy    | PAT, or key + secret       | ✓       | hybrid v3/v1; sandbox = OTE (v1 only)        |\n| `namebright` | NameBright | client ID + secret         | —       | OAuth2 bearer; production-only               |\n| `namecheap`  | Namecheap  | username + key + client IP | ✓       | XML API; IP allowlisting required            |\n| `namecom`    | Name.com   | username + API token       | ✓       | Core v1; separate sandbox host and token     |\n| `namesilo`   | NameSilo   | API key                    | ✓       | JSON/XML API; key sent in query string       |\n| `porkbun`    | Porkbun    | key + secret               | ✓       | sandbox via `pk1_sb_` key; per-domain opt-in |\n| `spaceship`  | Spaceship  | key + secret               | —       |                                              |\n\nEach provider class exposes static discovery metadata — `displayName`,\n`website` (its public domain, e.g. `gandi.net`), `configFields` (the credential\nfields it needs), and `helpText` (where to get them) — so you can build a\ncredential UI generically.\n\nResearch notes for additional registrars live in\n[`docs/registrars/`](docs/registrars). Three are documented but **not**\nimplemented because they have no usable public API: **Squarespace**\n(reseller-program-gated), **Network Solutions** (partner-gated Partner Protocol /\nSRSplus), and **eDomains** (WHMCS-based, no documented API). They can be added if\nAPI access becomes available.\n\n## Usage\n\nConstruct a provider (directly or via the `createRegistrar` factory) and, optionally, wrap it in\nthe `RegistrarClient` facade:\n\n```ts\nimport { RegistrarClient, createRegistrar } from '@aoxborrow/registrar-client';\n\nconst client = new RegistrarClient(\n  createRegistrar('cloudflare', {\n    apiToken: process.env.CF_API_TOKEN!,\n    accountId: process.env.CF_ACCOUNT_ID!,\n  })\n);\n\nawait client.testConnection();\nconst domains = await client.listDomains();\nconst [availability] = await client.checkAvailability(['example.com']);\nconst records = await client.getDnsRecords('example.com');\nawait client.updateNameservers('example.com', ['ns1.example.net', 'ns2.example.net']);\n```\n\nEvery provider implements the same `Registrar` interface — the full core\ncontract is `testConnection`, `listDomains`, `getDomain`, `checkAvailability`,\n`getPricing`, `registerDomain`, `renewDomain`, `setAutoRenew`, `transferIn`,\n`updateNameservers`, `getNameservers`, `lockDomain`, `unlockDomain`,\n`setPrivacy`, `getContacts`, `updateContacts`, `getDnsRecords`, and\n`setDnsRecords`. Every provider implements it; where a registrar's API can't\nexpress a given method, that method throws `NotImplementedError` with a specific\nreason (see [Supported functionality](#supported-functionality)). The gaps are\nAPI limits, not missing work — e.g. **Cloudflare** has no post-registration write\nendpoints, **Porkbun** exposes no transfer-lock / privacy / contact-read toggles,\n**NameBright** has no transfer-in endpoint, and **Spaceship** / **NameBright**\nhave no pricing endpoint. **Namecheap** and **Gandi** are the only providers with\na real per-TLD `getPricing` table; **GoDaddy** and **Dynadot** price per-domain\nvia their availability endpoint.\n\n## Listing domains & portfolios\n\n`listDomains` returns the **full account**, paginating internally at each\nprovider's maximum page size (so it makes the fewest requests each API allows).\nOptions:\n\n- `search` — a domain-name substring filter, applied server-side where the API\n  supports it (**Namecheap** `SearchTerm`, **Gandi** `fqdn`) and client-side\n  everywhere else.\n- `detailed` — fetch full per-domain detail after listing (see below).\n\nThe usual request options (timeout/retries/signal) still apply.\n\n```ts\nconst all = await client.listDomains();\nconst acme = await client.listDomains({ search: 'acme' });\nconst full = await client.listDomains({ detailed: true });\n```\n\nSeveral providers' list endpoints return only a **summary** that omits\n`nameservers`, `privacy`, and/or the transfer `locked` flag, which then read as\ntheir defaults (`[]` / `false`). Nameservers come back in the single list call\nonly on **GoDaddy** (via `includes=nameServers`), **Spaceship**, and\n**Dynadot**; **Gandi**, **Namecheap**, **Porkbun**, **NameSilo**, and\n**NameBright** omit them (and **Gandi**/**NameSilo** also omit `privacy`).\n(**Cloudflare** manages nameservers via its Zones API, not the Registrar list.)\n\nPass `detailed: true` and the facade follows up with a `getDomain` per domain\n(bounded concurrency, falling back to `getNameservers` where detail still lacks\nthem) and merges the result — so `nameservers`, `privacy`, and `locked` are\naccurate. It costs one extra request per domain, so it's opt-in; leave it off\nfor a fast summary, or call `getDomain` / `getNameservers` yourself for\nindividual domains.\n\nTo build a combined view across registrars, `listPortfolio` fans out over many\nproviders concurrently with per-registrar error isolation (one provider being\ndown never sinks the whole view). Every `Domain` already carries its `registrar`:\n\n```ts\nimport { listPortfolio, createRegistrar } from '@aoxborrow/registrar-client';\n\nconst { domains, errors } = await listPortfolio([\n  createRegistrar('godaddy', godaddyCreds),\n  createRegistrar('namecheap', namecheapCreds),\n  createRegistrar('gandi', gandiCreds),\n]);\n// domains: Domain[] (each tagged with .registrar); errors: { registrar, error }[]\n```\n\n## Supported functionality\n\nWhat each provider implements today, read straight from the code. **Core** methods\nare the guaranteed contract; **extended** methods are opt-in per provider.\n\n**Legend:** ✓ implemented · ✗ not available via the provider's API (throws\n`NotImplementedError`) · a superscript marks a caveat noted below.\n\n| Core method         | CF  | DY  | GA  | GD  | NB  | NC  | NS  | PB  | SP  | NM  |\n| ------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| `testConnection`    | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `listDomains`       | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `getDomain`         | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `checkAvailability` | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `getPricing`        | ✓   | ✓ᵃ  | ✓   | ✓ᵃ  | ✗ᵇ  | ✓   | ✓   | ✓   | ✗ᵇ  | ✓   |\n| `registerDomain`    | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `renewDomain`       | ✗ᶜ  | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `setAutoRenew`      | ✗ᶜ  | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `transferIn`        | ✗ᶜ  | ✓   | ✓   | ✓   | ✗ᵈ  | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `updateNameservers` | ✗ᶜ  | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `getNameservers`    | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `lockDomain`        | ✗ᶜ  | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✗ᵉ  | ✓   | ✓   |\n| `unlockDomain`      | ✗ᶜ  | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✗ᵉ  | ✓   | ✓   |\n| `setPrivacy`        | ✓   | ✓   | ✓ᶠ  | ✓ᵍ  | ✓   | ✓   | ✓   | ✗ᵉ  | ✓   | ✓   |\n| `getContacts`       | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✗ᵉ  | ✓   | ✓   |\n| `updateContacts`    | ✗ᶜ  | ✓   | ✓   | ✓   | ✗ᵈ  | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `getDnsRecords`     | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   |\n| `setDnsRecords`     | ✓   | ✓ʰ  | ✓   | ✓   | ✓   | ✓   | ✓   | ✓   | ✓ʰ  | ✓   |\n\n| Extended method       | CF  | DY  | GA  | GD  | NB  | NC  | NS  | PB  | SP  | NM  |\n| --------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| `getAuthCode`         | ✗   | ✓   | ✓   | ✓   | ✓   | ✗ⁱ  | ✗ⁱ  | ✗   | ✓   | ✓   |\n| `getDnssec`           | ✗   | ✓   | ✓   | ✗   | ✗   | ✗   | ✓   | ✓   | ✗   | ✗ᵐ  |\n| `disableDnssec`       | ✗   | ✓   | ✓   | ✗   | ✗   | ✗   | ✓   | ✓   | ✗   | ✗ᵐ  |\n| `getEmailForwarding`  | ✓   | ✓   | ✓   | ✗   | ✗   | ✓   | ✓   | ✗   | ✗   | ✗ᵐ  |\n| `setEmailForwarding`  | ✓   | ✓   | ✓   | ✗   | ✗   | ✓   | ✓   | ✗   | ✗   | ✗ᵐ  |\n| `getDomainForwarding` | ✓   | ✓ʲ  | ✓ᵏ  | ✓ˡ  | ✗   | ✓   | ✓ʲ  | ✓   | ✗   | ✗ᵐ  |\n| `setDomainForwarding` | ✓   | ✓ʲ  | ✓ᵏ  | ✓ˡ  | ✗   | ✓   | ✓ʲ  | ✓   | ✗   | ✗ᵐ  |\n\n`CF` Cloudflare · `DY` Dynadot · `GA` Gandi · `GD` GoDaddy · `NB` NameBright ·\n`NC` Namecheap · `NS` NameSilo · `PB` Porkbun · `SP` Spaceship · `NM` Name.com.\n\n**Caveats**\n\n- **ᵐ** Name.com DNSSEC and forwarding are not wired into this adapter yet;\n  they are not advertised as extended features. See [Name.com](#namecom-core-api)\n  for pricing, transfer and DNS limits.\n\n- **ᵃ** `getPricing` is per-domain only (pass a full name, not a bare TLD) —\n  Dynadot and GoDaddy price via their availability endpoint and have no per-TLD\n  price table.\n- **ᵇ** No pricing endpoint at all; a per-domain registration price is still\n  available through `checkAvailability`.\n- **ᶜ** Cloudflare Registrar has no post-registration write API — auto-renew,\n  privacy, and lock are settable only at registration; nameserver changes require\n  Cloudflare support; there is no renew, transfer-in, or contact-update endpoint.\n  These throw with a message pointing to the dashboard.\n- **ᵈ** NameBright's REST API has no transfer-in or contact-update endpoint.\n- **ᵉ** Porkbun exposes the transfer-lock and privacy state read-only (settable\n  only at registration) and has no WHOIS/contact-read endpoint.\n- **ᶠ** Gandi `setPrivacy(false)` is a no-op for individual registrants — WHOIS\n  stays obfuscated for GDPR.\n- **ᵍ** GoDaddy `setPrivacy`: enabling is a paid add-on (not implemented);\n  disabling works for paid privacy, but GoDaddy's free privacy (\"Free DBP\")\n  cannot be disabled via the API (returns a clear error pointing to the dashboard).\n- **ʰ** `setDnsRecords` writes cover the common record types; SRV/CAA and other\n  sub-field-bearing types throw on write (reads handle every type).\n- **ⁱ** Namecheap and NameSilo only email the EPP/auth code to the registrant;\n  it can't be returned synchronously.\n- **ʲ** Dynadot and NameSilo forward the whole domain (a single `@` rule);\n  clearing a forward restores the default nameservers.\n- **ᵏ** Gandi web redirects are subdomain-only — the apex (`@`) is rejected.\n- **ˡ** GoDaddy domain forwarding uses the v2 customer-scoped API, so it requires\n  a `customerId` (the customer UUID, or a numeric shopper ID the client resolves to\n  the UUID via an sso-key-only lookup); the old v1 forwarding route was removed.\n\nFor the deeper cross-provider notes and per-registrar quirks, see\n[docs/registrars/FEATURES.md](docs/registrars/FEATURES.md).\n\n## Capabilities\n\nRegistrars don't all support the same operations. **Core** is a fixed contract\nevery provider is expected to fulfil (inherited by extending `BaseRegistrar`);\n**extended** capabilities are opt-in and declared per provider. Where a core\nmethod's API path isn't wired up yet, it throws `NotImplementedError` — the\ncontract is the promise, not a claim that every byte is implemented today.\n\nReference capabilities through the `Feature` object (autocomplete +\nfind-all-references), and introspect statically — no instance or credentials\nneeded, which makes this easy to surface to a UI or an MCP tool:\n\n```ts\nimport { registrars, createRegistrar, Feature, CORE_FEATURES } from '@aoxborrow/registrar-client';\n\nregistrars.dynadot.features; // full set: core + Dynadot's extras\nregistrars.dynadot.extendedFeatures; // just the extras\nCORE_FEATURES.includes(Feature.GetDnsRecords); // true — DNS is core\n\nconst gd = createRegistrar('godaddy', creds);\ngd.supports(Feature.RegisterDomain); // true (core)\ngd.supports(Feature.GetAuthCode); // true (its extended)\ngd.supports(Feature.SetDomainForwarding); // false (not declared)\n```\n\nSee [docs/registrars/FEATURES.md](docs/registrars/FEATURES.md) for the full\nfeature matrix and the core vs. extended breakdown.\n\n## Forwarding\n\nTwo opt-in extended capabilities cover forwarding, both modelled as replace-all\nsets:\n\n- **Domain (URL) forwarding** — `getDomainForwarding` / `setDomainForwarding`\n  take `DomainForward[]` (`{ host, url, type }`). `host` is apex-relative (`@`,\n  `www`, …); `type` is `temporary` (302) or `permanent` (301). HTTPS targets work\n  wherever the provider issues a certificate for the domain (all supported\n  providers do).\n- **Email forwarding** — `getEmailForwarding` / `setEmailForwarding` take\n  `EmailForward[]` (`{ alias, forwardTo }`). `alias` is the local part; `*` (or\n  `@`) is the catch-all. This is alias→inbox **forwarding**, not mailbox hosting.\n\n**Masked/framed forwarding is read-only.** `DomainForwardType` also has a\n`masked` value — a \"cloaked\" forward where an iframe keeps the source URL in the\naddress bar. The library **never creates** one (`setDomainForwarding` rejects\n`masked`): it breaks HTTPS, SEO, and modern browser protections, and several\nproviders (e.g. Cloudflare) can't do it at all. But `getDomainForwarding`\n**reports** `masked` truthfully when a provider already has one configured, so\nreading state stays accurate. (One consequence: reading a masked forward and\nwriting the same array straight back is rejected — by design.)\n\nProviders that expose a native forwarding feature do this in one call.\n**Cloudflare** has no such primitive, so the provider composes it from other\nCloudflare APIs: domain forwarding writes a Rules redirect plus a proxied\nplaceholder DNS record so the edge can apply it, and email forwarding uses Email\nRouting (enabling it adds the required MX/SPF records). Email Routing\ndestinations must be verified on the Cloudflare account before a rule activates;\nwhere the token can manage addresses, `setEmailForwarding` adds any unknown\ndestination (sending its verification email) and reports which are still\npending. See [docs/registrars/cloudflare.md](docs/registrars/cloudflare.md).\n\n## Registering & transferring domains\n\nRegistering or transferring a domain forms a legal contract with the registry, so\nregistrars gate `registerDomain`/`transferIn` behind **consent** to their\nagreements. Consent is supplied **per operation** (matching how the registrar\nAPIs model it — there is no \"consent once\" server state):\n\n```ts\nawait client.registerDomain('example.com', {\n  years: 1,\n  contacts: { registrant: { firstName: 'Ada', lastName: 'Lovelace' /* … */ } },\n  consent: { agreedBy: userIpAddress }, // the consenting party's IP\n});\n\nawait client.transferIn('example.com', {\n  authCode: 'EPP-CODE-FROM-LOSING-REGISTRAR',\n  consent: { agreedBy: userIpAddress },\n});\n```\n\nYou only affirm **who** consents (`agreedBy` — the consenting user's IP address)\nand optionally **when** (`agreedAt`, defaulting to now). The provider fetches the\nspecific per-TLD agreement documents itself and attaches them. Omitting `consent`\nthrows `ConsentRequiredError` (distinct from `NotImplementedError` — the\ncapability exists; you just have to consent).\n\nContacts are supplied on the same call, where the registrar needs them: GoDaddy\nand Spaceship take a full contact set on registration (omitted roles fall back to\nthe registrant); Namecheap requires all four roles; Dynadot and Porkbun use the\naccount's default WHOIS contact. Transfers carry over the existing contacts, so\nmost providers need only the auth code (`TransferDomainInput`).\n\n> `registerDomain` is implemented for **every bundled provider**, and `transferIn`\n> for every one whose API has a transfer endpoint (all except **Cloudflare** and\n> **NameBright**). `registerDomain` has been exercised live against several\n> sandboxes and one real account (a live Cloudflare `.dev` registration), but since\n> these operations spend real money, treat any path you haven't run yourself as\n> documented-but-unverified. Known gap: Namecheap registration doesn't yet send\n> per-TLD extended attributes, so TLDs that require them (`.us`, `.eu`, …) aren't\n> registrable there yet.\n\n## Name.com Core API\n\n```ts\nconst namecom = createRegistrar(\n  'namecom',\n  {\n    username: 'your-username-test',\n    apiToken: 'your-development-test-token',\n  },\n  { environment: 'sandbox' }\n);\n\nawait namecom.listDomains();\nawait namecom.getPricing('example.com'); // exact domain prices, including premiums\nawait namecom.getPricing('.co.uk'); // explicit compound TLD; 'com' also works\n```\n\nThe adapter uses [Core v1](https://docs.name.com/api/v1/overview), with HTTP Basic\nAuth in the Authorization header. Production is `https://api.name.com/core/v1`;\nsandbox is `https://api.dev.name.com/core/v1`. Use the Development/Test token and\n`-test` username from [API settings](https://www.name.com/account/settings/api).\nThe username is used exactly as supplied. For 2FA accounts, API Access must be\nenabled. New sandbox credentials can take up to 15 minutes to activate, per the\n[testing guide](https://docs.name.com/guides/testing-environment).\n\nAll portfolio and DNS pages are consumed using `nextPage`, including short\nintermediate pages. Missing boolean fields are Core's default `false` values.\n`status` contains the returned registry lock statuses (lowercased, comma separated);\nCore has no lifecycle-status field. `renewalDate` remains null because Core does\nnot report a scheduled renewal date. The shared `Domain` model has no price field:\nuse `getPricing(domainName)` for renewal prices, rather than estimating them from\nTLD retail prices.\n\nPricing uses account-level USD amounts before VAT. Domain registration and renewal\nquotes explicitly request one year; unavailable/null products remain undefined.\nTransfer prices cover the registry's transfer term, which may exceed one year.\nBare compound strings such as `co.uk` are interpreted as domains; use `.co.uk` for\nTLD pricing. Availability is restricted to standard/registry-premium registration,\nbatched in groups of 50; its discovery price covers the TLD minimum term, so no\none-year `period` is inferred.\n\nRegistration rechecks availability and obtains a quote for the requested term.\nPremium create/renew/transfer requests send the exact matching purchase, renewal,\nor transfer price; standard operations omit `purchasePrice`. Null/unavailable\nquotes stop the operation before purchase. Registration defaults to one year;\npass the appropriate `years` for TLDs with a higher minimum. Aftermarket/backorder,\nclaims acknowledgments, IDN language attributes, and other TLD-specific registration\nrequirements are not exposed by the shared input types. Such registrations require\na provider-specific workflow. Transfers accept `authCode` and optional `privacy`;\nexplicit `years`, `contacts` or `autoRenew` are rejected before submission because\nCore cannot apply them in its transfer request. Update settings after completion.\n\nMutations follow the shared [retry rules](#retries): a request Name.com may have\nreceived is never re-sent. Transport/parse failures after a purchase report an\nunknown outcome: inspect Name.com orders and domain/transfer status before retrying. An accepted order is\nreported as accepted, not proof of final registry completion. Read operations\nretain the shared retry policy and honor `Retry-After` / `X-RateLimit-Reset`.\nHTTP errors retain typed status information but omit provider response bodies,\nwhich may contain credentials, EPP codes or contact data.\n\nContacts require complete objects for each supplied role (including state), and\nomitted roles are left unchanged on update. Postal code/company and EPP-style\nphone numbers are mapped to Core's `zip`, `companyName` and E.164 fields. DNS\nreplacement reconciles individual record IDs, preserving unchanged records and\ncreating/updating before removing stale records. This is **not atomic**; failures\ncan leave a partial zone, which must be read before retrying. Supported DNS types\nare A, AAAA, ANAME, CNAME, MX, NS, SRV and TXT, with a minimum TTL of 300 seconds.\nOnly auth-code retrieval is implemented as an extended feature in this version.\n\nOffline tests exercise the published API contract. Run the dedicated sandbox\nchecks with credentials in `.env.testing`:\n\n```bash\nnpm run test:integration -- test/integration/namecom.integration.test.ts\n```\n\nRead checks are credential-gated and always use sandbox. To exercise registration,\nrenewal, flags, nameservers, contacts and DNS, additionally set\n`NAMECOM_TEST_DOMAIN=registrar-client-<unique-suffix>.com`. This must be a disposable\nsandbox name with that prefix. The test creates it if absent and leaves it in the\nsandbox (Name.com offers no domain deletion/reset there); it is excluded from the\ndefault offline suite. Transfer completion and production behavior need separate\nverification; sandbox transfers are not deterministic.\n\n## Sandbox environments\n\nProviders that offer a test environment accept `{ environment: 'sandbox' }` at\nconstruction, so you can exercise real API calls without touching live domains:\n\n```ts\nconst gd = createRegistrar('godaddy', oteCredentials, { environment: 'sandbox' });\n```\n\nRequesting `sandbox` on a provider that has none (`cloudflare`, `namebright`,\n`spaceship`) throws a `ConfigurationError` — a test can never silently hit\nproduction. Check `SomeRegistrar.supportsSandbox` to discover which do.\n\nSome providers key their sandbox off the **credential**, not a separate host.\n**Porkbun**'s sandbox shares the production base URL — a sandbox key is prefixed\n`pk1_sb_`, starts with $1,000 of fake credit, and marks every response with\n`\"sandbox\": true` (top up / reset via `POST /sandbox/topup` · `POST\n/sandbox/reset`). There, `{ environment: 'sandbox' }` is cosmetic; the `pk1_sb_`\nkey is what routes to the test environment.\n\n### Integration tests\n\nReal sandbox integration tests live in `test/integration/` and are **credential-\ngated**: each registrar's suite skips unless its env vars are set, so the default\nsuite stays offline.\n\n```bash\ncp .env.example .env    # fill in sandbox credentials for the registrars you want\nnpm run test:integration\n```\n\nThey exercise read-only operations (`testConnection`, `listDomains`) against each\nconfigured sandbox. Unit tests (`npm test`) never make network calls.\n\n## Architecture\n\nThe package separates the **caller-facing facade** from **provider\nimplementations**:\n\n- **`RegistrarClient`** — a thin, provider-agnostic facade. Normalizes input and\n  delegates to the configured provider.\n- **`Registrar`** — the core interface every backend implements (the 18 core\n  operations listed under [Usage](#usage), plus the capability accessors).\n  Defined in `src/types.ts`, with shared payload types (`Contact`, `DnsRecord`,\n  `DomainAvailability`, `TldPricing`, `RegisterDomainInput`) alongside it.\n- **`BaseRegistrar`** (`src/registrar.ts`) — an abstract base that owns the\n  shared HTTP/auth/retry plumbing (via `HttpClient`) and provides\n  `NotImplementedError`-rejecting defaults. Concrete providers under\n  `src/registrars/` extend it and override only what their API supports.\n- **`HttpClient`** — a small `fetch` wrapper with timeout, `AbortSignal`\n  linking, retry-with-backoff, `request`/`requestText` (JSON and raw/XML), and\n  typed error mapping. No Node built-ins.\n- **`parseXml` / `ensureArray`** — shared XML helpers (backed by\n  `fast-xml-parser`) with one consistent config across XML providers: attributes\n  kept, values left as raw strings so providers coerce them explicitly.\n- **`registrars` / `createRegistrar`** — a lookup of the built-in providers by\n  id, and a factory to construct one.\n\n### Adding a provider\n\nExtend `BaseRegistrar`, pass a `baseUrl` + auth headers to `super()`, add the\nstatic `displayName` / `configFields` / `helpText` metadata, override the\noperations the API supports (mapping payloads to the shared types in\n`src/types.ts`), and add the class to `src/registrars/index.ts`. Forward the\n`opts` you are given into every `this.http` request: they carry the timeout and\nsignal, and tell the [retry rules](#retries) whether the call reads or writes.\nFor a REST API set `static safeMethods = REST_SAFE_METHODS`; otherwise wrap any\nlookup a write performs first in `asRead(opts)`. The existing providers under\n`src/registrars/` are working references.\n\n**New providers are welcome** — if you've wired up a registrar, open a PR.\n\n## Errors\n\nAll failures throw a typed subclass of `RegistrarError` (`AuthenticationError`,\n`NotFoundError`, `RateLimitError`, `TimeoutError`, `NotImplementedError`, …),\neach carrying an HTTP-style `status`.\n\n## Retries\n\nRequests retry with exponential backoff (`retries`, default 2). What may be\nre-sent depends on where the failure happened and on whether the call reads or\nwrites, and is the same for every provider:\n\n| Failure                                                                    | Read  | Write                                  |\n| -------------------------------------------------------------------------- | ----- | -------------------------------------- |\n| The registrar never saw it: DNS failure, connection refused, TLS handshake | Retry | Retry                                  |\n| `429`, honoring `Retry-After`                                              | Retry | Retry                                  |\n| Outcome unknown: timeout, connection dropped mid-response, `5xx`           | Retry | **Not re-sent.** `OutcomeUnknownError` |\n| Any other response                                                         | Fail  | Fail                                   |\n\nReads and writes are told apart by feature, not by HTTP method (`FEATURE_CALLS`\nlists every one). The method is no guide: Namecheap sends writes as `GET`, and\nPorkbun sends reads as `POST`. `getAuthCode` counts as a write because some\nregistrars regenerate the code.\n\nA write often reads first: current DNS records, a price, a zone id. Those\nlookups changed nothing, so they are retried like any read and never reported as\nan unknown outcome. REST providers get this from the HTTP method\n(`static safeMethods = REST_SAFE_METHODS` treats `GET` and `HEAD` as reads);\nproviders whose method means nothing wrap the lookup's options in `asRead(opts)`.\n\nA write whose outcome is unknown may have been applied, and a second renewal\ncharges twice. So the library reports it and leaves the decision to you: re-read\nthe domain, then retry if nothing changed. Providers that throw raise\n`OutcomeUnknownError`; providers that return an `OperationResult` set\n`outcome: 'unknown'` on it:\n\n```ts\nconst result = await client.renewDomain('example.com', 1);\nif (!result.success && result.outcome === 'unknown') {\n  const domain = await client.getDomain('example.com'); // did it go through?\n}\n```\n\nOnly positive evidence counts as \"never sent\": a pre-connection error code from\nNode's `fetch`, or an error a custom transport marked with `markNotSent`.\nBrowsers and Workers report network failures opaquely, so there they count as\nunknown.\n\n### Custom transport\n\nPass `fetch` to route every request through your own transport, such as a\nproxy:\n\n```ts\nconst registrar = createRegistrar('namecheap', credentials, { fetch: proxiedFetch });\n```\n\nIf the transport can fail before the request leaves, for instance a proxy that\nrefuses the tunnel, throw `markNotSent(error)` so the failure is retried even\nfor writes.\n\n## Security\n\nCredentials are sent as request **headers** wherever the registrar's API\nsupports it. Two providers require query-string authentication by their own API\ndesign — **Dynadot** (`key`) and **Namecheap** (`ApiUser`/`ApiKey`) — so for\nthose the key necessarily appears in the request URL. This is noted in each\nprovider's source. Credentials are not interpolated into error messages.\n\n## License\n\nMIT © Aaron Oxborrow\n","readmeFilename":"README.md"}