UNPKG

@jesseditson/dnsimple

Version:

A Node.JS client for the DNSimple API.

273 lines (272 loc) 10.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DNSimple = exports.ServerError = exports.ClientError = exports.TooManyRequestsError = exports.MethodNotAllowedError = exports.NotFoundError = exports.AuthenticationError = exports.RequestError = exports.TimeoutError = exports.toQueryString = void 0; const pkg = require("../package.json"); const accounts_1 = require("./accounts"); const billing_1 = require("./billing"); const certificates_1 = require("./certificates"); const contacts_1 = require("./contacts"); const domains_1 = require("./domains"); const identity_1 = require("./identity"); const oauth_1 = require("./oauth"); const registrar_1 = require("./registrar"); const services_1 = require("./services"); const templates_1 = require("./templates"); const tlds_1 = require("./tlds"); const vanity_name_servers_1 = require("./vanity_name_servers"); const webhooks_1 = require("./webhooks"); const zones_1 = require("./zones"); __exportStar(require("./types"), exports); const toQueryString = (params) => { const queryParams = []; for (const [name, value] of Object.entries(params)) { if (value == null || value === false) { continue; } let queryString = encodeURIComponent(name); if (value !== true) { queryString += "=" + encodeURIComponent(value.toString()); } queryParams.push(queryString); } return queryParams.join("&"); }; exports.toQueryString = toQueryString; const versionedPath = (path, params) => { let versionedPath = `/v2${path}`; const queryString = (0, exports.toQueryString)(params); if (queryString) { versionedPath = `${versionedPath}?${queryString}`; } return versionedPath; }; class TimeoutError extends Error { } exports.TimeoutError = TimeoutError; class RequestError extends Error { constructor(status, description) { super(description); this.status = status; } } exports.RequestError = RequestError; class AuthenticationError extends RequestError { constructor(data) { super(401, "Authentication error"); this.data = data; } } exports.AuthenticationError = AuthenticationError; class NotFoundError extends RequestError { constructor(data) { super(404, "Not found"); this.data = data; } } exports.NotFoundError = NotFoundError; class MethodNotAllowedError extends RequestError { constructor() { super(405, "Method not allowed"); } } exports.MethodNotAllowedError = MethodNotAllowedError; class TooManyRequestsError extends RequestError { constructor() { super(429, "Too many requests"); } } exports.TooManyRequestsError = TooManyRequestsError; class ClientError extends RequestError { constructor(status, data) { super(status, "Bad request"); this.data = data; } // This is a standard method across all our clients to get the errors from a failed response. attributeErrors() { return this.data.errors; } } exports.ClientError = ClientError; class ServerError extends RequestError { constructor(status, data) { super(status, "Server error"); this.data = data; } } exports.ServerError = ServerError; // Cloudflare workers will hoist requires when compiling, so we can't use // require conditionally. Instead, hoist them manually and store the error if we // have one, so that if we feature detect node and they still fail, we can throw // the right error. let NODE_IMPORTS; let NODE_IMPORT_ERR; try { const { Buffer } = require("buffer"); const https = require("https"); NODE_IMPORTS = { Buffer, https }; } catch (e) { NODE_IMPORT_ERR = e; } const getFetcherForPlatform = () => { if ( // @ts-ignore detect browser typeof window == "object" || // @ts-ignore detect web worker or cloudflare worker typeof WorkerGlobalScope !== undefined) { return (_a) => __awaiter(void 0, void 0, void 0, function* () { var { url, timeout } = _a, req = __rest(_a, ["url", "timeout"]); const abortController = new AbortController(); if (timeout) { setTimeout(() => abortController.abort(), timeout); } try { const res = yield fetch(url, Object.assign(Object.assign({}, req), { signal: abortController.signal })); const status = res.status; const body = yield res.text(); return { status, body }; } catch (err) { // Don't just check `err.name == "AbortError"`, as that could be any AbortController and aborted for any reason. Only `abortController` signifies tiemout. if (abortController.signal.aborted) { throw new TimeoutError(); } throw err; } }); } if (NODE_IMPORT_ERR) { throw NODE_IMPORT_ERR; } const { Buffer, https } = NODE_IMPORTS; return ({ url, method, headers, timeout, body }) => new Promise((resolve, reject) => { const req = https.request(url, { method, headers, timeout, }); req .on("response", (res) => { const chunks = Array(); res .on("data", (chunk) => chunks.push(chunk)) .on("end", () => resolve({ status: res.statusCode, body: Buffer.concat(chunks).toString("utf-8"), })) .on("error", reject); }) .on("timeout", () => { // A Promise can only be fulfilled once, so we don't need to flag this; any further "error" events with `reject` calls will do nothing. req.destroy(); reject(new TimeoutError()); }) .on("error", reject) .end(body); }); }; class DNSimple { constructor({ accessToken, baseUrl = DNSimple.DEFAULT_BASE_URL, fetcher = getFetcherForPlatform(), timeout = DNSimple.DEFAULT_TIMEOUT, userAgent = "", } = {}) { this.accounts = new accounts_1.Accounts(this); this.billing = new billing_1.Billing(this); this.certificates = new certificates_1.Certificates(this); this.contacts = new contacts_1.Contacts(this); this.domains = new domains_1.Domains(this); this.identity = new identity_1.Identity(this); this.oauth = new oauth_1.OAuth(this); this.registrar = new registrar_1.Registrar(this); this.services = new services_1.Services(this); this.templates = new templates_1.Templates(this); this.tlds = new tlds_1.Tlds(this); this.vanityNameServers = new vanity_name_servers_1.VanityNameServers(this); this.webhooks = new webhooks_1.Webhooks(this); this.zones = new zones_1.Zones(this); this.accessToken = accessToken; this.baseUrl = baseUrl; this.fetcher = fetcher; this.timeout = timeout; this.userAgent = userAgent; } request(method, path, body, params) { return __awaiter(this, void 0, void 0, function* () { const timeout = this.timeout; const headers = { Authorization: `Bearer ${this.accessToken}`, Accept: "application/json", "Content-Type": "application/json", "User-Agent": `${this.userAgent} ${DNSimple.DEFAULT_USER_AGENT}`.trim(), }; const { status, body: data } = yield this.fetcher({ url: this.baseUrl + versionedPath(path, params), method, headers, timeout, body: body == null ? undefined : JSON.stringify(body), }); if (status === 401) { throw new AuthenticationError(JSON.parse(data)); } if (status === 404) { throw new NotFoundError(JSON.parse(data)); } if (status === 405) { throw new MethodNotAllowedError(); } if (status === 429) { throw new TooManyRequestsError(); } if (status >= 400 && status < 500) { throw new ClientError(status, JSON.parse(data)); } if (status === 204) { return {}; } if (status >= 200 && status < 300) { return !data ? {} : JSON.parse(data); } if (status >= 500) { throw new ServerError(status, JSON.parse(data)); } throw new Error(`Unsupported status code: ${status}`); }); } } exports.DNSimple = DNSimple; DNSimple.VERSION = pkg.version; DNSimple.DEFAULT_TIMEOUT = 120000; DNSimple.DEFAULT_BASE_URL = "https://api.dnsimple.com"; DNSimple.DEFAULT_USER_AGENT = `dnsimple-node/${DNSimple.VERSION}`;