A javascript data transformation layer.
Inspired by Laravels Eloquent API Resources.
npm i resources.js
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' },
... ] }
*/
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.
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: '...' } },
*/
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' } }
*/