Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ TypeScript is supported for TypeScript version 2.9 and above.

To make sure the installation was successful, try sending yourself an SMS message, like this:

**CommonJS:**
```js
// Your AccountSID and Auth Token from console.twilio.com
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
Expand All @@ -54,6 +55,25 @@ client.messages
.then((message) => console.log(message.sid));
```

**ESM/ES6 Modules:**
```js
// Your AccountSID and Auth Token from console.twilio.com
import twilio from 'twilio';

const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';

const client = twilio(accountSid, authToken);

client.messages
.create({
body: 'Hello from twilio-node',
to: '+12345678901', // Text your number
from: '+12345678901', // From a valid Twilio number
})
.then((message) => console.log(message.sid));
```

After a brief delay, you will receive the text message on your phone.

> **Warning**
Expand All @@ -80,6 +100,7 @@ If your environment requires SSL decryption, you can set the path to CA bundle i

If you invoke any V2010 operations without specifying an account SID, `twilio-node` will automatically use the `TWILIO_ACCOUNT_SID` value that the client was initialized with. This is useful for when you'd like to, for example, fetch resources for your main account but also your subaccount. See below:

**CommonJS:**
```javascript
// Your Account SID, Subaccount SID Auth Token from console.twilio.com
const accountSid = process.env.TWILIO_ACCOUNT_SID;
Expand All @@ -91,10 +112,25 @@ const mainAccountCalls = client.api.v2010.account.calls.list; // SID not specifi
const subaccountCalls = client.api.v2010.account(subaccountSid).calls.list; // SID specified as subaccountSid
```

**ESM/ES6 Modules:**
```javascript
// Your Account SID, Subaccount SID Auth Token from console.twilio.com
import twilio from 'twilio';

const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const subaccountSid = process.env.TWILIO_ACCOUNT_SUBACCOUNT_SID;

const client = twilio(accountSid, authToken);
const mainAccountCalls = client.api.v2010.account.calls.list; // SID not specified, so defaults to accountSid
const subaccountCalls = client.api.v2010.account(subaccountSid).calls.list; // SID specified as subaccountSid
```

### Lazy Loading

`twilio-node` supports lazy loading required modules for faster loading time. Lazy loading is enabled by default. To disable lazy loading, simply instantiate the Twilio client with the `lazyLoading` flag set to `false`:

**CommonJS:**
```javascript
// Your Account SID and Auth Token from console.twilio.com
const accountSid = process.env.TWILIO_ACCOUNT_SID;
Expand All @@ -105,6 +141,19 @@ const client = require('twilio')(accountSid, authToken, {
});
```

**ESM/ES6 Modules:**
```javascript
// Your Account SID and Auth Token from console.twilio.com
import twilio from 'twilio';

const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;

const client = twilio(accountSid, authToken, {
lazyLoading: false,
});
```

### Enable Auto-Retry with Exponential Backoff

`twilio-node` supports automatic retry with exponential backoff when API requests receive an [Error 429 response](https://support.twilio.com/hc/en-us/articles/360044308153-Twilio-API-response-Error-429-Too-Many-Requests-). This retry with exponential backoff feature is disabled by default. To enable this feature, instantiate the Twilio client with the `autoRetry` flag set to `true`.
Expand Down
109 changes: 109 additions & 0 deletions examples/example-esm.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Example usage of twilio-node with ESM/ES6 import syntax
import twilio, { Twilio, RestException } from "../lib-esm/index.js";

const accountSid = process.env.TWILIO_ACCOUNT_SID;
const token = process.env.TWILIO_AUTH_TOKEN;

// Uncomment the following line to specify a custom CA bundle for HTTPS requests:
// process.env.TWILIO_CA_BUNDLE = '/path/to/cert.pem';
// You can also set this as a regular environment variable outside of the code

// Option 1: Use default export (convenience function)
const client = twilio(accountSid, token);

// Option 2: Use named export (Twilio class)
// const client = new Twilio(accountSid, token);

let i = 0;
// Callback as second parameter
client.calls.each({
pageSize: 7,
callback: function (call, done) {
console.log(call.sid);
i++;
if (i === 10) {
done();
}
},
done: function (error) {
console.log("je suis fini");
console.log(error);
},
});

// Callback as first parameter
client.calls.each(function (call) {
console.log(call.sid);
});

const from = process.env.FROM_NUMBER;
const to = process.env.TO_NUMBER;

// Send message using callback with RestException handling
client.messages.create(
{
from: from,
to: to,
body: "create using callback",
},
function (err, result) {
if (err) {
if (err instanceof RestException) {
console.log(`Twilio Error ${err.code}: ${err.message}`);
console.log(`Status: ${err.status}`);
console.log(`More info: ${err.moreInfo}`);
} else {
console.log("Other error:", err);
}
return;
}
console.log("Created message using callback");
console.log(result.sid);
}
);

// Send message using promise with RestException handling
const promise = client.messages.create({
from: from,
to: to,
body: "create using promises",
});

promise
.then(function (message) {
console.log("Created message using promises");
console.log(message.sid);
})
.catch(function (error) {
if (error instanceof RestException) {
console.log(`Twilio Error ${error.code}: ${error.message}`);
console.log(`Status: ${error.status}`);
console.log(`More info: ${error.moreInfo}`);
} else {
console.log("Other error:", error);
}
});

// Using async/await syntax (ESM makes this even more natural)
async function sendMessageAsync() {
try {
const message = await client.messages.create({
from: from,
to: to,
body: "create using async/await",
});
console.log("Created message using async/await");
console.log(message.sid);
} catch (error) {
if (error instanceof RestException) {
console.log(`Twilio Error ${error.code}: ${error.message}`);
console.log(`Status: ${error.status}`);
console.log(`More info: ${error.moreInfo}`);
} else {
console.log("Other error:", error);
}
}
}

// Uncomment to run async example
// sendMessageAsync();
49 changes: 49 additions & 0 deletions lib-esm/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// ESM wrapper for twilio-node
import { createRequire } from "module";
const require = createRequire(import.meta.url);

// Import the CommonJS module
const TwilioSDK = require("../lib/index.js");

// Extract all exports from the CJS module
const {
Twilio,
jwt,
twiml,
RequestClient,
RestException,
ClientCredentialProviderBuilder,
OrgsCredentialProviderBuilder,
NoAuthCredentialProvider,
validateBody,
validateRequest,
validateRequestWithBody,
validateExpressRequest,
validateIncomingRequest,
getExpectedBodyHash,
getExpectedTwilioSignature,
webhook,
} = TwilioSDK;

// Export everything as named exports
export {
Twilio,
jwt,
twiml,
RequestClient,
RestException,
ClientCredentialProviderBuilder,
OrgsCredentialProviderBuilder,
NoAuthCredentialProvider,
validateBody,
validateRequest,
validateRequestWithBody,
validateExpressRequest,
validateIncomingRequest,
getExpectedBodyHash,
getExpectedTwilioSignature,
webhook,
};

// Also provide default export for convenience
export default TwilioSDK;
3 changes: 3 additions & 0 deletions lib-esm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
15 changes: 13 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,16 @@
"typedoc": "^0.28.11"
},
"scripts": {
"test": "npm run test:javascript && npm run test:typescript",
"test": "npm run test:javascript && npm run test:typescript && npm run test:esm",
"test:javascript": "jest spec --coverage --detectOpenHandles --testPathIgnorePatterns=spec/cluster",
"test:typescript": "tsc --noEmit",
"test:esm": "node scripts/verify-esm.js",
"jshint": "jshint src/rest/** src/base/** src/http/**",
"jscs": "eslint src/base/**/**.js src/http/**/**.js --fix",
"prepublish": "npm run build",
"build": "tsc",
"build": "npm run build:cjs && npm run build:esm && npm run prettier",
"build:cjs": "tsc",
"build:esm": "node scripts/build-esm.js",
"check": "npm run jshint && npm run jscs",
"ci": "npm run test && npm run nsp && npm run prettier-check",
"nsp": "npm audit --production",
Expand All @@ -65,11 +68,19 @@
},
"files": [
"lib",
"lib-esm",
"index.js",
"index.d.ts"
],
"main": "./lib",
"module": "./lib-esm/index.js",
"types": "./index.d.ts",
"exports": {
".": {
"import": "./lib-esm/index.js",
"require": "./lib/index.js"
}
},
"engines": {
"node": ">=14.0"
},
Expand Down
77 changes: 77 additions & 0 deletions scripts/build-esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const fs = require("fs");
const path = require("path");

// Create lib-esm directory
const libEsmDir = path.join(__dirname, "..", "lib-esm");
if (!fs.existsSync(libEsmDir)) {
fs.mkdirSync(libEsmDir);
}

// ESM wrapper for the main entry point
const esmIndexContent = `// ESM wrapper for twilio-node
import { createRequire } from 'module';
const require = createRequire(import.meta.url);

// Import the CommonJS module
const TwilioSDK = require('../lib/index.js');

// Extract all exports from the CJS module
const {
Twilio,
jwt,
twiml,
RequestClient,
RestException,
ClientCredentialProviderBuilder,
OrgsCredentialProviderBuilder,
NoAuthCredentialProvider,
validateBody,
validateRequest,
validateRequestWithBody,
validateExpressRequest,
validateIncomingRequest,
getExpectedBodyHash,
getExpectedTwilioSignature,
webhook
} = TwilioSDK;

// Export everything as named exports
export {
Twilio,
jwt,
twiml,
RequestClient,
RestException,
ClientCredentialProviderBuilder,
OrgsCredentialProviderBuilder,
NoAuthCredentialProvider,
validateBody,
validateRequest,
validateRequestWithBody,
validateExpressRequest,
validateIncomingRequest,
getExpectedBodyHash,
getExpectedTwilioSignature,
webhook
};

// Also provide default export for convenience
export default TwilioSDK;
`;

fs.writeFileSync(path.join(libEsmDir, "index.js"), esmIndexContent);

// Create package.json for ESM directory
const esmPackageJson = {
type: "module",
};

fs.writeFileSync(
path.join(libEsmDir, "package.json"),
JSON.stringify(esmPackageJson, null, 2)
);

console.log("ESM build completed!");
console.log("Generated files:");
console.log("- lib-esm/index.js");
console.log("- lib-esm/package.json");
Loading
Loading