Needlessly Postulating Minds

    swaddle

    0.7.0 • Public • Published

    swaddle


    Automagically create API clients/wrappers in JavaScript. This is a great alternative for when client libraries don't already exist, and they can't be easily generated from a swagger API. How does it work? ES6 proxies!

    let repos = await github.users('octocat').repos.get()
    // GET https://api.github.com/users/octocat/repos

    Build Status

    Overview

    The library wraps an API, returning an object that builds the target URL with each property and invocation. It performs the request when an HTTP method is invoked. Properties reserved for HTTP methods include: get, post, put, patch, delete, head, and options.

    The library also comes with some sane defaults for JSON APIs. Two options are set to true by default: json and returnBody. JSON response bodies are parsed, and the response body itself is returned instead of the response object. In the example below, we also make use of the camelCase option, which creates a camelCase client for a snake_case JSON API.

    let swaddle = require('swaddle')
    let github = swaddle('https://api.github.com', {camelCase: true})
     
    // GET https://api.github.com/users/octocat
    let user = await github.users.get('octocat')
    user.publicRepos // instead of user.public_repos
     
    // Without async/await
    github.users.get('octocat').then((user) => {
      // ...
    })
     
    // GET https://api.github.com/users/octocat/repos
    let repos = await github.users('octocat').get()
     
    // GET https://api.github.com/repos/octocat/Spoon-Knife/stargazers
    let stargazers = await github.repos('octocat', 'Spoon-Knife').stargazers.get()
     
    // GET https://api.github.com/search/repositories?q=tetris
    let results = await github.search.repositories.get('?q=tetris')
     
    // Identical operations, both perform
    // GET https://api.example.com/users/octocat
    await github.users('octocat').get()
    await github.users().get('octocat')

    The library is compatible with a range of HTTP request clients, including: got, request, request-promise, whatwg-fetch, and node-fetch.

    None are installed as a dependency, giving you the freedom to pick your favorite. Unless provided, it will default to trying to require got, request-promise, request, or the browser's fetch, in that order.

    let swaddle = require('swaddle')
    let request = require('request')
    let github = swaddle('https://api.github.com', {
      fn: request // Use `request` to perform requests
    })
     
    github.users('octocat').repos.get((err, repos) => {
      // GET https://api.github.com/users/octocat/repos
      // request uses callbacks instead of promises
    })

    Installation

    npm install --save swaddle
    npm install got # optional

    Options

    Options are passed to the underlying request library in two ways. The first, is during initialization:

    let client = swaddle('https://api.example.com', {
      headers: {
        Authorization: 'Basic ' + Buffer.from('User:Pass').toString('base64')
      }
    })

    Any options set during initialization will be stored and inherited by all requests to that API, unless otherwise overwritten. That is, in the following request, both basic auth and the custom header would be set:

    client.search.get('?q=foo', {
      headers: {'x-custom-header': 'value'}
    }).then((res) => {
      // ...
    })

    All options are passed through to the underlying request function, except for those reserved by swaddle.

    aliases

    Creates aliases for the supplied HTTP methods. Default: none

    let swaddle = require('swaddle')
    let client = swaddle('https://api.example.com', {
      aliases: {create: 'post', destroy: 'delete'}
    })
     
    client.threads.create({body: {subject: 'hi'}}).then((res) => {
      // POST https://api.example.com/threads
      // body: '{"subject": "hi"}'
    })

    fn

    The request function to use. Unless provided, it will default to requiring got, request-promise, request, or the browser's fetch, in that order.

    let swaddle = require('swaddle')
    let request = require('request-promise')
    let client = swaddle('https://api.example.com', {
      fn: request
    })

    returnBody

    Returns the response body instead of response object. Default: true

    let swaddle = require('swaddle')
     
    let client = swaddle('https://api.example.com')
    client.users.get().then((res) => {
      // Don't need to access res.body
    })
     
    client = swaddle('https://api.example.com', {returnBody: false})
    client.users.get().then((err) => {
      // Need to access res.body
    })

    sendAsBody

    Any literal or object passed to post, put, or patch, is set as the request body. Thus no additional headers or options can be set at the time of the request. Combined with aliases, it can prevent an otherwise leaky HTTP abstraction. Default: false

    let swaddle = require('swaddle')
    let client = swaddle('https://api.example.com', {
      aliases: {create: 'post'},
      sendAsBody: true
    })
     
    // Don't need to write:
    // client.messages.post({body: 'foo'})
     
    client.messages.create('foo').then((res) => {
      // POST https://api.example.com/messages
      // body: "foo"
    })

    json

    Parses the JSON response. This is built into some libraries, but not all (e.g. fetch). Default: true

    let swaddle = require('swaddle')
     
    let client = swaddle('https://api.example.com')
    client.users.get().then((res) => {
      // res.body has been parsed
    })
     
    client = swaddle('https://api.example.com', {json: false})
    client.users.get().then((res) => {
      // res.body is a string response
    })

    camelCase

    Creates a camelCase client for a snake_case JSON API. Only available when both returnBody and json are set to true. Camel case properties are appended as snake case to the resulting url. Arguments passed during function invocation are unaffected. Any objects request or response body are recursively formatted. Default: false

    let client = swaddle('https://api.example.com')
     
    client.jobStatuses.get((err, res) => {
      // GET http://api/job_statuses
    })
     
    client.fooBar('bazQux').get().then((res) => {
      // GET http://api/foo_bar/bazQux
    })
     
    client.users(1).get().then((res) => {
      // If the original response body was '{"is_admin": false}', then res is
      // {isAdmin: false}
    })
     
    client.users.post({
      body: {isAdmin: false, name: 'Foo Bar'}
    }).then((res) => {
      // POST http://api/users
      // body: '{"is_admin": false, "name": "Foo Bar"}'
    })

    extension

    Allows you to specify an extension to be appended to any requests, required by some APIs. Default: empty

    let swaddle = require('swaddle')
    let client = swaddle('https://api.example.com', {
      extension: 'json'
    })
     
    client.users(1).get().then((res) => {
      // https://api.example.com/users/1.json
    })
     
    client.search.get('?q=foo').then((res) => {
      // https://api.example.com/search.json?q=foo
    })

    whitelist

    Whitelists properties that can be accessed. Required when polyfilling Proxy support for older browsers. Note that the exception is thrown during the property access, and not during request execution. Accepts arrays of strings for top level resources, or objects with nested objects and arrays for listing sub-resources. Default: empty

    // Single top level resource, /user
    var client = swaddle('https://api.example.com', {
      whitelist: ['users']
    });
     
    client.users().get().then((res) => {
      // success
    });
     
    client.search
    // Error: search not listed in swaddle's whitelist
     
    // Can provide a combination of objects & arrays for sub-resources
    // Example supports: /users, /tickets, /tickets/replies, /tickets/related
    client = swaddle(BASE_URL, {
      whitelist: {
        users: [],
        tickets: ['replies', 'related'],
      }
    })
     
    client.tickets(1).replies.get().then((replies) => {
      // success
    })

    Compatibility

    The module has been tested and is compatible with the following module versions:

    package version
    got ^7
    request ^2.81.0
    request-promise ^4.2.0
    whatwg-fetch ^2.03
    node-fetch ^1.6.3

    The library makes use of Proxies, which means it works with Node 6.4+, Chrome 49+, FF 18+, Opera 36+, Safari 10+, and Edge. For older versions of Node and browsers such as IE9+ and Safari 6+, two things are required:

    • Installing a polyfill like proxy-polyfill
    • Enumerating available properties via whitelist

    This is because polyfills require that properties you want to proxy be known at creation time. In a browser with fetch, an example would then be:

    var github = swaddle('https://api.github.com', {
      whitelist: {users: ['repos']}
    });
     
    // Default to using fetch in the browser
    github.users('octocat').repos.get().then((repos) => {
      // repos
    });
     
    github.search
    // Error: search not listed in swaddle's whitelist

    For browsers, it's assumed that you're using browserify, webpack, or similar, to load the module with your build.

    Keywords

    none

    Install

    npm i swaddle

    DownloadsWeekly Downloads

    0

    Version

    0.7.0

    License

    MIT

    Last publish

    Collaborators

    • danielstjules