team-telnyx / telnyx-node

Node SDK for the Telnyx API
https://developers.telnyx.com/docs/api/v2/overview
MIT License
54 stars 20 forks source link
hacktoberfest

Telnyx Node.js Library

Version Build Status Coverage Status Downloads Try on RunKit Join Slack

The Telnyx Node library provides convenient access to the Telnyx API from applications written in server-side JavaScript.

Documentation

See the Node API docs.

Installation

Install the package with:

npm install telnyx --save

Usage

The package needs to be configured with your account's API key which is available in your the Telnyx Mission Control Portal. Require it with the key's value:

const telnyx = require('telnyx')('KEY123456...');

const messagingProfile = await telnyx.messagingProfiles.create({
  name: 'Summer Campaign'
});

Or with versions of Node.js prior to v7.9:

var telnyx = require('telnyx')('KEY123456...');

telnyx.messagingProfiles.create(
  { name: 'Summer Campaign' },
  function(err, messagingProfile) {
    err; // null if no error occurred
    messagingProfile; // the created messaging profile object
  }
);

Or using ES modules, this looks more like:

import Telnyx from 'telnyx';
const telnyx = Telnyx('KEY...');
//…

Using Promises

Every method returns a chainable promise which can be used instead of a regular callback:

// Create a new messaging profile and then send a message using that profile:
telnyx.MessagingProfiles.create({
  name: 'Summer Campaign'
}).then((messagingProfile) => {
  return telnyx.MessagingPhoneNumbers.update(
    '+18005554000',
    {
      'messaging_profile_id': messagingProfile.data.id
    }
  );
}).catch((err) => {
  // Deal with an error
});

Configuring Timeout

Request timeout is configurable (the default is Node's default of 120 seconds):

telnyx.setTimeout(20000); // in ms (this is 20 seconds)

Configuring a Proxy

An https-proxy-agent can be configured with setHttpAgent.

To use telnyx behind a proxy you can pass to sdk:

if (process.env.http_proxy) {
  const ProxyAgent = require('https-proxy-agent');
  telnyx.setHttpAgent(new ProxyAgent(process.env.http_proxy));
}

Network retries

Automatic network retries can be enabled with setMaxNetworkRetries. This will retry requests n times with exponential backoff if they fail due to an intermittent network problem.

// Retry a request once before giving up
telnyx.setMaxNetworkRetries(1);

Examining Responses

Some information about the response which generated a resource is available with the lastResponse property:

messagingProfile.lastResponse.requestId // see: https://telnyx.com/docs/api/node#request_ids
messagingProfile.lastResponse.statusCode

request and response events

The Telnyx object emits request and response events. You can use them like this:

const telnyx = require('telnyx')('KEY...');

const onRequest = (request) => {
  // Do something.
}

// Add the event handler function:
telnyx.on('request', onRequest);

// Remove the event handler function:
telnyx.off('request', onRequest);

request object

{
  method: 'POST',
  path: '/v2/messaging_profiles'
}

response object

{
  method: 'POST',
  path: '/v2/messaging_profiles',
  status: 200,
  request_id: 'Ghc9r26ts73DRf',
  elapsed: 445                // Elapsed time in milliseconds
}

Webhook signing

Telnyx signs the webhook events it sends to your endpoint, allowing you to validate that they were not sent by a third-party. You can read more about it here.

Please note that you must pass the raw request body, exactly as received from Telnyx, to the constructEvent() function; this will not work with a parsed (i.e., JSON) request body.

You can find an example of how to use this with Express in the examples/webhook-signing folder, but here's what it looks like:

const event = telnyx.webhooks.constructEvent(
  webhookRawBody,
  webhookTelnyxSignatureHeader,
  webhookTelnyxTimestampHeader,
  publicKey
);

TeXML Signature

TeXML sends webhooks as form-encoded payloads instead of JSON. To validate the signature, use the telnyx.webhooks.signature.verifySignature method.

You can find an example of how to use this with Express in the examples/webhook-signing folder.

const timeToleranceInSeconds = 300; // Will validate signatures of webhooks up to 5 minutes after Telnyx sent the request
try {
  telnyx.webhooks.signature.verifySignature(
    webhookRawBody,
    webhookTelnyxSignatureHeader,
    webhookTelnyxTimestampHeader,
    publicKey,
    timeToleranceInSeconds
  );
} catch (e) {
  console.log("Failed to validate the signature")
  console.log(e);
}

Writing a Plugin

If you're writing a plugin that uses the library, we'd appreciate it if you identified using telnyx.setAppInfo():

telnyx.setAppInfo({
  name: 'MyAwesomePlugin',
  version: '1.2.34', // Optional
  url: 'https://myawesomeplugin.info', // Optional
});

This information is passed along when the library makes calls to the Telnyx API.

Auto-pagination

You can auto-paginate list methods. We provide a few different APIs for this to aid with a variety of node versions and styles.

Async iterators (for-await-of)

If you are in a Node environment that has support for async iteration, such as Node 10+ or babel, the following will auto-paginate:

for await (const messagingProfile of telnyx.messagingProfiles.list()) {
  doSomething(messagingProfile);
  if (shouldStop()) {
    break;
  }
}

autoPagingEach

If you are in a Node environment that has support for await, such as Node 7.9 and greater, you may pass an async function to .autoPagingEach:

await telnyx.messagingProfiles.list().autoPagingEach(async (messagingProfile) => {
  await doSomething(messagingProfile);
  if (shouldBreak()) {
    return false;
  }
})
console.log('Done iterating.');

Equivalently, without await, you may return a Promise, which can resolve to false to break:

telnyx.messagingProfiles.list().autoPagingEach((messagingProfile) => {
  return doSomething(messagingProfile).then(() => {
    if (shouldBreak()) {
      return false;
    }
  });
}).then(() => {
  console.log('Done iterating.');
}).catch(handleError);

If you prefer callbacks to promises, you may also use a next callback and a second onDone callback:

telnyx.messagingProfiles.list().autoPagingEach(
  function onItem(messagingProfile, next) {
    doSomething(messagingProfile, function(err, result) {
      if (shouldStop(result)) {
        next(false); // Passing `false` breaks out of the loop.
      } else {
        next();
      }
    });
  },
  function onDone(err) {
    if (err) {
      console.error(err);
    } else {
      console.log('Done iterating.');
    }
  }
)

If your onItem function does not accept a next callback parameter or return a Promise, the return value is used to decide whether to continue (false breaks, anything else continues).

autoPagingToArray

This is a convenience for cases where you expect the number of items to be relatively small; accordingly, you must pass a limit option to prevent runaway list growth from consuming too much memory.

Returns a promise of an array of all items across pages for a list request.

const allMessagingProfiles = await telnyx.messagingProfiles.list()
  .autoPagingToArray({limit: 10000});

Development

Setup

The test suite depends on the Prism Mock Server.

npm install -g @stoplight/prism-cli

# OR

yarn global add @stoplight/prism-cli

Once installed, start the prism mock service with the following command:

prism mock https://raw.githubusercontent.com/team-telnyx/openapi/master/openapi/spec3.json

One final step -- because the Node SDK originally expected to reach the legacy telnyx-mock service at port 12111 (in addition to providing a /v2/ base path), we need to setup the Telnyx mock proxy server to modify the request path and forward along to the prism mock server.

# In new terminal window

git clone git@github.com:team-telnyx/telnyx-prism-mock.git
cd telnyx-prism-mock/proxy

yarn install
node index.js

Running Tests

$ npm install
$ npm test

Run all tests with a custom telnyx-mock port:

$ TELNYX_MOCK_PORT=12000 npm test

Run a single test suite:

$ npm run mocha -- test/Error.spec.js

Run a single test (case sensitive):

$ npm run mocha -- test/Error.spec.js --grep 'Populates with type'

If you wish, you may run tests using your Telnyx Test API key by setting the environment variable TELNYX_TEST_API_KEY before running the tests:

$ export TELNYX_TEST_API_KEY='KEY....'
$ export TELNYX_MOCK_PORT='12...'
$ npm test

Debugging

To inspect values in tests first import debug:

var debug = require('debug')('foo');
//...
debug(result)

Then run the tests with:

$ DEBUG=foo npm test

To view verbose debugging for nock run the tests with:

$ DEBUG=nock.* npm test

Acknowledgements

The contributors and maintainers of Telnyx Node would like to extend their deep gratitude to the authors of Stripe Node, upon which this project is based. Thank you for developing such elegant, usable, extensible code and for sharing it with the community.