Socket
Socket
Sign inDemoInstall

fetch-decorators

Package Overview
Dependencies
0
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    fetch-decorators

A set of ES7 composable decorators around the fetch api


Version published
Weekly downloads
9
Maintainers
1
Install size
11.0 kB
Created
Weekly downloads
 

Readme

Source

fetch-decorators

npm package Build Status Commitizen friendly Code Climate Test Coverage npm package

A set of composable ES7 decorators around the fetch api

Automate things request and response body parsing so you don't have to.

No dependency (oh, except a fetch polyfill maybe)

Usage TL;DR:

npm i -S fetch-decorators
class Messages {
  @extractJson
  @bodify
  @fetchify({method: 'POST'})
  post(userId) {
    return `/users/${userId}/messages`;
  }
}

const messages = new Messages();

messages.post('ArnaudRinquin')({
  content: 'Hello World',
  public: true,
  draft: false,
}).then(({response, data}) => {
  // response === the original fetch response
  // data === the JSON object returned by the server
});

Decorators

  • @fetchify: decorates a function returning a url to a fetch call with your options.
  • @bodify: prepare passed data (and extra options) into fetch-ready body options.
  • @extractJson, @extractText, @extractBlob: decorates a function returning a Response to extract its result as json, text or blob.
  • @extractAuto: decorates a function returning a Response to extract its result automatically based on response Content-Type header.

These decorators have been designed to be composable, give it a try!

@fetchify(options:?object)

This helper wraps the original function into a fetch call so it may just return a string, and then be called with optional data, headers, options.

(originalArgs) => url:string

becomes:

(originalArgs) => (options:?object) => fetchResponse:promise

import { fetchify } from 'fetch-decorators';

class Users {
  constructor(baseUrl) {
    this.baseUrl = baseUrl;
  }

  @fetchify()
  get(userId) {
    return `${this.baseUrl}/users/${userId}`;
  }

  @fetchify({
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    }
  })
  create() {
    return `${this.baseUrl}/users`;
  }
}

const userApi = new UserApi('/api');

userApi.createUser()({
  body: JSON.stringify({
    firstName: 'Walter',
    lastName: 'White',
  }
})).then(function(response){
  // Regular `fetch` response
);

userApi.getUser('fakeUserId123')().then(function(response){
  // Regular `fetch` response
});

@bodify

Takes body data and options and calls the decorated function with a proper fetch options object where options.body is passed data as a string.

(options) => orignalResult

becomes:

(originalArgs) => (data:object, extraOptions:?object) => orignalResult(options)

import { bodify } from 'fetch-decorators';

class Messages {
  @bodify
  create(userId) {
    return function(options) {
      return fetch(`/api/users/${userId}/messages`, options);
    };
  }
}

const messages = new Messages();
const messages = {
  content: 'Hello',
  draft: false,
};
const options = { method: 'POST' };

users.create('fakeUserId')(message, options).then(function(response){
  // response === the original fetch response
});

@extractJson, @extractText, @extractBlob

These decorators wrap functions returning a fetch promise with the matching Response extraction function.

(originalArgs) => fetchResponse:promise

becomes:

(originalArgs) => (options:?object) => extractionResult:promise

where the extractionResult promise resolves with : {response:Response, data:any}

import { extractJson } from 'fetch-decorators';

class Users {
  @extractJson
  get(userId) {
    return (options) => fetch(`/api/users/${userId}`, options);
  }
}

const users = new Users();

users.get('userId123')().then(function({response, data}){
  // response === the original fetch response
  // data === the extracted data, here a `user` JSON object
});

@extractAuto

This extractor has the same signature and behaviour as other extractors but will use the Reponse Content-Type header to determine the right Response method to use for data extraction.

Content types are matched this way:

'application/json': 'json'
'text/plain': 'text'
'default': 'blob'

Composition

All these decorators where designed so it's easy to use them together, just stack them! Note: obviously, the order matters.

import {
  fetchify,
  bodify,
  extractJson,
} from 'fetch-decorators';

class Messages {
  @extractJson
  @bodify
  @fetchify({method: 'POST'})
  post(userId) {
    return `/users/${userId}/messages`;
  }

  // Approximate equivalent without decorators
  // Thanks to ES6, the volume of code is roughly the same
  // But the complexity is higher and you'll probably
  // have a lot of code duplication
  mehPost(userId, data, extraOptions) {
    return fetch(`/users/${userId}/messages`, {
      method: 'POST',
      ...extraOptions,
      body: JSON.stringify(data),
    }).then((response) => response.json());
  }
}

const messagesApi = new Messages();

// Request body, as an object
const message = {
  content: 'Hello World',
  public: true,
  draft: false,
};

// Some extra options
const authHeaders = {
  headers: {
    'X-AUTH-MUCH-SECURE': '123FOO456BAR',
  },
};

messagesApi.post('ArnaudRinquin')(message, authHeaders).then(({response, data}) => {
  // response === the original fetch response
  // data === the JSON object returned by the server
});

FAQ

Is it just syntactic sugar?

Yes.

I have a more complex case where my [ headers are dynamic | I have to change fetch options | whatever ]. How do I do?

Then you should manually write your call to fetch instead of shoehorning these decorators in your code.

Keywords

FAQs

Last updated on 16 Feb 2016

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc