From 7203b67fa2d57a2ea8ffbf37cd00ca2d13b6d709 Mon Sep 17 00:00:00 2001 From: childish-sambino Date: Mon, 30 Jan 2023 14:08:45 -0600 Subject: [PATCH] fix: update exports for backwards-compatibility (#907) --- index.d.ts | 2 +- index.js | 2 +- src/base/BaseTwilio.ts | 436 +++++++++++++++++---------------- src/base/Domain.ts | 2 +- src/base/RequestClient.ts | 219 +++++++++-------- src/rest/Twilio.ts | 9 +- src/twiml/FaxResponse.ts | 2 +- src/twiml/MessagingResponse.ts | 2 +- src/twiml/VoiceResponse.ts | 2 +- 9 files changed, 349 insertions(+), 327 deletions(-) diff --git a/index.d.ts b/index.d.ts index e3d30d207b..1e39038b7e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,2 +1,2 @@ import lib from "./lib"; -export default lib; +export = lib; diff --git a/index.js b/index.js index 8513691f09..2d0545e641 100644 --- a/index.js +++ b/index.js @@ -6,4 +6,4 @@ var __importDefault = }; Object.defineProperty(exports, "__esModule", { value: true }); const lib_1 = __importDefault(require("./lib")); -exports.default = lib_1.default; +module.exports = lib_1.default; diff --git a/src/base/BaseTwilio.ts b/src/base/BaseTwilio.ts index 183048c408..7c8d900543 100644 --- a/src/base/BaseTwilio.ts +++ b/src/base/BaseTwilio.ts @@ -7,236 +7,246 @@ const moduleInfo = require("../../package.json"); /* jshint ignore:line */ const util = require("util"); /* jshint ignore:line */ const RestException = require("../base/RestException"); /* jshint ignore:line */ -export interface ClientOpts { - httpClient?: RequestClient; - accountSid?: string; - env?: NodeJS.ProcessEnv; - edge?: string; - region?: string; - lazyLoading?: boolean; - logLevel?: string; - userAgentExtensions?: string[]; - autoRetry?: boolean; - maxRetries?: number; -} - -export interface RequestOpts { - method?: HttpMethod; - uri?: string; - username?: string; - password?: string; - headers?: Headers; - params?: object; - data?: object; - timeout?: number; - allowRedirects?: boolean; - logLevel?: string; -} - -/* jshint ignore:start */ -/** - * Parent class for Twilio Client that implements request & validation logic - */ -/* jshint ignore:end */ - -export class BaseTwilio { - username: string; - password: string; - accountSid: string; - opts?: ClientOpts; - env?: NodeJS.ProcessEnv; - edge?: string; - region?: string; - logLevel?: string; - autoRetry: boolean; - maxRetries?: number; - userAgentExtensions?: string[]; - _httpClient?: RequestClient; - - /* jshint ignore:start */ - /** - * Create a BaseTwilio instance - * - * @param username - - * The username used for authentication. This is normally account sid, but if using key/secret auth will be - * the api key sid. - * @param password - - * The password used for authentication. This is normally auth token, but if using key/secret auth will be - * the secret. - * @param opts - The options argument - * - * @returns A new instance of BaseTwilio - */ - /* jshint ignore:end */ - - constructor(username?: string, password?: string, opts?: ClientOpts) { - this.opts = opts || {}; - this.env = this.opts.env || process.env; - this.username = - username || - this.env.TWILIO_ACCOUNT_SID || - (() => { - throw new Error("username is required"); - })(); - this.password = - password || - this.env.TWILIO_AUTH_TOKEN || - (() => { - throw new Error("password is required"); - })(); - this.accountSid = this.opts.accountSid || this.username; - this.edge = this.opts.edge || this.env.TWILIO_EDGE; - this.region = this.opts.region || this.env.TWILIO_REGION; - this.logLevel = this.opts.logLevel || this.env.TWILIO_LOG_LEVEL; - this.autoRetry = this.opts.autoRetry || false; - this.maxRetries = this.opts.maxRetries; - this.userAgentExtensions = this.opts.userAgentExtensions || []; - this._httpClient = this.opts.httpClient; - - if (this.opts.lazyLoading === false) { - this._httpClient = this.httpClient; - } - - if (!this.accountSid.startsWith("AC")) { - const apiKeyMsg = this.accountSid.startsWith("SK") - ? ". The given SID indicates an API Key which requires the accountSid to be passed as an additional option" - : ""; - - throw new Error("accountSid must start with AC" + apiKeyMsg); - } +namespace Twilio { + export interface ClientOpts { + httpClient?: RequestClient; + accountSid?: string; + env?: NodeJS.ProcessEnv; + edge?: string; + region?: string; + lazyLoading?: boolean; + logLevel?: string; + userAgentExtensions?: string[]; + autoRetry?: boolean; + maxRetries?: number; } - get httpClient() { - if (!this._httpClient) { - this._httpClient = new RequestClient({ - autoRetry: this.autoRetry, - maxRetries: this.maxRetries, - }); - } - return this._httpClient; + export interface RequestOpts { + method?: HttpMethod; + uri?: string; + username?: string; + password?: string; + headers?: Headers; + params?: object; + data?: object; + timeout?: number; + allowRedirects?: boolean; + logLevel?: string; } /* jshint ignore:start */ /** - * Makes a request to the Twilio API using the configured http client. - * Authentication information is automatically added if none is provided. - * - * @param opts - The options argument + * Parent class for Twilio Client that implements request & validation logic */ - /* jshint ignore:end */ - request(opts: RequestOpts): Promise { - opts = opts || {}; - - if (!opts.method) { - throw new Error("method is required"); - } + /* jshint ignore:end */ - if (!opts.uri) { - throw new Error("uri is required"); + export class Client { + username: string; + password: string; + accountSid: string; + opts?: ClientOpts; + env?: NodeJS.ProcessEnv; + edge?: string; + region?: string; + logLevel?: string; + autoRetry: boolean; + maxRetries?: number; + userAgentExtensions?: string[]; + _httpClient?: RequestClient; + + /* jshint ignore:start */ + /** + * Create a BaseTwilio instance + * + * @param username - + * The username used for authentication. This is normally account sid, but if using key/secret auth will be + * the api key sid. + * @param password - + * The password used for authentication. This is normally auth token, but if using key/secret auth will be + * the secret. + * @param opts - The options argument + * + * @returns A new instance of BaseTwilio + */ + + /* jshint ignore:end */ + + constructor(username?: string, password?: string, opts?: ClientOpts) { + this.opts = opts || {}; + this.env = this.opts.env || process.env; + this.username = + username || + this.env.TWILIO_ACCOUNT_SID || + (() => { + throw new Error("username is required"); + })(); + this.password = + password || + this.env.TWILIO_AUTH_TOKEN || + (() => { + throw new Error("password is required"); + })(); + this.accountSid = this.opts.accountSid || this.username; + this.edge = this.opts.edge || this.env.TWILIO_EDGE; + this.region = this.opts.region || this.env.TWILIO_REGION; + this.logLevel = this.opts.logLevel || this.env.TWILIO_LOG_LEVEL; + this.autoRetry = this.opts.autoRetry || false; + this.maxRetries = this.opts.maxRetries; + this.userAgentExtensions = this.opts.userAgentExtensions || []; + this._httpClient = this.opts.httpClient; + + if (this.opts.lazyLoading === false) { + this._httpClient = this.httpClient; + } + + if (!this.accountSid.startsWith("AC")) { + const apiKeyMsg = this.accountSid.startsWith("SK") + ? ". The given SID indicates an API Key which requires the accountSid to be passed as an additional option" + : ""; + + throw new Error("accountSid must start with AC" + apiKeyMsg); + } } - const username = opts.username || this.username; - const password = opts.password || this.password; - - const headers: any = opts.headers || {}; - - const pkgVersion = moduleInfo.version; - const osName = os.platform(); - const osArch = os.arch(); - const nodeVersion = process.version; - - headers["User-Agent"] = util.format( - "twilio-node/%s (%s %s) node/%s", - pkgVersion, - osName, - osArch, - nodeVersion - ); - this.userAgentExtensions?.forEach((extension) => { - headers["User-Agent"] += ` ${extension}`; - }); - headers["Accept-Charset"] = "utf-8"; - - if (opts.method === "post" && !headers["Content-Type"]) { - headers["Content-Type"] = "application/x-www-form-urlencoded"; + get httpClient() { + if (!this._httpClient) { + this._httpClient = new RequestClient({ + autoRetry: this.autoRetry, + maxRetries: this.maxRetries, + }); + } + return this._httpClient; } - if (!headers["Accept"]) { - headers["Accept"] = "application/json"; + /* jshint ignore:start */ + /** + * Makes a request to the Twilio API using the configured http client. + * Authentication information is automatically added if none is provided. + * + * @param opts - The options argument + */ + + /* jshint ignore:end */ + + request(opts: RequestOpts): Promise { + opts = opts || {}; + + if (!opts.method) { + throw new Error("method is required"); + } + + if (!opts.uri) { + throw new Error("uri is required"); + } + + const username = opts.username || this.username; + const password = opts.password || this.password; + + const headers: any = opts.headers || {}; + + const pkgVersion = moduleInfo.version; + const osName = os.platform(); + const osArch = os.arch(); + const nodeVersion = process.version; + + headers["User-Agent"] = util.format( + "twilio-node/%s (%s %s) node/%s", + pkgVersion, + osName, + osArch, + nodeVersion + ); + this.userAgentExtensions?.forEach((extension) => { + headers["User-Agent"] += ` ${extension}`; + }); + headers["Accept-Charset"] = "utf-8"; + + if (opts.method === "post" && !headers["Content-Type"]) { + headers["Content-Type"] = "application/x-www-form-urlencoded"; + } + + if (!headers["Accept"]) { + headers["Accept"] = "application/json"; + } + + var uri = new url.URL(opts.uri); + uri.hostname = this.getHostname(uri.hostname, this.edge, this.region); + + return this.httpClient?.request({ + method: opts.method, + uri: uri.href, + username: username, + password: password, + headers: headers, + params: opts.params, + data: opts.data, + timeout: opts.timeout, + allowRedirects: opts.allowRedirects, + logLevel: opts.logLevel, + }); } - var uri = new url.URL(opts.uri); - uri.hostname = this.getHostname(uri.hostname, this.edge, this.region); - - return this.httpClient?.request({ - method: opts.method, - uri: uri.href, - username: username, - password: password, - headers: headers, - params: opts.params, - data: opts.data, - timeout: opts.timeout, - allowRedirects: opts.allowRedirects, - logLevel: opts.logLevel, - }); - } - - /* jshint ignore:start */ - /** - * Adds a region and/or edge to a given hostname - * - * @param hostname - A URI hostname (e.g. api.twilio.com) - * @param targetEdge - The targeted edge location (e.g. sydney) - * @param targetRegion - The targeted region location (e.g. au1) - */ - /* jshint ignore:end */ - - getHostname( - hostname: string, - targetEdge: string | undefined, - targetRegion: string | undefined - ) { - const defaultRegion = "us1"; - - const domain = hostname.split(".").slice(-2).join("."); - const prefix = hostname.split("." + domain)[0]; - let [product, edge, region]: any = prefix.split("."); - if (edge && !region) { - region = edge; - edge = undefined; + /* jshint ignore:start */ + /** + * Adds a region and/or edge to a given hostname + * + * @param hostname - A URI hostname (e.g. api.twilio.com) + * @param targetEdge - The targeted edge location (e.g. sydney) + * @param targetRegion - The targeted region location (e.g. au1) + */ + + /* jshint ignore:end */ + + getHostname( + hostname: string, + targetEdge: string | undefined, + targetRegion: string | undefined + ) { + const defaultRegion = "us1"; + + const domain = hostname.split(".").slice(-2).join("."); + const prefix = hostname.split("." + domain)[0]; + let [product, edge, region]: any = prefix.split("."); + if (edge && !region) { + region = edge; + edge = undefined; + } + + region = targetRegion || region || (targetEdge && defaultRegion); + if (!region) { + return hostname; + } + edge = targetEdge || edge; + + return [product, edge, region, domain].filter((part) => part).join("."); } - region = targetRegion || region || (targetEdge && defaultRegion); - if (!region) { - return hostname; + /* jshint ignore:start */ + /** + * Validates that a request to the new SSL certificate is successful. + * + * @throws RestException if the request fails + * + */ + + /* jshint ignore:end */ + + validateSslCert() { + return this.httpClient + ?.request({ + method: "get", + uri: "https://api.twilio.com:8443/2010-04-01/.json", + }) + .then((response: any) => { + if (response["statusCode"] < 200 || response["statusCode"] >= 300) { + throw new RestException(response); + } + + return response; + }); } - edge = targetEdge || edge; - - return [product, edge, region, domain].filter((part) => part).join("."); - } - /* jshint ignore:start */ - /** - * Validates that a request to the new SSL certificate is successful. - * - * @throws RestException if the request fails - * - */ - /* jshint ignore:end */ - - validateSslCert() { - return this.httpClient - ?.request({ - method: "get", - uri: "https://api.twilio.com:8443/2010-04-01/.json", - }) - .then((response: any) => { - if (response["statusCode"] < 200 || response["statusCode"] >= 300) { - throw new RestException(response); - } - - return response; - }); } } + +export = Twilio; diff --git a/src/base/Domain.ts b/src/base/Domain.ts index c420ff8042..b4fb2d4786 100644 --- a/src/base/Domain.ts +++ b/src/base/Domain.ts @@ -1,4 +1,4 @@ -import { BaseTwilio, RequestOpts } from "./BaseTwilio"; +import { Client as BaseTwilio, RequestOpts } from "./BaseTwilio"; import { trim } from "./utility"; /** diff --git a/src/base/RequestClient.ts b/src/base/RequestClient.ts index 3db163f412..002f2866e4 100644 --- a/src/base/RequestClient.ts +++ b/src/base/RequestClient.ts @@ -5,8 +5,10 @@ import HttpsProxyAgent from "https-proxy-agent"; import qs from "qs"; import * as https from "https"; import Response from "../http/response"; -import Request from "../http/request"; -import { RequestOptions as LastRequestOptions, Headers } from "../http/request"; +import Request, { + RequestOptions as LastRequestOptions, + Headers, +} from "../http/request"; const DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded"; const DEFAULT_TIMEOUT = 30000; @@ -14,103 +16,6 @@ const DEFAULT_INITIAL_RETRY_INTERVAL_MILLIS = 100; const DEFAULT_MAX_RETRY_DELAY = 3000; const DEFAULT_MAX_RETRIES = 3; -export interface RequestOptions { - /** - * The HTTP method - */ - method: HttpMethod; - /** - * The request URI - */ - uri: string; - /** - * The username used for auth - */ - username?: string; - /** - * The password used for auth - */ - password?: string; - /** - * The request headers - */ - headers?: Headers; - /** - * The object of params added as query string to the request - */ - params?: TParams; - /** - * The form data that should be submitted - */ - data?: TData; - /** - * The request timeout in milliseconds - */ - timeout?: number; - /** - * Should the client follow redirects - */ - allowRedirects?: boolean; - /** - * Set to true to use the forever-agent - */ - forever?: boolean; - /** - * Set to 'debug' to enable debug logging - */ - logLevel?: string; -} - -export interface RequestClientOptions { - /** - * A timeout in milliseconds. This will be used as the HTTPS agent's socket - * timeout, AND as the default request timeout. - */ - timeout?: number; - /** - * https.Agent keepAlive option - */ - keepAlive?: boolean; - /** - * https.Agent keepAliveMSecs option - */ - keepAliveMsecs?: number; - /** - * https.Agent maxSockets option - */ - maxSockets?: number; - /** - * https.Agent maxTotalSockets option - */ - maxTotalSockets?: number; - /** - * https.Agent maxFreeSockets option - */ - maxFreeSockets?: number; - /** - * https.Agent scheduling option - */ - scheduling?: "fifo" | "lifo" | undefined; - /** - * The private CA certificate bundle (if private SSL certificate) - */ - ca?: string | Buffer; - /** - * Enable auto-retry with exponential backoff when receiving 429 Errors from - * the API. Disabled by default. - */ - autoRetry?: boolean; - /** - * Maximum retry delay in milliseconds for 429 Error response retries. - * Defaults to 3000. - */ - maxRetryDelay?: number; - /** - * Maximum number of request retries for 429 Error responses. Defaults to 3. - */ - maxRetries?: number; -} - interface BackoffAxiosRequestConfig extends AxiosRequestConfig { /** * Current retry attempt performed by Axios @@ -118,7 +23,7 @@ interface BackoffAxiosRequestConfig extends AxiosRequestConfig { retryCount?: number; } -interface ExpontentialBackoffResponseHandlerOptions { +interface ExponentialBackoffResponseHandlerOptions { /** * Maximum retry delay in milliseconds */ @@ -129,9 +34,9 @@ interface ExpontentialBackoffResponseHandlerOptions { maxRetries: number; } -function getExpontentialBackoffResponseHandler( +function getExponentialBackoffResponseHandler( axios: AxiosInstance, - opts: ExpontentialBackoffResponseHandlerOptions + opts: ExponentialBackoffResponseHandlerOptions ) { const maxIntervalMillis = opts.maxIntervalMillis; const maxRetries = opts.maxRetries; @@ -160,7 +65,7 @@ function getExpontentialBackoffResponseHandler( }; } -export default class RequestClient { +class RequestClient { defaultTimeout: number; axios: AxiosInstance; lastResponse?: Response; @@ -183,7 +88,7 @@ export default class RequestClient { * @param opts.maxRetryDelay - Max retry delay in milliseconds for 429 Too Many Request response retries. Defaults to 3000. * @param opts.maxRetries - Max number of request retries for 429 Too Many Request responses. Defaults to 3. */ - constructor(opts?: RequestClientOptions) { + constructor(opts?: RequestClient.RequestClientOptions) { opts = opts || {}; this.defaultTimeout = opts.timeout || DEFAULT_TIMEOUT; this.autoRetry = opts.autoRetry || false; @@ -224,7 +129,7 @@ export default class RequestClient { this.axios.defaults.httpsAgent = agent; if (opts.autoRetry) { this.axios.interceptors.response.use( - getExpontentialBackoffResponseHandler(this.axios, { + getExponentialBackoffResponseHandler(this.axios, { maxIntervalMillis: this.maxRetryDelay, maxRetries: this.maxRetries, }) @@ -247,7 +152,9 @@ export default class RequestClient { * @param opts.forever - Set to true to use the forever-agent * @param opts.logLevel - Show debug logs */ - request(opts: RequestOptions): Promise> { + request( + opts: RequestClient.RequestOptions + ): Promise> { if (!opts.method) { throw new Error("http method is required"); } @@ -362,3 +269,103 @@ export default class RequestClient { console.log("-- END Twilio API Request --"); } } + +namespace RequestClient { + export interface RequestOptions { + /** + * The HTTP method + */ + method: HttpMethod; + /** + * The request URI + */ + uri: string; + /** + * The username used for auth + */ + username?: string; + /** + * The password used for auth + */ + password?: string; + /** + * The request headers + */ + headers?: Headers; + /** + * The object of params added as query string to the request + */ + params?: TParams; + /** + * The form data that should be submitted + */ + data?: TData; + /** + * The request timeout in milliseconds + */ + timeout?: number; + /** + * Should the client follow redirects + */ + allowRedirects?: boolean; + /** + * Set to true to use the forever-agent + */ + forever?: boolean; + /** + * Set to 'debug' to enable debug logging + */ + logLevel?: string; + } + + export interface RequestClientOptions { + /** + * A timeout in milliseconds. This will be used as the HTTPS agent's socket + * timeout, AND as the default request timeout. + */ + timeout?: number; + /** + * https.Agent keepAlive option + */ + keepAlive?: boolean; + /** + * https.Agent keepAliveMSecs option + */ + keepAliveMsecs?: number; + /** + * https.Agent maxSockets option + */ + maxSockets?: number; + /** + * https.Agent maxTotalSockets option + */ + maxTotalSockets?: number; + /** + * https.Agent maxFreeSockets option + */ + maxFreeSockets?: number; + /** + * https.Agent scheduling option + */ + scheduling?: "fifo" | "lifo" | undefined; + /** + * The private CA certificate bundle (if private SSL certificate) + */ + ca?: string | Buffer; + /** + * Enable auto-retry with exponential backoff when receiving 429 Errors from + * the API. Disabled by default. + */ + autoRetry?: boolean; + /** + * Maximum retry delay in milliseconds for 429 Error response retries. + * Defaults to 3000. + */ + maxRetryDelay?: number; + /** + * Maximum number of request retries for 429 Error responses. Defaults to 3. + */ + maxRetries?: number; + } +} +export = RequestClient; diff --git a/src/rest/Twilio.ts b/src/rest/Twilio.ts index 873a0f3a97..411adc18d1 100644 --- a/src/rest/Twilio.ts +++ b/src/rest/Twilio.ts @@ -9,7 +9,7 @@ * Do not edit the class manually. */ -import { BaseTwilio, ClientOpts } from "../base/BaseTwilio"; +import { Client, ClientOpts, RequestOpts } from "../base/BaseTwilio"; import Accounts from "./Accounts"; import Api from "./Api"; import Autopilot from "./Autopilot"; @@ -76,7 +76,7 @@ import { ValidationRequestListInstance } from "./api/v2010/account/validationReq */ /* jshint ignore:end */ -class Twilio extends BaseTwilio { +class Twilio extends Client { /** (Twilio.Accounts) - accounts domain */ _accounts?: Accounts; /** (Twilio.Api) - api domain */ @@ -480,4 +480,9 @@ class Twilio extends BaseTwilio { } } +namespace Twilio { + export interface RequestClientOptions extends ClientOpts {} + export interface RequestOptions extends RequestOpts {} +} + export = Twilio; diff --git a/src/twiml/FaxResponse.ts b/src/twiml/FaxResponse.ts index 941f095f2b..b35e7e8e3d 100644 --- a/src/twiml/FaxResponse.ts +++ b/src/twiml/FaxResponse.ts @@ -84,4 +84,4 @@ namespace FaxResponse { } } -export default FaxResponse; +export = FaxResponse; diff --git a/src/twiml/MessagingResponse.ts b/src/twiml/MessagingResponse.ts index cd3f93fc52..be1bdb629e 100644 --- a/src/twiml/MessagingResponse.ts +++ b/src/twiml/MessagingResponse.ts @@ -199,4 +199,4 @@ namespace MessagingResponse { } } -export default MessagingResponse; +export = MessagingResponse; diff --git a/src/twiml/VoiceResponse.ts b/src/twiml/VoiceResponse.ts index c5a2f0de00..56c45b8d6f 100644 --- a/src/twiml/VoiceResponse.ts +++ b/src/twiml/VoiceResponse.ts @@ -4516,4 +4516,4 @@ namespace VoiceResponse { } } -export default VoiceResponse; +export = VoiceResponse;