You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
5.1 KiB
187 lines
5.1 KiB
# jsonapi-datastore |
|
[![Build Status](https://travis-ci.org/beauby/jsonapi-datastore.svg)](https://travis-ci.org/beauby/jsonapi-datastore) |
|
|
|
JavaScript client-side [JSON API](http://jsonapi.org) data handling made easy. |
|
|
|
Current version is v0.4.0-beta. It is still a work in progress, but should do what it says. |
|
|
|
## Description |
|
|
|
The [JSONAPI](http://jsonapi.org) standard is great for exchanging data (which is its purpose), but the format is not ideal to work directly with in an application. |
|
jsonapi-datastore is a JavaScript framework-agnostic library (but an [AngularJS version](#angularjs) is provided for convenience) that takes away the burden of handling [JSONAPI](http://jsonapi.org) data on the client side. |
|
|
|
What it does: |
|
- read JSONAPI payloads, |
|
- rebuild the underlying data graph, |
|
- allows you to query models and access their relationships directly, |
|
- create new models, |
|
- serialize models for creation/update. |
|
|
|
What it does not do: |
|
- make requests to your API. You design your endpoints URLs, the way you handle authentication, caching, etc. is totally up to you. |
|
|
|
## Installing |
|
|
|
Install jsonapi-datastore with `bower` by running: |
|
``` |
|
$ bower install jsonapi-datastore |
|
``` |
|
or with `npm` by running: |
|
``` |
|
$ npm install jsonapi-datastore |
|
``` |
|
|
|
## Parsing data |
|
|
|
Just call the `.sync()` method of your store. |
|
```javascript |
|
var store = new JsonApiDataStore(); |
|
store.sync(data); |
|
``` |
|
This parses the data and incorporates it in the store, taking care of already existing records (by updating them) and relationships. |
|
|
|
## Parsing with meta data |
|
|
|
If you have meta data in your payload use the `.syncWithMeta` method of your store. |
|
```javascript |
|
var store = new JsonApiDataStore(); |
|
store.syncWithMeta(data); |
|
``` |
|
This does everything that `.sync()` does, but returns an object with data and meta split. |
|
|
|
## Retrieving models |
|
|
|
Just call the `.find(type, id)` method of your store. |
|
```javascript |
|
var article = store.find('article', 123); |
|
``` |
|
or call the `.findAll(type)` method of your store to get all the models of that type. |
|
```javascript |
|
var articles = store.findAll('article'); |
|
``` |
|
All the attributes *and* relationships are accessible through the model as object properties. |
|
```javascript |
|
console.log(article.author.name); |
|
``` |
|
In case a related resource has not been fetched yet (either as a primary resource or as an included resource), the corresponding property on the model will contain only the `type` and `id` (and the `._placeHolder` property will be set to `true`). However, the models are *updated in place*, so you can fetch a related resource later, and your data will remain consistent. |
|
|
|
## Serializing data |
|
|
|
Just call the `.serialize()` method on the model. |
|
```javascript |
|
console.log(article.serialize()); |
|
``` |
|
|
|
## Examples |
|
|
|
```javascript |
|
// Create a store: |
|
var store = new JsonApiDataStore(); |
|
|
|
// Then, given the following payload, containing two `articles`, with a related `user` who is the author of both: |
|
var payload = { |
|
data: [{ |
|
type: 'article', |
|
id: 1337, |
|
attributes: { |
|
title: 'Cool article' |
|
}, |
|
relationships: { |
|
author: { |
|
data: { |
|
type: 'user', |
|
id: 1 |
|
} |
|
} |
|
} |
|
}, { |
|
type: 'article', |
|
id: 300, |
|
attributes: { |
|
title: 'Even cooler article' |
|
}, |
|
relationships: { |
|
author: { |
|
data: { |
|
type: 'user', |
|
id: 1 |
|
} |
|
} |
|
} |
|
}] |
|
}; |
|
|
|
// we can sync it: |
|
var articles = store.sync(payload); |
|
|
|
// which will return the list of synced articles. |
|
|
|
// Later, we can retrieve one of those: |
|
var article = store.find('article', 1337); |
|
|
|
// If the author resource has not been synced yet, we can only access its id and its type: |
|
console.log(article.author); |
|
// { id: 1, _type: 'article' } |
|
|
|
// If we do sync the author resource later: |
|
var authorPayload = { |
|
data: { |
|
type: 'user', |
|
id: 1, |
|
attributes: { |
|
name: 'Lucas' |
|
} |
|
} |
|
}; |
|
|
|
store.sync(authorPayload); |
|
|
|
// we can then access the author's name through our old `article` reference: |
|
console.log(article.author.name); |
|
// 'Lucas' |
|
|
|
// We can also serialize any whole model in a JSONAPI-compliant way: |
|
console.log(article.serialize()); |
|
// ... |
|
// or just a subset of its attributes/relationships: |
|
console.log(article.serialize({ attributes: ['title'], relationships: []})); |
|
// ... |
|
``` |
|
|
|
## Documentation |
|
|
|
See [DOCUMENTATION.md](DOCUMENTATION.md). |
|
|
|
## What's missing |
|
|
|
Currently, the store does not handle `links` attributes or resource-level or relationship-level meta. |
|
|
|
## Notes |
|
|
|
### AngularJS |
|
|
|
jsonapi-datastore is bundled with an AngularJs wrapper. Just include `ng-jsonapi-datastore.js` in your `index.html` and require the module `beauby.jsonApiDataStore` in your application. |
|
You can then use the `JsonApiDataStore` factory, which is essentially defined as follows: |
|
```javascript |
|
{ |
|
store: new JsonApiDataStore(), |
|
Model: JsonApiDataStoreModel |
|
} |
|
``` |
|
so that you can use it as follows: |
|
|
|
```javascript |
|
angular |
|
.module('myApp') |
|
.controller('myController', function(JsonApiDataStore) { |
|
var article = JsonApiDataStore.store.find('article', 1337); |
|
var newArticle = new JsonApiDataStore.Model('article'); |
|
newArticle.setAttribute('title', 'My cool article'); |
|
console.log(newArticle.serialize()); |
|
}); |
|
``` |
|
|
|
|
|
## Contributing |
|
|
|
All pull-requests welcome!
|
|
|