/API-Resources

A data transformation layer for javascript.

Primary LanguageJavaScriptMIT LicenseMIT

Coverage Status Build Status

resources.js

A javascript data transformation layer.

Inspired by Laravels Eloquent API Resources.

Installation

npm i resources.js

Basic Usage

Create a resource, UserResource.js.

const Resource = require('resources.js');

class UserResource extends Resource {
  toArray() {
    return {
      id: Number(this.id),
      name: this.name,
      email: this.email,
      created_at: this.created_at,
      updated_at: this.updated_at,
    }
  }
}

module.exports = UserResource;

Create some data, maybe in index.js

const data = [{
  id: '1',
  name: 'Bob',
  email: 'bob@bob.com',
  created_at: 'today',
  updated_at: 'today',
  posts: [{
      title: 'im cool'
    },
    {
      title: 'so cool cool'
    },
  ]
}, {
  id: '2',
  name: 'Waldo',
  email: 'waldo@waldo.com',
  created_at: 'today',
  updated_at: 'today',
}];

Then you can transform a single item:

const single = new UserResource(data[0]);
console.log(single);
/**
 *  { data:
      { id: 1,
        name: 'Bob',
        email: 'bob@bob.com',
        posts:
         { data:
            [ { title: 'im cool - Title' },
              { title: 'so cool cool - Title' } ] },
        created_at: 'today',
        updated_at: 'today' } }
 */

Or all of them

const collection = UserResource.collection(data);
console.log(collection);
/**
 *  { data:
      [ { id: 1,
          name: 'Bob',
          email: 'bob@bob.com',
          posts:
           { data:
              [ { title: 'im cool - Title' },
                { title: 'so cool cool - Title' } ] },
          created_at: 'today',
          updated_at: 'today' },
        ... ] }
 */

Advance Usage

Data wrapper

You can enable the data wrapper by passing true to the second arguement for both methods.

const single = new UserResource(data[0], false);
console.log(single);
/**
 *  { id: 1,
     name: 'Bob',
     email: 'bob@bob.com',
     created_at: 'today',
     updated_at: 'today' } }
 */

Or all of them

const collection = UserResource.collection(data, false);
console.log(collection);
/**
 *  [ { id: 1,
       name: 'Bob',
       email: 'bob@bob.com',
       created_at: 'today',
       updated_at: 'today' },
     { id: 2,
       name: 'Waldo',
       email: 'waldo@waldo.com',
       posts: { data: [] },
       created_at: 'today',
       updated_at: 'today' } ]
 */

If you pass a data key to collections you cannot disable this option.

Pagination

If you pass a data key to collections your transformation will be merged with the rest of the passed object.

Let's use a simple Paginator class.

class Paginator {
  constructor(data) {
    return {
      data,
      meta: {
        page: 1,
        total: data.length
      },
      links: {
        nextPage: '...',
        prevPage: '...'
      }
    }
  }
}

We'll return our data as data key along with other pagination information like meta and links

Now we can call collection with the paginator

const paginated = UserResource.collection(new Paginator(data));
console.log(paginated);
/**
 *  { data:
      [ { id: 1,
          name: 'Bob',
          email: 'bob@bob.com',
          created_at: 'today',
          updated_at: 'today' },
        ...
     meta: { page: 1, total: 2 },
     links: { nextPage: '...', prevPage: '...' } },
 */

Nested Resources

Transforming nested resources is not to difficult, just create a new resource like PostResource.js

const Resource = require('resources.js');

class PostResource extends Resource {
  toArray() {
    return {
      title: `${this.title} - Title`
    }
  }
}

module.exports = PostResource;

Then modify the UserResource

class UserResource extends Resource {
  toArray() {
    return {
      id: Number(this.id),
      name: this.name,
      email: this.email,
      posts: PostResource.collection(this.posts),
      created_at: this.created_at,
      updated_at: this.updated_at,
    }
  }
}

Now when you do a transformation you'll see posts

/**
 *  { id: 1,
     name: 'Bob',
     email: 'bob@bob.com',
     posts:
      { data:
         [ { title: 'im cool - Title' },
           { title: 'so cool cool - Title' } ] },
     created_at: 'today',
     updated_at: 'today' } }
 */