fastly-promises

Promise based Fastly API client for Node.js

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
fastly-promises
1470.9.05 years ago5 years agoMinified + gzip package size for fastly-promises in KB

Readme

fastly-promises
Promise based Fastly API client for Node.js

travis build codecov coverage npm version npm downloads npm license
NPM

Problem

The callback based fastly package is still the most used client on NPM. However, I needed a client which allows me to perform request sequentially and parallelly without ending up in an untamable callback hell!

Solution

The fastly-promises package uses the promise based HTTP client Axios to perform requests to the Fastly API. Axios supports the native JavaScript Promise API and automatically transforms the data into JSON. Each fastly-promises API method returns a Promise which represents either the completion or failure of the request.

Table of Contents

Security

You'll need a Fastly API Token in order to use the fastly-promises library. I recommend to use a token with a global scope to be able to use all fastly-promises API methods.

Install

This is a Node.js module available through the npm registry. Installation is done using the npm install command:
$ npm install fastly-promises

Usage

const fastly = require('fastly-promises');

// create one or more instances
const service_1 = fastly('token', 'service_id_1');
const serivce_2 = fastly('token', 'service_id_2');

// read/write baseURL property
console.log(service_1.request.defaults.baseURL); // https://api.fastly.com

// read/write timeout property
console.log(service_1.request.defaults.timeout); // 3000

Promises

Purge all domains of the active version:
  1. Get all the versions
  2. Filter out the active version
  3. Get all the domains for the active version
  4. Purge all the domains
  5. Log the status text for each purge request

const fastly = require('fastly-promises');

const service = fastly('token', 'service_id');

function handler() {
  service.readVersions()
    .then(versions => {
      const active = versions.data.filter(version => version.active)[0];
      return service.readDomains(active.number);
    })
    .then(domains => {
      return Promise.all(domains.data.map(domain => service.purgeIndividual(domain.name)));
    })
    .then(purges => {
      purges.forEach(purge => console.log(purge.statusText));
    })
    .catch(e => {
      console.log('Shoot!');
    });
}

Async/Await

Update first_byte_timeout property for every backend and service if the value is less than 5000 milliseconds:
  1. Get all the services associated with the Fastly API token
  2. Filter out the service IDs
  3. Iterate over all services synchronously
  4. Get all the versions
  5. Filter out the active version
  6. Get all the backends for the active version
  7. Filter out the affected backends
  8. Continue with the next service if there are no affected backends
  9. Clone the active version
  10. Update all the affected backends parallelly
  11. Activate the cloned version

const fastly = require('fastly-promises');

const account = fastly('token');

async function handler() {
  try {
    const services = await account.readServices();
    const ids = services.data.map(service => service.id);

    for (const id of ids) {
      const service = fastly('token', id);
      const versions = await service.readVersions();
      const active = versions.data.filter(version => version.active)[0];
      const backends = await service.readBackends(active.number);
      const affected = backends.data.filter(backend => backend.first_byte_timeout < 5000);

      if (!affected.length) continue;

      const clone = await service.cloneVersion(active.number);
      await Promise.all(affected.map(backend => service.updateBackend(clone.data.number, backend.name, { first_byte_timeout: 5000 })));
      await service.activateVersion(clone.data.number);
    }
  } catch (e) {
    console.log('Shoot!');
  }
}

Response Schema

Each fastly-promises API method returns the following response object:
{
  // the HTTP status code from the server response
  status: 200,

  // the HTTP status message from the server response
  statusText: 'OK',

  // the headers that the server responded with
  headers: {},

  // the config that was provided to axios for the request
  config: {},

  // the request that generated the response
  request: {},

  // the response that was provided by the server
  data: {}
}

API

- Properties
- [.request.defaults.baseURL](#baseURL)
- [.request.defaults.timeout](#timeout)
- Purging
- [.purgeIndividual(url)](#purgeIndividual)
- [.purgeAll()](#purgeAll)
- [.purgeKey(key)](#purgeKey)
- [.purgeKeys(keys)](#purgeKeys)
- Soft Purging
- [.softPurgeIndividual(url)](#softPurgeIndividual)
- [.softPurgeKey(key)](#softPurgeKey)
- Utilities
- [.dataCenters()](#dataCenters)
- [.publicIpList()](#publicIpList)
- [.edgeCheck(url)](#edgeCheck)
- Service
- [.readServices()](#readServices)
- Version
- [.readVersions()](#readVersions)
- [.cloneVersion(version)](#cloneVersion)
- [.activateVersion(version)](#activateVersion)
- Domain
- [.domainCheckAll(version)](#domainCheckAll)
- [.readDomains(version)](#readDomains)
- Backend
- [.readBackends(version)](#readBackends)
- [.updateBackend(version, name, data)](#updateBackend)
- VCL Snippets
- [.createSnippet(version, data)](#createSnippet)

constructor(token, serviceid)

Method for creating and initializing a new fastly-promises instance.
Example:
const fastly = require('fastly-promises');

// create one or more instances
const instance = fastly('token', 'service_id');

Kind: method
Param: token {string} The Fastly API token.
Param: serviceid {string} The Fastly service ID.
Return: instance {object} A new fastly-promises instance.

Properties

.request.defaults.baseURL

The main entry point for the Fastly API.
Example:
// read/write baseURL property
console.log(instance.request.defaults.baseURL); // https://api.fastly.com

// in case the fastly api main entry point changes one day
instance.request.defaults.baseURL = 'https://api.fastly.com/v1';

Kind: property
Return: url {string} The main entry point for the Fastly API.

.request.defaults.timeout

The number of milliseconds before the request times out.
Example:
// read/write timeout property
console.log(instance.request.defaults.timeout); // 3000

instance.request.defaults.timeout = 5000;

Kind: property
Return: milliseconds {number} The number of milliseconds before the request times out.

Purging

.purgeIndividual(url)

Instant Purge an individual URL.
Example:
instance.purgeIndividual('www.example.com')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: url {string} The URL to purge.
Return: schema {promise} The response object representing the completion or failure.

.purgeAll()

Instant Purge everything from a service.
Example:
instance.purgeAll()
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Return: schema {promise} The response object representing the completion or failure.

.purgeKey(key)

Instant Purge a particular service of items tagged with a Surrogate Key.
Example:
instance.purgeKey('key_1')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: key {string} The surrogate key to purge.
Return: schema {promise} The response object representing the completion or failure.

.purgeKeys(keys)

Instant Purge a particular service of items tagged with Surrogate Keys in a batch.
Example:
instance.purgeKeys(['key_2', 'key_3', 'key_4'])
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: keys {array} The array of surrogate keys to purge.
Return: schema {promise} The response object representing the completion or failure.

Soft Purging

.softPurgeIndividual(url)

Soft Purge an individual URL.
Example:
instance.softPurgeIndividual('www.example.com/images')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: url {string} The URL to soft purge.
Return: schema {promise} The response object representing the completion or failure.

.softPurgeKey(key)

Soft Purge a particular service of items tagged with a Surrogate Key.
Example:
instance.softPurgeKey('key_5')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: key {string} The surrogate key to soft purge.
Return: schema {promise} The response object representing the completion or failure.

Utilities

.dataCenters()

Get a list of all Fastly datacenters.
Example:
instance.dataCenters()
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Return: schema {promise} The response object representing the completion or failure.

.publicIpList()

Fastly's services IP ranges.
Example:
instance.publicIpList()
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Return: schema {promise} The response object representing the completion or failure.

.edgeCheck(url)

Retrieve headers and MD5 hash of the content for a particular URL from each Fastly edge server.
Example:
instance.edgeCheck('api.example.com')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: url {string} Full URL (host and path) to check on all nodes. If protocol is omitted, http will be assumed.
Return: schema {promise} The response object representing the completion or failure.

Service

.readServices()

List all services.
Example:
instance.readServices()
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Return: schema {promise} The response object representing the completion or failure.

Version

.readVersions()

List the versions for a particular service.
Example:
instance.readVersions()
  .then(res => {
    const active = res.data.filter(version => version.active);
    console.log(active);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Return: schema {promise} The response object representing the completion or failure.

.cloneVersion(version)

Clone the current configuration into a new version.
Example:
instance.cloneVersion('45')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: version {string} The version to be cloned.
Return: schema {promise} The response object representing the completion or failure.

.activateVersion(version)

Activate the current version.
Example:
instance.activateVersion('23')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: version {string} The version to be activated.
Return: schema {promise} The response object representing the completion or failure.

Domain

.domainCheckAll(version)

Checks the status of all domains for a particular service and version.
Example:
instance.domainCheckAll('182')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: version {string} The current version of a service.
Return: schema {promise} The response object representing the completion or failure.

.readDomains(version)

List all the domains for a particular service and version.
Example:
instance.readDomains('182')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: version {string} The current version of a service.
Return: schema {promise} The response object representing the completion or failure.

Backend

.readBackends(version)

List all backends for a particular service and version.
Example:
instance.readBackends('12')
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: version {string} The current version of a service.
Return: schema {promise} The response object representing the completion or failure.

.updateBackend(version, name, data)

Update the backend for a particular service and version.
Example:
instance.updateBackend('34', 'slow-server', { name: 'fast-server' })
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: version {string} The current version of a service.
Param: name {string} The name of the backend.
Param: data {object} The data to be sent as the request body.
Return: schema {promise} The response object representing the completion or failure.

VCL Snippets

.createSnippet(version, data)

Create a snippet for a particular service and version.
Example:
instance.createSnippet('36', {
    name: 'your_snippet',
    priority: 10,
    dynamic: 1,
    content: 'table referer_blacklist {}',
    type: 'init'
  })
  .then(res => {
    console.log(res.data);
  })
  .catch(err => {
    console.log(err.message);
  });

Kind: method
Param: version {string} The current version of a service.
Param: data {object} The data to be sent as the request body.
Return: schema {promise} The response object representing the completion or failure.

Tests

To run the test suite, first install the dependencies, then run the npm test command
:
$ npm install
$ npm test

Contribute

PRs accepted. I am open to suggestions in improving this library. Commit by:
$ npm run commit

License

Licensed under the MIT License © 2017 Philipp Schulte