diff --git a/index.html b/index.html
index 358097f..fc58022 100644
--- a/index.html
+++ b/index.html
@@ -184,14 +184,14 @@
npm i json-api-store
diff --git a/releases/v0.5.0/store.dev.js b/releases/v0.5.0/store.dev.js
new file mode 100644
index 0000000..97537da
--- /dev/null
+++ b/releases/v0.5.0/store.dev.js
@@ -0,0 +1,968 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Store = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o
+// For all details and docs: https://github.com/paulmillr/array.prototype.find
+// Fixes and tests supplied by Duncan Hall
+(function(globals){
+ if (Array.prototype.find) return;
+
+ var find = function(predicate) {
+ var list = Object(this);
+ var length = list.length < 0 ? 0 : list.length >>> 0; // ES.ToUint32;
+ if (length === 0) return undefined;
+ if (typeof predicate !== 'function' || Object.prototype.toString.call(predicate) !== '[object Function]') {
+ throw new TypeError('Array#find: predicate must be a function');
+ }
+ var thisArg = arguments[1];
+ for (var i = 0, value; i < length; i++) {
+ value = list[i];
+ if (predicate.call(thisArg, value, i, list)) return value;
+ }
+ return undefined;
+ };
+
+ if (Object.defineProperty) {
+ try {
+ Object.defineProperty(Array.prototype, 'find', {
+ value: find, configurable: true, enumerable: false, writable: true
+ });
+ } catch(e) {}
+ }
+
+ if (!Array.prototype.find) {
+ Array.prototype.find = find;
+ }
+})(this);
+
+},{}],2:[function(require,module,exports){
+'use strict';
+
+Object.defineProperty(exports, '__esModule', {
+ value: true
+});
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
+
+var AjaxAdapter = (function () {
+ function AjaxAdapter(options) {
+ _classCallCheck(this, AjaxAdapter);
+
+ this._base = options && options.base || "";
+ }
+
+ _createClass(AjaxAdapter, [{
+ key: 'create',
+ value: function create(store, type, partial, success, error, context) {
+ var _this = this;
+
+ if (error && ({}).toString.call(error) !== '[object Function]') {
+
+ this.create(store, type, partial, success, null, error);
+ } else if (store._types[type]) {
+ (function () {
+
+ var request = new XMLHttpRequest();
+
+ request.open('POST', _this._base + '/' + type, true);
+
+ request.onload = function () {
+ if (request.status >= 200 && request.status < 300) {
+ var response = JSON.parse(request.responseText);
+ try {
+ store.push(response);
+ if (success) {
+ success.call(context, store.find(response.data.type, response.data.id));
+ }
+ } catch (e) {
+ if (error) {
+ error.call(context, e);
+ }
+ }
+ } else {
+ if (error) {
+ error.call(context);
+ }
+ }
+ };
+
+ request.send({
+ data: JSON.stringify(store.convert(type, partial))
+ });
+ })();
+ } else {
+ throw new Error('Unknown type \'' + type + '\'');
+ }
+ }
+ }, {
+ key: 'destroy',
+ value: function destroy(store, type, id, success, error, context) {
+ var _this2 = this;
+
+ if (error && ({}).toString.call(error) !== '[object Function]') {
+
+ this.destroy(store, type, id, success, null, error);
+ } else if (store._types[type]) {
+ (function () {
+
+ var request = new XMLHttpRequest();
+
+ request.open('DELETE', _this2._base + '/' + type + '/' + id, true);
+
+ request.onload = function () {
+ if (request.status >= 200 && request.status < 300) {
+ try {
+ store.remove(type, id);
+ if (success) {
+ success.call(context);
+ }
+ } catch (e) {
+ error.call(context, e);
+ }
+ } else if (error) {
+ error.call(context);
+ }
+ };
+
+ request.send();
+ })();
+ } else {
+ throw new Error('Unknown type \'' + type + '\'');
+ }
+ }
+ }, {
+ key: 'load',
+ value: function load(store, type, id, options, success, error, context) {
+ var _this3 = this;
+
+ if (id && ({}).toString.call(id) === '[object Function]') {
+ this.load(store, type, null, null, id, options, success);
+ } else if (id && typeof id === "object") {
+ this.load(store, type, null, id, options, success, error);
+ } else if (options && ({}).toString.call(options) === '[object Function]') {
+ this.load(store, type, id, {}, options, success, error);
+ } else if (error && ({}).toString.call(error) !== '[object Function]') {
+ this.load(store, type, id, options, success, null, error);
+ } else if (store._types[type]) {
+ (function () {
+
+ var request = new XMLHttpRequest();
+ var url = undefined;
+
+ options = options || {};
+ url = id ? _this3._base + '/' + type + '/' + id : _this3._base + '/' + type;
+
+ if (options) {
+
+ var params = [];
+
+ if (options.fields) {
+ Object.keys(options.fields).forEach(function (field) {
+ options['fields[' + field + ']'] = options.fields[field];
+ });
+ delete options.fields;
+ }
+
+ params = Object.keys(options).map(function (key) {
+ return key + "=" + encodeURIComponent(options[key]);
+ }).sort();
+
+ if (params.length) {
+ url = url + '?' + params.join("&");
+ }
+ }
+
+ request.open('GET', url, true);
+
+ request.onload = function () {
+ if (request.status >= 200 && request.status < 300) {
+ try {
+ store.push(JSON.parse(request.responseText));
+ if (success) {
+ success.call(context, id ? store.find(type, id) : store.find(type));
+ }
+ } catch (e) {
+ error.call({}, e);
+ }
+ } else if (error) {
+ error.call(context);
+ }
+ };
+
+ request.send();
+ })();
+ } else {
+ throw new Error('Unknown type \'' + type + '\'');
+ }
+ }
+ }, {
+ key: 'update',
+ value: function update(store, type, id, partial, success, error, context) {
+ var _this4 = this;
+
+ if (error && ({}).toString.call(error) !== '[object Function]') {
+
+ this.update(store, type, id, partial, success, null, error);
+ } else if (store._types[type]) {
+ (function () {
+
+ var request = new XMLHttpRequest();
+ var data = store.convert(type, id, partial);
+
+ request.open('PATCH', _this4._base + '/' + type + '/' + id, true);
+
+ request.onload = function () {
+ if (request.status >= 200 && request.status < 300) {
+ try {
+ store.add(data);
+ if (success) {
+ success.call(context, store.find(data.type, data.id));
+ }
+ } catch (e) {
+ if (error) {
+ error.call(context, e);
+ }
+ }
+ } else if (error) {
+ error.call(context);
+ }
+ };
+
+ request.send({
+ data: JSON.stringify(data)
+ });
+ })();
+ } else {
+ throw new Error('Unknown type \'' + type + '\'');
+ }
+ }
+ }]);
+
+ return AjaxAdapter;
+})();
+
+exports['default'] = AjaxAdapter;
+module.exports = exports['default'];
+
+},{}],3:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+require("array.prototype.find");
+
+var _ajaxAdapter = require("./ajax-adapter");
+
+var _ajaxAdapter2 = _interopRequireDefault(_ajaxAdapter);
+
+var Store = (function () {
+ _createClass(Store, null, [{
+ key: "attr",
+
+ /**
+ * Creates a field definition for an attribute.
+ *
+ * @since 0.1.0
+ * @param {string} [name] - Name of the property to map this field from.
+ * @param {Object} [options] - An options object.
+ * @param {string} [options.default] - Default value for this field.
+ * @return {Object} - Field definition.
+ */
+ value: function attr(name, options) {
+ if (name && typeof name === 'object') {
+ return Store.attr(null, name);
+ } else {
+ return {
+ type: "attr",
+ "default": options && options["default"],
+ deserialize: function deserialize(data, key) {
+ return data.attributes && data.attributes[name || key];
+ },
+ serialize: function serialize(resource, data, key) {
+ data.attributes[name || key] = resource[key];
+ }
+ };
+ }
+ }
+
+ /**
+ * Creates a field definition for an has-one relationship.
+ *
+ * @since 0.1.0
+ * @param {string} [name] - Name of the property to map this field from.
+ * @param {Object} [options] - An options object.
+ * @param {string} [options.inverse] - Name of the inverse relationship.
+ * @return {Object} - Field definition.
+ */
+ }, {
+ key: "hasOne",
+ value: function hasOne(name, options) {
+ if (name && typeof name === 'object') {
+ return Store.hasOne(null, name);
+ } else {
+ return {
+ type: "has-one",
+ inverse: options && options.inverse,
+ deserialize: function deserialize(data, key) {
+ name = name || key;
+ if (data.relationships && data.relationships[name]) {
+ if (data.relationships[name].data === null) {
+ return null;
+ } else if (data.relationships[name].data) {
+ return this.find(data.relationships[name].data.type, data.relationships[name].data.id);
+ }
+ }
+ }
+ };
+ }
+ }
+
+ /**
+ * Creates a field definition for an has-many relationship.
+ *
+ * @since 0.1.0
+ * @param {string} [name] - Name of the property to map this field from.
+ * @param {Object} [options] - An options object.
+ * @param {string} [options.inverse] - Name of the inverse relationship.
+ * @return {Object} - Field definition.
+ */
+ }, {
+ key: "hasMany",
+ value: function hasMany(name, options) {
+ if (name && typeof name === 'object') {
+ return Store.hasMany(null, name);
+ } else {
+ return {
+ type: "has-many",
+ "default": [],
+ inverse: options && options.inverse,
+ deserialize: function deserialize(data, key) {
+ var _this = this;
+
+ name = name || key;
+ if (data.relationships && data.relationships[name]) {
+ if (data.relationships[name].data === null) {
+ return [];
+ } else if (data.relationships[name].data) {
+ return data.relationships[name].data.map(function (c) {
+ return _this.find(c.type, c.id);
+ });
+ }
+ }
+ }
+ };
+ }
+ }
+ }]);
+
+ function Store(adapter) {
+ _classCallCheck(this, Store);
+
+ this._adapter = adapter;
+ this._collectionListeners = { "added": {}, "updated": {}, "removed": {} };
+ this._data = {};
+ this._resourceListeners = { "added": {}, "updated": {}, "removed": {} };
+ this._types = {};
+ }
+
+ /**
+ * Add an individual resource to the store. This is used internally by the
+ * `push()` method.
+ *
+ * @since 0.1.0
+ * @param {!Object} object - Resource Object to add. See:
+ http://jsonapi.org/format/#document-resource-objects
+ * @return {undefined} - Nothing.
+ */
+
+ _createClass(Store, [{
+ key: "add",
+ value: function add(object) {
+ var _this2 = this;
+
+ if (object) {
+ if (object.type && object.id) {
+ (function () {
+ var event = _this2._data[object.type] && _this2._data[object.type][object.id] ? "updated" : "added";
+ var resource = _this2.find(object.type, object.id);
+ var definition = _this2._types[object.type];
+ Object.keys(definition).forEach(function (fieldName) {
+ if (fieldName[0] !== "_") {
+ _this2._addField(object, resource, definition, fieldName);
+ }
+ });
+ if (_this2._resourceListeners[event][object.type] && _this2._resourceListeners[event][object.type][object.id]) {
+ _this2._resourceListeners[event][object.type][object.id].forEach(function (x) {
+ return x[0].call(x[1], resource);
+ });
+ }
+ if (_this2._collectionListeners[event][object.type]) {
+ _this2._collectionListeners[event][object.type].forEach(function (x) {
+ return x[0].call(x[1], resource);
+ });
+ }
+ })();
+ } else {
+ throw new TypeError("The data must have a type and id");
+ }
+ } else {
+ throw new TypeError("You must provide data to add");
+ }
+ }
+
+ /**
+ * Converts the given partial into a JSON API compliant representation.
+ *
+ * @since 0.5.0
+ * @param {!string} [type] - The type of the resource. This can be omitted if the partial includes a type property.
+ * @param {!string} [id] - The id of the resource. This can be omitted if the partial includes an id property.
+ * @param {!object} partial - The data to convert.
+ * @return {object} - JSON API version of the object.
+ */
+ }, {
+ key: "convert",
+ value: function convert(type, id, partial) {
+ var _this3 = this;
+
+ if (type && typeof type === "object") {
+ return this.convert(type.type, type.id, type);
+ } else if (id && typeof id === "object") {
+ return this.convert(type, id.id, id);
+ } else {
+ var _ret2 = (function () {
+ var data = {
+ type: type,
+ attributes: {},
+ relationships: {}
+ };
+ if (id) {
+ data.id = id;
+ }
+ var definition = _this3._types[data.type];
+ Object.keys(definition).forEach(function (fieldName) {
+ if (fieldName[0] !== "_") {
+ definition[fieldName].serialize(partial, data, fieldName);
+ }
+ });
+ return {
+ v: data
+ };
+ })();
+
+ if (typeof _ret2 === "object") return _ret2.v;
+ }
+ }
+
+ /**
+ * Attempts to create the resource through the adapter and adds it to the
+ * store if successful.
+ *
+ * @since 0.5.0
+ * @param {!string} type - Type of resource.
+ * @param {!Object} partial - Data to create the resource with.
+ * @param {function} [success] - Callback on success.
+ * @param {function} [error] - Callback on error.
+ * @param {Object} [context] - Context for the callbacks.
+ * @return {undefined} - Nothing.
+ *
+ * @example
+ * let adapter = new Store.AjaxAdapter();
+ * let store = new Store(adpater);
+ * store.create("product", { title: "A Book" }, (product) => {
+ * console.log(product.title);
+ * });
+ */
+ }, {
+ key: "create",
+ value: function create(type, partial, success, error, context) {
+ if (this._adapter) {
+ this._adapter.create(this, type, partial, success, error, context);
+ } else {
+ throw new Error("Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`");
+ }
+ }
+
+ /**
+ * Defines a type of resource.
+ *
+ * @since 0.2.0
+ * @param {!string|string[]} names - Name(s) of the resource.
+ * @param {!Object} definition - The resource's definition.
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "define",
+ value: function define(names, definition) {
+ var _this4 = this;
+
+ names = names.constructor === Array ? names : [names];
+ if (definition) {
+ definition._names = names;
+ names.forEach(function (name) {
+ if (!_this4._types[name]) {
+ _this4._types[name] = definition;
+ } else {
+ throw new Error("The type '" + name + "' has already been defined.");
+ }
+ });
+ } else {
+ throw new Error("You must provide a definition for the type '" + names[0] + "'.");
+ }
+ }
+
+ /**
+ * Attempts to delete the resource through the adapter and removes it from
+ * the store if successful.
+ *
+ * @since 0.5.0
+ * @param {!string} type - Type of resource.
+ * @param {!string} id - ID of resource.
+ * @param {function} [success] - Callback on success.
+ * @param {function} [error] - Callback on error.
+ * @param {Object} [context] - Context for the callbacks.
+ * @return {undefined} - Nothing.
+ *
+ * @example
+ * let adapter = new Store.AjaxAdapter();
+ * let store = new Store(adpater);
+ * store.destroy("product", "1", () => {
+ * console.log("Destroyed!");
+ * });
+ */
+ }, {
+ key: "destroy",
+ value: function destroy(type, id, success, error, context) {
+ if (this._adapter) {
+ this._adapter.destroy(this, type, id, success, error, context);
+ } else {
+ throw new Error("Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`");
+ }
+ }
+
+ /**
+ * Find a resource or entire collection of resources.
+ *
+ * NOTE: If the resource hasn't been loaded via an add() or push() call it
+ * will be automatically created when find is called.
+ *
+ * @since 0.1.0
+ * @param {!string} type - Type of the resource(s) to find.
+ * @param {string} [id] - The id of the resource to find. If omitted all
+ * resources of the type will be returned.
+ * @return {Object|Object[]} - Either the resource or an array of resources.
+ */
+ }, {
+ key: "find",
+ value: function find(type, id) {
+ var _this5 = this;
+
+ if (type) {
+ var _ret3 = (function () {
+ var definition = _this5._types[type];
+ if (definition) {
+ if (!_this5._data[type]) {
+ (function () {
+ var collection = {};
+ definition._names.forEach(function (t) {
+ return _this5._data[t] = collection;
+ });
+ })();
+ }
+ if (id) {
+ if (!_this5._data[type][id]) {
+ _this5._data[type][id] = {
+ _dependents: [],
+ type: type,
+ id: id
+ };
+ Object.keys(definition).forEach(function (key) {
+ if (key[0] !== "_") {
+ _this5._data[type][id][key] = definition[key]["default"];
+ }
+ });
+ }
+ return {
+ v: _this5._data[type][id]
+ };
+ } else {
+ return {
+ v: Object.keys(_this5._data[type]).map(function (x) {
+ return _this5._data[type][x];
+ })
+ };
+ }
+ } else {
+ throw new TypeError("Unknown type '" + type + "'");
+ }
+ })();
+
+ if (typeof _ret3 === "object") return _ret3.v;
+ } else {
+ throw new TypeError("You must provide a type");
+ }
+ }
+
+ /**
+ * Attempts to load the resource(s) through the adapter and adds it/them to
+ * the store if successful.
+ *
+ * @since 0.5.0
+ * @param {!string} type - Type of resource.
+ * @param {!string} [id] - ID of resource.
+ * @param {Object} [options] - **NOT YET IMPLEMENTED** (this will include sorting, filtering and pagination options)
+ * @param {function} [success] - Callback on success.
+ * @param {function} [error] - Callback on error.
+ * @param {Object} [context] - Context for the callbacks.
+ * @return {undefined} - Nothing.
+ *
+ * @example
+ * let adapter = new Store.AjaxAdapter();
+ * let store = new Store(adpater);
+ * store.load("product", "1", (product) => {
+ * console.log(product.title);
+ * });
+ */
+ }, {
+ key: "load",
+ value: function load(type, id, options, success, error, context) {
+ if (this._adapter) {
+ this._adapter.load(this, type, id, options, success, error, context);
+ } else {
+ throw new Error("Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`");
+ }
+ }
+
+ /**
+ * Unregister an event listener that was registered with on().
+ *
+ * @since 0.4.0
+ * @param {string} event - Name of the event.
+ * @param {string} type - Name of resource to originally passed to on().
+ * @param {string} [id] - ID of the resource to originally passed to on().
+ * @param {function} callback - Function originally passed to on().
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "off",
+ value: function off(event, type, id, callback) {
+ var _this6 = this;
+
+ if (this._resourceListeners[event] && this._collectionListeners[event]) {
+ if (this._types[type]) {
+ if (id && ({}).toString.call(id) === '[object Function]') {
+ this.off.call(this, event, type, null, id, callback);
+ } else {
+ // TODO: Performance-wise, this can be made way better. There shouldn't be a need to maintain separate lists.
+ this._types[type]._names.forEach(function (type) {
+ if (id) {
+ if (_this6._resourceListeners[event][type] && _this6._resourceListeners[event][type][id]) {
+ _this6._resourceListeners[event][type][id] = _this6._resourceListeners[event][type][id].filter(function (x) {
+ return x[0] !== callback;
+ });
+ }
+ } else if (_this6._collectionListeners[event][type]) {
+ _this6._collectionListeners[event][type] = _this6._collectionListeners[event][type].filter(function (x) {
+ return x[0] !== callback;
+ });
+ }
+ });
+ }
+ } else {
+ throw new Error("Unknown type '" + type + "'");
+ }
+ } else {
+ throw new Error("Unknown event '" + event + "'");
+ }
+ }
+
+ /**
+ * Register an event listener: "added", "updated" or "removed".
+ *
+ * @since 0.4.0
+ * @param {string} event - Name of the event.
+ * @param {string} type - Name of resource to watch.
+ * @param {string} [id] - ID of the resource to watch.
+ * @param {function} callback - Function to call when the event occurs.
+ * @param {Object} [context] - Context in which to call the callback.
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "on",
+ value: function on(event, type, id, callback, context) {
+ var _this7 = this;
+
+ if (this._resourceListeners[event] && this._collectionListeners[event]) {
+ if (this._types[type]) {
+ if (id && ({}).toString.call(id) === '[object Function]') {
+ this.on.call(this, event, type, null, id, callback);
+ } else {
+ // TODO: Performance-wise, this can be made way better. There shouldn't be a need to maintain separate lists.
+ this._types[type]._names.forEach(function (type) {
+ if (id) {
+ _this7._resourceListeners[event][type] = _this7._resourceListeners[event][type] || {};
+ _this7._resourceListeners[event][type][id] = _this7._resourceListeners[event][type][id] || [];
+ if (!_this7._resourceListeners[event][type][id].find(function (x) {
+ return x[0] === callback;
+ })) {
+ _this7._resourceListeners[event][type][id].push([callback, context]);
+ }
+ } else {
+ _this7._collectionListeners[event][type] = _this7._collectionListeners[event][type] || [];
+ if (!_this7._collectionListeners[event][type].find(function (x) {
+ return x[0] === callback;
+ })) {
+ _this7._collectionListeners[event][type].push([callback, context]);
+ }
+ }
+ });
+ }
+ } else {
+ throw new Error("Unknown type '" + type + "'");
+ }
+ } else {
+ throw new Error("Unknown event '" + event + "'");
+ }
+ }
+
+ /**
+ * Add a JSON API response to the store. This method can be used to handle a
+ * successful GET or POST response from the server.
+ *
+ * @since 0.1.0
+ * @param {Object} root - Top Level Object to push. See:
+ http://jsonapi.org/format/#document-top-level
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "push",
+ value: function push(root) {
+ var _this8 = this;
+
+ if (root.data.constructor === Array) {
+ root.data.forEach(function (x) {
+ return _this8.add(x);
+ });
+ } else {
+ this.add(root.data);
+ }
+ if (root.included) {
+ root.included.forEach(function (x) {
+ return _this8.add(x);
+ });
+ }
+ }
+
+ /**
+ * Remove a resource or collection of resources from the store.
+ *
+ * @since 0.1.0
+ * @param {!string} type - Type of the resource(s) to remove.
+ * @param {string} [id] - The id of the resource to remove. If omitted all
+ * resources of the type will be removed.
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "remove",
+ value: function remove(type, id) {
+ var _this9 = this;
+
+ if (type) {
+ if (this._types[type]) {
+ if (id) {
+ (function () {
+ var resource = _this9._data[type] && _this9._data[type][id];
+ if (resource) {
+ _this9._remove(resource);
+ if (_this9._resourceListeners["removed"][type] && _this9._resourceListeners["removed"][type][id]) {
+ _this9._resourceListeners["removed"][type][id].forEach(function (x) {
+ return x[0].call(x[1], resource);
+ });
+ }
+ if (_this9._collectionListeners["removed"][type]) {
+ _this9._collectionListeners["removed"][type].forEach(function (x) {
+ return x[0].call(x[1], resource);
+ });
+ }
+ }
+ })();
+ } else {
+ Object.keys(this._data[type]).forEach(function (id) {
+ return _this9.remove(type, id);
+ });
+ }
+ } else {
+ throw new TypeError("Unknown type '" + type + "'");
+ }
+ } else {
+ throw new TypeError("You must provide a type to remove");
+ }
+ }
+
+ /**
+ * Attempts to update the resource through the adapter and updates it in the
+ * store if successful.
+ *
+ * @since 0.5.0
+ * @param {!string} type - Type of resource.
+ * @param {!string} id - ID of resource.
+ * @param {!Object} partial - Data to update the resource with.
+ * @param {function} [success] - Callback on success.
+ * @param {function} [error] - Callback on error.
+ * @param {Object} [context] - Context for the callbacks.
+ * @return {undefined} - Nothing.
+ *
+ * @example
+ * let adapter = new Store.AjaxAdapter();
+ * let store = new Store(adpater);
+ * store.update("product", "1", { title: "foo" }, (product) => {
+ * console.log(product.title);
+ * });
+ */
+ }, {
+ key: "update",
+ value: function update(type, id, partial, success, error, context) {
+ if (this._adapter) {
+ this._adapter.update(this, type, id, partial, success, error, context);
+ } else {
+ throw new Error("Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`");
+ }
+ }
+ }, {
+ key: "_addField",
+ value: function _addField(object, resource, definition, fieldName) {
+ var _this10 = this;
+
+ var field = definition[fieldName];
+ var newValue = field.deserialize.call(this, object, fieldName);
+ if (typeof newValue !== "undefined") {
+ if (field.type === "has-one") {
+ if (resource[fieldName]) {
+ this._removeInverseRelationship(resource, fieldName, resource[fieldName], field);
+ }
+ if (newValue) {
+ this._addInverseRelationship(resource, fieldName, newValue, field);
+ }
+ } else if (field.type === "has-many") {
+ resource[fieldName].forEach(function (r) {
+ if (resource[fieldName].indexOf(r) !== -1) {
+ _this10._removeInverseRelationship(resource, fieldName, r, field);
+ }
+ });
+ newValue.forEach(function (r) {
+ _this10._addInverseRelationship(resource, fieldName, r, field);
+ });
+ }
+ resource[fieldName] = newValue;
+ }
+ }
+ }, {
+ key: "_addInverseRelationship",
+ value: function _addInverseRelationship(sourceResource, sourceFieldName, targetResource, sourceField) {
+ var targetDefinition = this._types[targetResource.type];
+ var sourceDefinition = this._types[sourceResource.type];
+ if (targetDefinition) {
+ var targetFieldName = [sourceField.inverse].concat(sourceDefinition._names).find(function (x) {
+ return targetDefinition[x];
+ });
+ var targetField = targetDefinition && targetDefinition[targetFieldName];
+ targetResource._dependents.push({ type: sourceResource.type, id: sourceResource.id, fieldName: sourceFieldName });
+ if (targetField) {
+ if (targetField.type === "has-one") {
+ sourceResource._dependents.push({ type: targetResource.type, id: targetResource.id, fieldName: targetFieldName });
+ targetResource[targetFieldName] = sourceResource;
+ } else if (targetField.type === "has-many") {
+ sourceResource._dependents.push({ type: targetResource.type, id: targetResource.id, fieldName: targetFieldName });
+ if (targetResource[targetFieldName].indexOf(sourceResource) === -1) {
+ targetResource[targetFieldName].push(sourceResource);
+ }
+ } else if (targetField.type === "attr") {
+ throw new Error("The the inverse relationship for '" + sourceFieldName + "' is an attribute ('" + targetFieldName + "')");
+ }
+ } else if (sourceField.inverse) {
+ throw new Error("The the inverse relationship for '" + sourceFieldName + "' is missing ('" + sourceField.inverse + "')");
+ }
+ }
+ }
+ }, {
+ key: "_remove",
+ value: function _remove(resource) {
+ var _this11 = this;
+
+ resource._dependents.forEach(function (dependent) {
+ var dependentResource = _this11._data[dependent.type][dependent.id];
+ switch (_this11._types[dependent.type][dependent.fieldName].type) {
+ case "has-one":
+ {
+ dependentResource[dependent.fieldName] = null;
+ break;
+ }
+ case "has-many":
+ {
+ var index = dependentResource[dependent.fieldName].indexOf(resource);
+ if (index !== -1) {
+ dependentResource[dependent.fieldName].splice(index, 1);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ // TODO: This only needs to be run once for each dependent.
+ dependentResource._dependents = dependentResource._dependents.filter(function (d) {
+ return !(d.type === resource.type && d.id === resource.id);
+ });
+ });
+ delete this._data[resource.type][resource.id];
+ }
+ }, {
+ key: "_removeInverseRelationship",
+ value: function _removeInverseRelationship(sourceResource, sourceFieldName, targetResource, sourceField) {
+ var targetDefinition = this._types[targetResource.type];
+ var targetFieldName = sourceField.inverse || sourceResource.type;
+ var targetField = targetDefinition && targetDefinition[targetFieldName];
+ targetResource._dependents = targetResource._dependents.filter(function (r) {
+ return !(r.type === sourceResource.type && r.id === sourceResource.id && r.fieldName === sourceFieldName);
+ });
+ if (targetField) {
+ if (targetField.type === "has-one") {
+ sourceResource._dependents = sourceResource._dependents.filter(function (r) {
+ return !(r.type === targetResource.type && r.id === targetResource.id && r.fieldName === targetFieldName);
+ });
+ targetResource[targetFieldName] = null;
+ } else if (targetField.type === "has-many") {
+ sourceResource._dependents = sourceResource._dependents.filter(function (r) {
+ return !(r.type === targetResource.type && r.id === targetResource.id && r.fieldName === targetFieldName);
+ });
+ targetResource[targetFieldName] = targetResource[targetFieldName].filter(function (r) {
+ return r !== sourceResource;
+ });
+ } else if (targetField.type === "attr") {
+ throw new Error("The the inverse relationship for '" + sourceFieldName + "' is an attribute ('" + targetFieldName + "')");
+ }
+ } else if (sourceField.inverse) {
+ throw new Error("The the inverse relationship for '" + sourceFieldName + "' is missing ('" + sourceField.inverse + "')");
+ }
+ }
+ }]);
+
+ return Store;
+})();
+
+exports["default"] = Store;
+
+Store.AjaxAdapter = _ajaxAdapter2["default"];
+module.exports = exports["default"];
+
+},{"./ajax-adapter":2,"array.prototype.find":1}]},{},[3])(3)
+});
+//# sourceMappingURL=store.dev.js.map
diff --git a/releases/v0.5.0/store.dev.js.map b/releases/v0.5.0/store.dev.js.map
new file mode 100644
index 0000000..de6c4be
--- /dev/null
+++ b/releases/v0.5.0/store.dev.js.map
@@ -0,0 +1,19 @@
+{
+ "version": 3,
+ "sources": [
+ "../node_modules/browserify/node_modules/browser-pack/_prelude.js",
+ "../node_modules/array.prototype.find/index.js",
+ "../src/ajax-adapter.js",
+ "../src/store.js"
+ ],
+ "names": [],
+ "mappings": "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",
+ "file": "generated.js",
+ "sourceRoot": "",
+ "sourcesContent": [
+ "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o\n// For all details and docs: https://github.com/paulmillr/array.prototype.find\n// Fixes and tests supplied by Duncan Hall \n(function(globals){\n if (Array.prototype.find) return;\n\n var find = function(predicate) {\n var list = Object(this);\n var length = list.length < 0 ? 0 : list.length >>> 0; // ES.ToUint32;\n if (length === 0) return undefined;\n if (typeof predicate !== 'function' || Object.prototype.toString.call(predicate) !== '[object Function]') {\n throw new TypeError('Array#find: predicate must be a function');\n }\n var thisArg = arguments[1];\n for (var i = 0, value; i < length; i++) {\n value = list[i];\n if (predicate.call(thisArg, value, i, list)) return value;\n }\n return undefined;\n };\n\n if (Object.defineProperty) {\n try {\n Object.defineProperty(Array.prototype, 'find', {\n value: find, configurable: true, enumerable: false, writable: true\n });\n } catch(e) {}\n }\n\n if (!Array.prototype.find) {\n Array.prototype.find = find;\n }\n})(this);\n",
+ "export default class AjaxAdapter {\n\n constructor(options) {\n this._base = (options && options.base) || \"\";\n };\n\n create(store, type, partial, success, error, context) {\n\n if (error && {}.toString.call(error) !== '[object Function]') {\n\n this.create(store, type, partial, success, null, error);\n\n } else if (store._types[type]) {\n\n let request = new XMLHttpRequest();\n\n request.open('POST', `${this._base}/${type}`, true);\n\n request.onload = function () {\n if (request.status >= 200 && request.status < 300) {\n let response = JSON.parse(request.responseText);\n try {\n store.push(response);\n if (success) {\n success.call(context, store.find(response.data.type, response.data.id));\n }\n } catch (e) {\n if (error) {\n error.call(context, e);\n }\n }\n } else {\n if (error) {\n error.call(context);\n }\n }\n };\n\n request.send({\n data: JSON.stringify(store.convert(type, partial))\n });\n\n } else {\n throw new Error(`Unknown type '${type}'`);\n }\n\n }\n\n destroy(store, type, id, success, error, context) {\n\n if (error && {}.toString.call(error) !== '[object Function]') {\n\n this.destroy(store, type, id, success, null, error);\n\n } else if (store._types[type]) {\n\n let request = new XMLHttpRequest();\n\n request.open('DELETE', `${this._base}/${type}/${id}`, true);\n\n request.onload = function () {\n if (request.status >= 200 && request.status < 300) {\n try {\n store.remove(type, id);\n if (success) {\n success.call(context);\n }\n } catch (e) {\n error.call(context, e);\n }\n } else if (error) {\n error.call(context);\n }\n };\n\n request.send();\n\n } else {\n throw new Error(`Unknown type '${type}'`);\n }\n\n }\n\n load(store, type, id, options, success, error, context) {\n\n if (id && {}.toString.call(id) === '[object Function]') {\n this.load(store, type, null, null, id, options, success);\n } else if (id && typeof id === \"object\") {\n this.load(store, type, null, id, options, success, error);\n } else if (options && {}.toString.call(options) === '[object Function]') {\n this.load(store, type, id, {}, options, success, error);\n } else if (error && {}.toString.call(error) !== '[object Function]') {\n this.load(store, type, id, options, success, null, error);\n } else if (store._types[type]) {\n\n let request = new XMLHttpRequest();\n let url;\n\n options = options || {};\n url = id ? `${this._base}/${type}/${id}` : `${this._base}/${type}`;\n\n if (options) {\n\n let params = [];\n\n if (options.fields) {\n Object.keys(options.fields).forEach(field => {\n options[`fields[${field}]`] = options.fields[field];\n });\n delete options.fields;\n }\n\n params = Object.keys(options).map(key => {\n return key + \"=\" + encodeURIComponent(options[key]);\n }).sort();\n\n if (params.length) {\n url = `${url}?${params.join(\"&\")}`;\n }\n\n }\n\n request.open('GET', url, true);\n\n request.onload = function () {\n if (request.status >= 200 && request.status < 300) {\n try {\n store.push(JSON.parse(request.responseText));\n if (success) {\n success.call(context, id ? store.find(type, id) : store.find(type));\n }\n } catch (e) {\n error.call({}, e);\n }\n } else if (error) {\n error.call(context);\n }\n };\n\n request.send();\n\n } else {\n throw new Error(`Unknown type '${type}'`);\n }\n\n }\n\n update(store, type, id, partial, success, error, context) {\n\n if (error && {}.toString.call(error) !== '[object Function]') {\n\n this.update(store, type, id, partial, success, null, error);\n\n } else if (store._types[type]) {\n\n let request = new XMLHttpRequest();\n let data = store.convert(type, id, partial);\n\n request.open('PATCH', `${this._base}/${type}/${id}`, true);\n\n request.onload = function () {\n if (request.status >= 200 && request.status < 300) {\n try {\n store.add(data);\n if (success) {\n success.call(context, store.find(data.type, data.id));\n }\n } catch (e) {\n if (error) {\n error.call(context, e);\n }\n }\n } else if (error) {\n error.call(context);\n }\n };\n\n request.send({\n data: JSON.stringify(data)\n });\n\n } else {\n throw new Error(`Unknown type '${type}'`);\n }\n\n }\n\n}\n",
+ "import \"array.prototype.find\";\nimport AjaxAdapter from \"./ajax-adapter\";\n\nexport default class Store {\n\n /**\n * Creates a field definition for an attribute.\n *\n * @since 0.1.0\n * @param {string} [name] - Name of the property to map this field from.\n * @param {Object} [options] - An options object.\n * @param {string} [options.default] - Default value for this field.\n * @return {Object} - Field definition.\n */\n static attr(name, options) {\n if (name && typeof name === 'object') {\n return Store.attr(null, name);\n } else {\n return {\n type: \"attr\",\n default: options && options.default,\n deserialize: function (data, key) {\n return data.attributes && data.attributes[name || key];\n },\n serialize: function (resource, data, key) {\n data.attributes[name || key] = resource[key];\n }\n };\n }\n }\n\n /**\n * Creates a field definition for an has-one relationship.\n *\n * @since 0.1.0\n * @param {string} [name] - Name of the property to map this field from.\n * @param {Object} [options] - An options object.\n * @param {string} [options.inverse] - Name of the inverse relationship.\n * @return {Object} - Field definition.\n */\n static hasOne(name, options) {\n if (name && typeof name === 'object') {\n return Store.hasOne(null, name);\n } else {\n return {\n type: \"has-one\",\n inverse: options && options.inverse,\n deserialize: function (data, key) {\n name = name || key;\n if (data.relationships && data.relationships[name]) {\n if (data.relationships[name].data === null) {\n return null;\n } else if (data.relationships[name].data) {\n return this.find(data.relationships[name].data.type, data.relationships[name].data.id);\n }\n }\n }\n };\n }\n }\n\n /**\n * Creates a field definition for an has-many relationship.\n *\n * @since 0.1.0\n * @param {string} [name] - Name of the property to map this field from.\n * @param {Object} [options] - An options object.\n * @param {string} [options.inverse] - Name of the inverse relationship.\n * @return {Object} - Field definition.\n */\n static hasMany(name, options) {\n if (name && typeof name === 'object') {\n return Store.hasMany(null, name);\n } else {\n return {\n type: \"has-many\",\n default: [],\n inverse: options && options.inverse,\n deserialize: function (data, key) {\n name = name || key;\n if (data.relationships && data.relationships[name]) {\n if (data.relationships[name].data === null) {\n return [];\n } else if (data.relationships[name].data) {\n return data.relationships[name].data.map((c) => {\n return this.find(c.type, c.id);\n });\n }\n }\n }\n };\n }\n }\n\n constructor(adapter) {\n this._adapter = adapter;\n this._collectionListeners = { \"added\": {}, \"updated\": {}, \"removed\": {} };\n this._data = {};\n this._resourceListeners = { \"added\": {}, \"updated\": {}, \"removed\": {} };\n this._types = {};\n }\n\n /**\n * Add an individual resource to the store. This is used internally by the\n * `push()` method.\n *\n * @since 0.1.0\n * @param {!Object} object - Resource Object to add. See:\n http://jsonapi.org/format/#document-resource-objects\n * @return {undefined} - Nothing.\n */\n add(object) {\n if (object) {\n if (object.type && object.id) {\n let event = this._data[object.type] && this._data[object.type][object.id] ? \"updated\" : \"added\";\n let resource = this.find(object.type, object.id);\n let definition = this._types[object.type];\n Object.keys(definition).forEach(fieldName => {\n if (fieldName[0] !== \"_\") {\n this._addField(object, resource, definition, fieldName);\n }\n });\n if (this._resourceListeners[event][object.type] && this._resourceListeners[event][object.type][object.id]) {\n this._resourceListeners[event][object.type][object.id].forEach(x => x[0].call(x[1], resource));\n }\n if (this._collectionListeners[event][object.type]) {\n this._collectionListeners[event][object.type].forEach(x => x[0].call(x[1], resource));\n }\n } else {\n throw new TypeError(`The data must have a type and id`);\n }\n } else {\n throw new TypeError(`You must provide data to add`);\n }\n }\n\n /**\n * Converts the given partial into a JSON API compliant representation.\n *\n * @since 0.5.0\n * @param {!string} [type] - The type of the resource. This can be omitted if the partial includes a type property.\n * @param {!string} [id] - The id of the resource. This can be omitted if the partial includes an id property.\n * @param {!object} partial - The data to convert.\n * @return {object} - JSON API version of the object.\n */\n convert(type, id, partial) {\n if (type && typeof type === \"object\") {\n return this.convert(type.type, type.id, type);\n } else if (id && typeof id === \"object\") {\n return this.convert(type, id.id, id);\n } else {\n let data = {\n type: type,\n attributes: {},\n relationships: {}\n };\n if (id) {\n data.id = id;\n }\n let definition = this._types[data.type];\n Object.keys(definition).forEach(fieldName => {\n if (fieldName[0] !== \"_\") {\n definition[fieldName].serialize(partial, data, fieldName);\n }\n });\n return data;\n }\n }\n\n /**\n * Attempts to create the resource through the adapter and adds it to the\n * store if successful.\n *\n * @since 0.5.0\n * @param {!string} type - Type of resource.\n * @param {!Object} partial - Data to create the resource with.\n * @param {function} [success] - Callback on success.\n * @param {function} [error] - Callback on error.\n * @param {Object} [context] - Context for the callbacks.\n * @return {undefined} - Nothing.\n *\n * @example\n * let adapter = new Store.AjaxAdapter();\n * let store = new Store(adpater);\n * store.create(\"product\", { title: \"A Book\" }, (product) => {\n * console.log(product.title);\n * });\n */\n create(type, partial, success, error, context) {\n if (this._adapter) {\n this._adapter.create(this, type, partial, success, error, context);\n } else {\n throw new Error(\"Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`\");\n }\n }\n\n /**\n * Defines a type of resource.\n *\n * @since 0.2.0\n * @param {!string|string[]} names - Name(s) of the resource.\n * @param {!Object} definition - The resource's definition.\n * @return {undefined} - Nothing.\n */\n define(names, definition) {\n names = (names.constructor === Array) ? names : [ names ];\n if (definition) {\n definition._names = names;\n names.forEach(name => {\n if (!this._types[name]) {\n this._types[name] = definition;\n } else {\n throw new Error(`The type '${name}' has already been defined.`);\n }\n });\n } else {\n throw new Error(`You must provide a definition for the type '${names[0]}'.`);\n }\n }\n\n /**\n * Attempts to delete the resource through the adapter and removes it from\n * the store if successful.\n *\n * @since 0.5.0\n * @param {!string} type - Type of resource.\n * @param {!string} id - ID of resource.\n * @param {function} [success] - Callback on success.\n * @param {function} [error] - Callback on error.\n * @param {Object} [context] - Context for the callbacks.\n * @return {undefined} - Nothing.\n *\n * @example\n * let adapter = new Store.AjaxAdapter();\n * let store = new Store(adpater);\n * store.destroy(\"product\", \"1\", () => {\n * console.log(\"Destroyed!\");\n * });\n */\n destroy(type, id, success, error, context) {\n if (this._adapter) {\n this._adapter.destroy(this, type, id, success, error, context);\n } else {\n throw new Error(\"Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`\");\n }\n }\n\n /**\n * Find a resource or entire collection of resources.\n *\n * NOTE: If the resource hasn't been loaded via an add() or push() call it\n * will be automatically created when find is called.\n *\n * @since 0.1.0\n * @param {!string} type - Type of the resource(s) to find.\n * @param {string} [id] - The id of the resource to find. If omitted all\n * resources of the type will be returned.\n * @return {Object|Object[]} - Either the resource or an array of resources.\n */\n find(type, id) {\n if (type) {\n let definition = this._types[type];\n if (definition) {\n if (!this._data[type]) {\n let collection = {};\n definition._names.forEach(t => this._data[t] = collection);\n }\n if (id) {\n if (!this._data[type][id]) {\n this._data[type][id] = {\n _dependents: [],\n type: type,\n id: id\n };\n Object.keys(definition).forEach(key => {\n if (key[0] !== \"_\") {\n this._data[type][id][key] = definition[key].default;\n }\n });\n }\n return this._data[type][id];\n } else {\n return Object.keys(this._data[type]).map(x => this._data[type][x]);\n }\n } else {\n throw new TypeError(`Unknown type '${type}'`);\n }\n } else {\n throw new TypeError(`You must provide a type`);\n }\n }\n\n /**\n * Attempts to load the resource(s) through the adapter and adds it/them to\n * the store if successful.\n *\n * @since 0.5.0\n * @param {!string} type - Type of resource.\n * @param {!string} [id] - ID of resource.\n * @param {Object} [options] - **NOT YET IMPLEMENTED** (this will include sorting, filtering and pagination options)\n * @param {function} [success] - Callback on success.\n * @param {function} [error] - Callback on error.\n * @param {Object} [context] - Context for the callbacks.\n * @return {undefined} - Nothing.\n *\n * @example\n * let adapter = new Store.AjaxAdapter();\n * let store = new Store(adpater);\n * store.load(\"product\", \"1\", (product) => {\n * console.log(product.title);\n * });\n */\n load(type, id, options, success, error, context) {\n if (this._adapter) {\n this._adapter.load(this, type, id, options, success, error, context);\n } else {\n throw new Error(\"Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`\");\n }\n }\n\n /**\n * Unregister an event listener that was registered with on().\n *\n * @since 0.4.0\n * @param {string} event - Name of the event.\n * @param {string} type - Name of resource to originally passed to on().\n * @param {string} [id] - ID of the resource to originally passed to on().\n * @param {function} callback - Function originally passed to on().\n * @return {undefined} - Nothing.\n */\n off(event, type, id, callback) {\n if (this._resourceListeners[event] && this._collectionListeners[event]) {\n if (this._types[type]) {\n if (id && ({}).toString.call(id) === '[object Function]') {\n this.off.call(this, event, type, null, id, callback);\n } else {\n // TODO: Performance-wise, this can be made way better. There shouldn't be a need to maintain separate lists.\n this._types[type]._names.forEach(type => {\n if (id) {\n if (this._resourceListeners[event][type] && this._resourceListeners[event][type][id]) {\n this._resourceListeners[event][type][id] = this._resourceListeners[event][type][id].filter(x => {\n return x[0] !== callback;\n });\n }\n } else if (this._collectionListeners[event][type]) {\n this._collectionListeners[event][type] = this._collectionListeners[event][type].filter(x => {\n return x[0] !== callback;\n });\n }\n });\n }\n } else {\n throw new Error(`Unknown type '${type}'`);\n }\n } else {\n throw new Error(`Unknown event '${event}'`);\n }\n }\n\n /**\n * Register an event listener: \"added\", \"updated\" or \"removed\".\n *\n * @since 0.4.0\n * @param {string} event - Name of the event.\n * @param {string} type - Name of resource to watch.\n * @param {string} [id] - ID of the resource to watch.\n * @param {function} callback - Function to call when the event occurs.\n * @param {Object} [context] - Context in which to call the callback.\n * @return {undefined} - Nothing.\n */\n on(event, type, id, callback, context) {\n if (this._resourceListeners[event] && this._collectionListeners[event]) {\n if (this._types[type]) {\n if (id && ({}).toString.call(id) === '[object Function]') {\n this.on.call(this, event, type, null, id, callback);\n } else {\n // TODO: Performance-wise, this can be made way better. There shouldn't be a need to maintain separate lists.\n this._types[type]._names.forEach(type => {\n if (id) {\n this._resourceListeners[event][type] = this._resourceListeners[event][type] || {};\n this._resourceListeners[event][type][id] = this._resourceListeners[event][type][id] || [];\n if (!this._resourceListeners[event][type][id].find(x => x[0] === callback)) {\n this._resourceListeners[event][type][id].push([ callback, context ]);\n }\n } else {\n this._collectionListeners[event][type] = this._collectionListeners[event][type] || [];\n if (!this._collectionListeners[event][type].find(x => x[0] === callback)) {\n this._collectionListeners[event][type].push([ callback, context ]);\n }\n }\n });\n }\n } else {\n throw new Error(`Unknown type '${type}'`);\n }\n } else {\n throw new Error(`Unknown event '${event}'`);\n }\n }\n\n /**\n * Add a JSON API response to the store. This method can be used to handle a\n * successful GET or POST response from the server.\n *\n * @since 0.1.0\n * @param {Object} root - Top Level Object to push. See:\n http://jsonapi.org/format/#document-top-level\n * @return {undefined} - Nothing.\n */\n push(root) {\n if (root.data.constructor === Array) {\n root.data.forEach(x => this.add(x));\n } else {\n this.add(root.data);\n }\n if (root.included) {\n root.included.forEach(x => this.add(x));\n }\n }\n\n /**\n * Remove a resource or collection of resources from the store.\n *\n * @since 0.1.0\n * @param {!string} type - Type of the resource(s) to remove.\n * @param {string} [id] - The id of the resource to remove. If omitted all\n * resources of the type will be removed.\n * @return {undefined} - Nothing.\n */\n remove(type, id) {\n if (type) {\n if (this._types[type]) {\n if (id) {\n let resource = this._data[type] && this._data[type][id];\n if (resource) {\n this._remove(resource);\n if (this._resourceListeners[\"removed\"][type] && this._resourceListeners[\"removed\"][type][id]) {\n this._resourceListeners[\"removed\"][type][id].forEach(x => x[0].call(x[1], resource));\n }\n if (this._collectionListeners[\"removed\"][type]) {\n this._collectionListeners[\"removed\"][type].forEach(x => x[0].call(x[1], resource));\n }\n }\n } else {\n Object.keys(this._data[type]).forEach(id => this.remove(type, id));\n }\n } else {\n throw new TypeError(`Unknown type '${type}'`);\n }\n } else {\n throw new TypeError(`You must provide a type to remove`);\n }\n }\n\n /**\n * Attempts to update the resource through the adapter and updates it in the\n * store if successful.\n *\n * @since 0.5.0\n * @param {!string} type - Type of resource.\n * @param {!string} id - ID of resource.\n * @param {!Object} partial - Data to update the resource with.\n * @param {function} [success] - Callback on success.\n * @param {function} [error] - Callback on error.\n * @param {Object} [context] - Context for the callbacks.\n * @return {undefined} - Nothing.\n *\n * @example\n * let adapter = new Store.AjaxAdapter();\n * let store = new Store(adpater);\n * store.update(\"product\", \"1\", { title: \"foo\" }, (product) => {\n * console.log(product.title);\n * });\n */\n update(type, id, partial, success, error, context) {\n if (this._adapter) {\n this._adapter.update(this, type, id, partial, success, error, context);\n } else {\n throw new Error(\"Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`\");\n }\n }\n\n _addField(object, resource, definition, fieldName) {\n var field = definition[fieldName];\n var newValue = field.deserialize.call(this, object, fieldName);\n if (typeof newValue !== \"undefined\") {\n if (field.type === \"has-one\") {\n if (resource[fieldName]) {\n this._removeInverseRelationship(resource, fieldName, resource[fieldName], field);\n }\n if (newValue) {\n this._addInverseRelationship(resource, fieldName, newValue, field);\n }\n } else if (field.type === \"has-many\") {\n resource[fieldName].forEach(r => {\n if (resource[fieldName].indexOf(r) !== -1) {\n this._removeInverseRelationship(resource, fieldName, r, field);\n }\n });\n newValue.forEach(r => {\n this._addInverseRelationship(resource, fieldName, r, field);\n });\n }\n resource[fieldName] = newValue;\n }\n }\n\n _addInverseRelationship(sourceResource, sourceFieldName, targetResource, sourceField) {\n var targetDefinition = this._types[targetResource.type];\n var sourceDefinition = this._types[sourceResource.type];\n if (targetDefinition) {\n let targetFieldName = [ sourceField.inverse ].concat(sourceDefinition._names).find(x => targetDefinition[x]);\n let targetField = targetDefinition && targetDefinition[targetFieldName];\n targetResource._dependents.push({ type: sourceResource.type, id: sourceResource.id, fieldName: sourceFieldName });\n if (targetField) {\n if (targetField.type === \"has-one\") {\n sourceResource._dependents.push({ type: targetResource.type, id: targetResource.id, fieldName: targetFieldName });\n targetResource[targetFieldName] = sourceResource;\n } else if (targetField.type === \"has-many\") {\n sourceResource._dependents.push({ type: targetResource.type, id: targetResource.id, fieldName: targetFieldName });\n if (targetResource[targetFieldName].indexOf(sourceResource) === -1) {\n targetResource[targetFieldName].push(sourceResource);\n }\n } else if (targetField.type === \"attr\") {\n throw new Error(`The the inverse relationship for '${sourceFieldName}' is an attribute ('${targetFieldName}')`);\n }\n } else if (sourceField.inverse) {\n throw new Error(`The the inverse relationship for '${sourceFieldName}' is missing ('${sourceField.inverse}')`);\n }\n }\n }\n\n _remove(resource) {\n resource._dependents.forEach(dependent => {\n let dependentResource = this._data[dependent.type][dependent.id];\n switch (this._types[dependent.type][dependent.fieldName].type) {\n case \"has-one\": {\n dependentResource[dependent.fieldName] = null;\n break;\n }\n case \"has-many\": {\n let index = dependentResource[dependent.fieldName].indexOf(resource);\n if (index !== -1) {\n dependentResource[dependent.fieldName].splice(index, 1);\n }\n break;\n }\n default: {\n break;\n }\n }\n // TODO: This only needs to be run once for each dependent.\n dependentResource._dependents = dependentResource._dependents.filter(d => {\n return !(d.type === resource.type && d.id === resource.id);\n });\n });\n delete this._data[resource.type][resource.id];\n }\n\n _removeInverseRelationship(sourceResource, sourceFieldName, targetResource, sourceField) {\n var targetDefinition = this._types[targetResource.type];\n var targetFieldName = sourceField.inverse || sourceResource.type;\n var targetField = targetDefinition && targetDefinition[targetFieldName];\n targetResource._dependents = targetResource._dependents.filter(r => {\n return !(r.type === sourceResource.type && r.id === sourceResource.id && r.fieldName === sourceFieldName);\n });\n if (targetField) {\n if (targetField.type === \"has-one\") {\n sourceResource._dependents = sourceResource._dependents.filter(r => {\n return !(r.type === targetResource.type && r.id === targetResource.id && r.fieldName === targetFieldName);\n });\n targetResource[targetFieldName] = null;\n } else if (targetField.type === \"has-many\") {\n sourceResource._dependents = sourceResource._dependents.filter(r => {\n return !(r.type === targetResource.type && r.id === targetResource.id && r.fieldName === targetFieldName);\n });\n targetResource[targetFieldName] = targetResource[targetFieldName].filter(r => {\n return r !== sourceResource;\n });\n } else if (targetField.type === \"attr\") {\n throw new Error(`The the inverse relationship for '${sourceFieldName}' is an attribute ('${targetFieldName}')`);\n }\n } else if (sourceField.inverse) {\n throw new Error(`The the inverse relationship for '${sourceFieldName}' is missing ('${sourceField.inverse}')`);\n }\n }\n\n}\n\nStore.AjaxAdapter = AjaxAdapter;\n"
+ ]
+}
\ No newline at end of file
diff --git a/releases/v0.5.0/store.js b/releases/v0.5.0/store.js
new file mode 100644
index 0000000..ac21d33
--- /dev/null
+++ b/releases/v0.5.0/store.js
@@ -0,0 +1,717 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+require("array.prototype.find");
+
+var _ajaxAdapter = require("./ajax-adapter");
+
+var _ajaxAdapter2 = _interopRequireDefault(_ajaxAdapter);
+
+var Store = (function () {
+ _createClass(Store, null, [{
+ key: "attr",
+
+ /**
+ * Creates a field definition for an attribute.
+ *
+ * @since 0.1.0
+ * @param {string} [name] - Name of the property to map this field from.
+ * @param {Object} [options] - An options object.
+ * @param {string} [options.default] - Default value for this field.
+ * @return {Object} - Field definition.
+ */
+ value: function attr(name, options) {
+ if (name && typeof name === 'object') {
+ return Store.attr(null, name);
+ } else {
+ return {
+ type: "attr",
+ "default": options && options["default"],
+ deserialize: function deserialize(data, key) {
+ return data.attributes && data.attributes[name || key];
+ },
+ serialize: function serialize(resource, data, key) {
+ data.attributes[name || key] = resource[key];
+ }
+ };
+ }
+ }
+
+ /**
+ * Creates a field definition for an has-one relationship.
+ *
+ * @since 0.1.0
+ * @param {string} [name] - Name of the property to map this field from.
+ * @param {Object} [options] - An options object.
+ * @param {string} [options.inverse] - Name of the inverse relationship.
+ * @return {Object} - Field definition.
+ */
+ }, {
+ key: "hasOne",
+ value: function hasOne(name, options) {
+ if (name && typeof name === 'object') {
+ return Store.hasOne(null, name);
+ } else {
+ return {
+ type: "has-one",
+ inverse: options && options.inverse,
+ deserialize: function deserialize(data, key) {
+ name = name || key;
+ if (data.relationships && data.relationships[name]) {
+ if (data.relationships[name].data === null) {
+ return null;
+ } else if (data.relationships[name].data) {
+ return this.find(data.relationships[name].data.type, data.relationships[name].data.id);
+ }
+ }
+ }
+ };
+ }
+ }
+
+ /**
+ * Creates a field definition for an has-many relationship.
+ *
+ * @since 0.1.0
+ * @param {string} [name] - Name of the property to map this field from.
+ * @param {Object} [options] - An options object.
+ * @param {string} [options.inverse] - Name of the inverse relationship.
+ * @return {Object} - Field definition.
+ */
+ }, {
+ key: "hasMany",
+ value: function hasMany(name, options) {
+ if (name && typeof name === 'object') {
+ return Store.hasMany(null, name);
+ } else {
+ return {
+ type: "has-many",
+ "default": [],
+ inverse: options && options.inverse,
+ deserialize: function deserialize(data, key) {
+ var _this = this;
+
+ name = name || key;
+ if (data.relationships && data.relationships[name]) {
+ if (data.relationships[name].data === null) {
+ return [];
+ } else if (data.relationships[name].data) {
+ return data.relationships[name].data.map(function (c) {
+ return _this.find(c.type, c.id);
+ });
+ }
+ }
+ }
+ };
+ }
+ }
+ }]);
+
+ function Store(adapter) {
+ _classCallCheck(this, Store);
+
+ this._adapter = adapter;
+ this._collectionListeners = { "added": {}, "updated": {}, "removed": {} };
+ this._data = {};
+ this._resourceListeners = { "added": {}, "updated": {}, "removed": {} };
+ this._types = {};
+ }
+
+ /**
+ * Add an individual resource to the store. This is used internally by the
+ * `push()` method.
+ *
+ * @since 0.1.0
+ * @param {!Object} object - Resource Object to add. See:
+ http://jsonapi.org/format/#document-resource-objects
+ * @return {undefined} - Nothing.
+ */
+
+ _createClass(Store, [{
+ key: "add",
+ value: function add(object) {
+ var _this2 = this;
+
+ if (object) {
+ if (object.type && object.id) {
+ (function () {
+ var event = _this2._data[object.type] && _this2._data[object.type][object.id] ? "updated" : "added";
+ var resource = _this2.find(object.type, object.id);
+ var definition = _this2._types[object.type];
+ Object.keys(definition).forEach(function (fieldName) {
+ if (fieldName[0] !== "_") {
+ _this2._addField(object, resource, definition, fieldName);
+ }
+ });
+ if (_this2._resourceListeners[event][object.type] && _this2._resourceListeners[event][object.type][object.id]) {
+ _this2._resourceListeners[event][object.type][object.id].forEach(function (x) {
+ return x[0].call(x[1], resource);
+ });
+ }
+ if (_this2._collectionListeners[event][object.type]) {
+ _this2._collectionListeners[event][object.type].forEach(function (x) {
+ return x[0].call(x[1], resource);
+ });
+ }
+ })();
+ } else {
+ throw new TypeError("The data must have a type and id");
+ }
+ } else {
+ throw new TypeError("You must provide data to add");
+ }
+ }
+
+ /**
+ * Converts the given partial into a JSON API compliant representation.
+ *
+ * @since 0.5.0
+ * @param {!string} [type] - The type of the resource. This can be omitted if the partial includes a type property.
+ * @param {!string} [id] - The id of the resource. This can be omitted if the partial includes an id property.
+ * @param {!object} partial - The data to convert.
+ * @return {object} - JSON API version of the object.
+ */
+ }, {
+ key: "convert",
+ value: function convert(type, id, partial) {
+ var _this3 = this;
+
+ if (type && typeof type === "object") {
+ return this.convert(type.type, type.id, type);
+ } else if (id && typeof id === "object") {
+ return this.convert(type, id.id, id);
+ } else {
+ var _ret2 = (function () {
+ var data = {
+ type: type,
+ attributes: {},
+ relationships: {}
+ };
+ if (id) {
+ data.id = id;
+ }
+ var definition = _this3._types[data.type];
+ Object.keys(definition).forEach(function (fieldName) {
+ if (fieldName[0] !== "_") {
+ definition[fieldName].serialize(partial, data, fieldName);
+ }
+ });
+ return {
+ v: data
+ };
+ })();
+
+ if (typeof _ret2 === "object") return _ret2.v;
+ }
+ }
+
+ /**
+ * Attempts to create the resource through the adapter and adds it to the
+ * store if successful.
+ *
+ * @since 0.5.0
+ * @param {!string} type - Type of resource.
+ * @param {!Object} partial - Data to create the resource with.
+ * @param {function} [success] - Callback on success.
+ * @param {function} [error] - Callback on error.
+ * @param {Object} [context] - Context for the callbacks.
+ * @return {undefined} - Nothing.
+ *
+ * @example
+ * let adapter = new Store.AjaxAdapter();
+ * let store = new Store(adpater);
+ * store.create("product", { title: "A Book" }, (product) => {
+ * console.log(product.title);
+ * });
+ */
+ }, {
+ key: "create",
+ value: function create(type, partial, success, error, context) {
+ if (this._adapter) {
+ this._adapter.create(this, type, partial, success, error, context);
+ } else {
+ throw new Error("Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`");
+ }
+ }
+
+ /**
+ * Defines a type of resource.
+ *
+ * @since 0.2.0
+ * @param {!string|string[]} names - Name(s) of the resource.
+ * @param {!Object} definition - The resource's definition.
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "define",
+ value: function define(names, definition) {
+ var _this4 = this;
+
+ names = names.constructor === Array ? names : [names];
+ if (definition) {
+ definition._names = names;
+ names.forEach(function (name) {
+ if (!_this4._types[name]) {
+ _this4._types[name] = definition;
+ } else {
+ throw new Error("The type '" + name + "' has already been defined.");
+ }
+ });
+ } else {
+ throw new Error("You must provide a definition for the type '" + names[0] + "'.");
+ }
+ }
+
+ /**
+ * Attempts to delete the resource through the adapter and removes it from
+ * the store if successful.
+ *
+ * @since 0.5.0
+ * @param {!string} type - Type of resource.
+ * @param {!string} id - ID of resource.
+ * @param {function} [success] - Callback on success.
+ * @param {function} [error] - Callback on error.
+ * @param {Object} [context] - Context for the callbacks.
+ * @return {undefined} - Nothing.
+ *
+ * @example
+ * let adapter = new Store.AjaxAdapter();
+ * let store = new Store(adpater);
+ * store.destroy("product", "1", () => {
+ * console.log("Destroyed!");
+ * });
+ */
+ }, {
+ key: "destroy",
+ value: function destroy(type, id, success, error, context) {
+ if (this._adapter) {
+ this._adapter.destroy(this, type, id, success, error, context);
+ } else {
+ throw new Error("Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`");
+ }
+ }
+
+ /**
+ * Find a resource or entire collection of resources.
+ *
+ * NOTE: If the resource hasn't been loaded via an add() or push() call it
+ * will be automatically created when find is called.
+ *
+ * @since 0.1.0
+ * @param {!string} type - Type of the resource(s) to find.
+ * @param {string} [id] - The id of the resource to find. If omitted all
+ * resources of the type will be returned.
+ * @return {Object|Object[]} - Either the resource or an array of resources.
+ */
+ }, {
+ key: "find",
+ value: function find(type, id) {
+ var _this5 = this;
+
+ if (type) {
+ var _ret3 = (function () {
+ var definition = _this5._types[type];
+ if (definition) {
+ if (!_this5._data[type]) {
+ (function () {
+ var collection = {};
+ definition._names.forEach(function (t) {
+ return _this5._data[t] = collection;
+ });
+ })();
+ }
+ if (id) {
+ if (!_this5._data[type][id]) {
+ _this5._data[type][id] = {
+ _dependents: [],
+ type: type,
+ id: id
+ };
+ Object.keys(definition).forEach(function (key) {
+ if (key[0] !== "_") {
+ _this5._data[type][id][key] = definition[key]["default"];
+ }
+ });
+ }
+ return {
+ v: _this5._data[type][id]
+ };
+ } else {
+ return {
+ v: Object.keys(_this5._data[type]).map(function (x) {
+ return _this5._data[type][x];
+ })
+ };
+ }
+ } else {
+ throw new TypeError("Unknown type '" + type + "'");
+ }
+ })();
+
+ if (typeof _ret3 === "object") return _ret3.v;
+ } else {
+ throw new TypeError("You must provide a type");
+ }
+ }
+
+ /**
+ * Attempts to load the resource(s) through the adapter and adds it/them to
+ * the store if successful.
+ *
+ * @since 0.5.0
+ * @param {!string} type - Type of resource.
+ * @param {!string} [id] - ID of resource.
+ * @param {Object} [options] - **NOT YET IMPLEMENTED** (this will include sorting, filtering and pagination options)
+ * @param {function} [success] - Callback on success.
+ * @param {function} [error] - Callback on error.
+ * @param {Object} [context] - Context for the callbacks.
+ * @return {undefined} - Nothing.
+ *
+ * @example
+ * let adapter = new Store.AjaxAdapter();
+ * let store = new Store(adpater);
+ * store.load("product", "1", (product) => {
+ * console.log(product.title);
+ * });
+ */
+ }, {
+ key: "load",
+ value: function load(type, id, options, success, error, context) {
+ if (this._adapter) {
+ this._adapter.load(this, type, id, options, success, error, context);
+ } else {
+ throw new Error("Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`");
+ }
+ }
+
+ /**
+ * Unregister an event listener that was registered with on().
+ *
+ * @since 0.4.0
+ * @param {string} event - Name of the event.
+ * @param {string} type - Name of resource to originally passed to on().
+ * @param {string} [id] - ID of the resource to originally passed to on().
+ * @param {function} callback - Function originally passed to on().
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "off",
+ value: function off(event, type, id, callback) {
+ var _this6 = this;
+
+ if (this._resourceListeners[event] && this._collectionListeners[event]) {
+ if (this._types[type]) {
+ if (id && ({}).toString.call(id) === '[object Function]') {
+ this.off.call(this, event, type, null, id, callback);
+ } else {
+ // TODO: Performance-wise, this can be made way better. There shouldn't be a need to maintain separate lists.
+ this._types[type]._names.forEach(function (type) {
+ if (id) {
+ if (_this6._resourceListeners[event][type] && _this6._resourceListeners[event][type][id]) {
+ _this6._resourceListeners[event][type][id] = _this6._resourceListeners[event][type][id].filter(function (x) {
+ return x[0] !== callback;
+ });
+ }
+ } else if (_this6._collectionListeners[event][type]) {
+ _this6._collectionListeners[event][type] = _this6._collectionListeners[event][type].filter(function (x) {
+ return x[0] !== callback;
+ });
+ }
+ });
+ }
+ } else {
+ throw new Error("Unknown type '" + type + "'");
+ }
+ } else {
+ throw new Error("Unknown event '" + event + "'");
+ }
+ }
+
+ /**
+ * Register an event listener: "added", "updated" or "removed".
+ *
+ * @since 0.4.0
+ * @param {string} event - Name of the event.
+ * @param {string} type - Name of resource to watch.
+ * @param {string} [id] - ID of the resource to watch.
+ * @param {function} callback - Function to call when the event occurs.
+ * @param {Object} [context] - Context in which to call the callback.
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "on",
+ value: function on(event, type, id, callback, context) {
+ var _this7 = this;
+
+ if (this._resourceListeners[event] && this._collectionListeners[event]) {
+ if (this._types[type]) {
+ if (id && ({}).toString.call(id) === '[object Function]') {
+ this.on.call(this, event, type, null, id, callback);
+ } else {
+ // TODO: Performance-wise, this can be made way better. There shouldn't be a need to maintain separate lists.
+ this._types[type]._names.forEach(function (type) {
+ if (id) {
+ _this7._resourceListeners[event][type] = _this7._resourceListeners[event][type] || {};
+ _this7._resourceListeners[event][type][id] = _this7._resourceListeners[event][type][id] || [];
+ if (!_this7._resourceListeners[event][type][id].find(function (x) {
+ return x[0] === callback;
+ })) {
+ _this7._resourceListeners[event][type][id].push([callback, context]);
+ }
+ } else {
+ _this7._collectionListeners[event][type] = _this7._collectionListeners[event][type] || [];
+ if (!_this7._collectionListeners[event][type].find(function (x) {
+ return x[0] === callback;
+ })) {
+ _this7._collectionListeners[event][type].push([callback, context]);
+ }
+ }
+ });
+ }
+ } else {
+ throw new Error("Unknown type '" + type + "'");
+ }
+ } else {
+ throw new Error("Unknown event '" + event + "'");
+ }
+ }
+
+ /**
+ * Add a JSON API response to the store. This method can be used to handle a
+ * successful GET or POST response from the server.
+ *
+ * @since 0.1.0
+ * @param {Object} root - Top Level Object to push. See:
+ http://jsonapi.org/format/#document-top-level
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "push",
+ value: function push(root) {
+ var _this8 = this;
+
+ if (root.data.constructor === Array) {
+ root.data.forEach(function (x) {
+ return _this8.add(x);
+ });
+ } else {
+ this.add(root.data);
+ }
+ if (root.included) {
+ root.included.forEach(function (x) {
+ return _this8.add(x);
+ });
+ }
+ }
+
+ /**
+ * Remove a resource or collection of resources from the store.
+ *
+ * @since 0.1.0
+ * @param {!string} type - Type of the resource(s) to remove.
+ * @param {string} [id] - The id of the resource to remove. If omitted all
+ * resources of the type will be removed.
+ * @return {undefined} - Nothing.
+ */
+ }, {
+ key: "remove",
+ value: function remove(type, id) {
+ var _this9 = this;
+
+ if (type) {
+ if (this._types[type]) {
+ if (id) {
+ (function () {
+ var resource = _this9._data[type] && _this9._data[type][id];
+ if (resource) {
+ _this9._remove(resource);
+ if (_this9._resourceListeners["removed"][type] && _this9._resourceListeners["removed"][type][id]) {
+ _this9._resourceListeners["removed"][type][id].forEach(function (x) {
+ return x[0].call(x[1], resource);
+ });
+ }
+ if (_this9._collectionListeners["removed"][type]) {
+ _this9._collectionListeners["removed"][type].forEach(function (x) {
+ return x[0].call(x[1], resource);
+ });
+ }
+ }
+ })();
+ } else {
+ Object.keys(this._data[type]).forEach(function (id) {
+ return _this9.remove(type, id);
+ });
+ }
+ } else {
+ throw new TypeError("Unknown type '" + type + "'");
+ }
+ } else {
+ throw new TypeError("You must provide a type to remove");
+ }
+ }
+
+ /**
+ * Attempts to update the resource through the adapter and updates it in the
+ * store if successful.
+ *
+ * @since 0.5.0
+ * @param {!string} type - Type of resource.
+ * @param {!string} id - ID of resource.
+ * @param {!Object} partial - Data to update the resource with.
+ * @param {function} [success] - Callback on success.
+ * @param {function} [error] - Callback on error.
+ * @param {Object} [context] - Context for the callbacks.
+ * @return {undefined} - Nothing.
+ *
+ * @example
+ * let adapter = new Store.AjaxAdapter();
+ * let store = new Store(adpater);
+ * store.update("product", "1", { title: "foo" }, (product) => {
+ * console.log(product.title);
+ * });
+ */
+ }, {
+ key: "update",
+ value: function update(type, id, partial, success, error, context) {
+ if (this._adapter) {
+ this._adapter.update(this, type, id, partial, success, error, context);
+ } else {
+ throw new Error("Adapter missing. Specify an adapter when creating the store: `var store = new Store(adapter);`");
+ }
+ }
+ }, {
+ key: "_addField",
+ value: function _addField(object, resource, definition, fieldName) {
+ var _this10 = this;
+
+ var field = definition[fieldName];
+ var newValue = field.deserialize.call(this, object, fieldName);
+ if (typeof newValue !== "undefined") {
+ if (field.type === "has-one") {
+ if (resource[fieldName]) {
+ this._removeInverseRelationship(resource, fieldName, resource[fieldName], field);
+ }
+ if (newValue) {
+ this._addInverseRelationship(resource, fieldName, newValue, field);
+ }
+ } else if (field.type === "has-many") {
+ resource[fieldName].forEach(function (r) {
+ if (resource[fieldName].indexOf(r) !== -1) {
+ _this10._removeInverseRelationship(resource, fieldName, r, field);
+ }
+ });
+ newValue.forEach(function (r) {
+ _this10._addInverseRelationship(resource, fieldName, r, field);
+ });
+ }
+ resource[fieldName] = newValue;
+ }
+ }
+ }, {
+ key: "_addInverseRelationship",
+ value: function _addInverseRelationship(sourceResource, sourceFieldName, targetResource, sourceField) {
+ var targetDefinition = this._types[targetResource.type];
+ var sourceDefinition = this._types[sourceResource.type];
+ if (targetDefinition) {
+ var targetFieldName = [sourceField.inverse].concat(sourceDefinition._names).find(function (x) {
+ return targetDefinition[x];
+ });
+ var targetField = targetDefinition && targetDefinition[targetFieldName];
+ targetResource._dependents.push({ type: sourceResource.type, id: sourceResource.id, fieldName: sourceFieldName });
+ if (targetField) {
+ if (targetField.type === "has-one") {
+ sourceResource._dependents.push({ type: targetResource.type, id: targetResource.id, fieldName: targetFieldName });
+ targetResource[targetFieldName] = sourceResource;
+ } else if (targetField.type === "has-many") {
+ sourceResource._dependents.push({ type: targetResource.type, id: targetResource.id, fieldName: targetFieldName });
+ if (targetResource[targetFieldName].indexOf(sourceResource) === -1) {
+ targetResource[targetFieldName].push(sourceResource);
+ }
+ } else if (targetField.type === "attr") {
+ throw new Error("The the inverse relationship for '" + sourceFieldName + "' is an attribute ('" + targetFieldName + "')");
+ }
+ } else if (sourceField.inverse) {
+ throw new Error("The the inverse relationship for '" + sourceFieldName + "' is missing ('" + sourceField.inverse + "')");
+ }
+ }
+ }
+ }, {
+ key: "_remove",
+ value: function _remove(resource) {
+ var _this11 = this;
+
+ resource._dependents.forEach(function (dependent) {
+ var dependentResource = _this11._data[dependent.type][dependent.id];
+ switch (_this11._types[dependent.type][dependent.fieldName].type) {
+ case "has-one":
+ {
+ dependentResource[dependent.fieldName] = null;
+ break;
+ }
+ case "has-many":
+ {
+ var index = dependentResource[dependent.fieldName].indexOf(resource);
+ if (index !== -1) {
+ dependentResource[dependent.fieldName].splice(index, 1);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ // TODO: This only needs to be run once for each dependent.
+ dependentResource._dependents = dependentResource._dependents.filter(function (d) {
+ return !(d.type === resource.type && d.id === resource.id);
+ });
+ });
+ delete this._data[resource.type][resource.id];
+ }
+ }, {
+ key: "_removeInverseRelationship",
+ value: function _removeInverseRelationship(sourceResource, sourceFieldName, targetResource, sourceField) {
+ var targetDefinition = this._types[targetResource.type];
+ var targetFieldName = sourceField.inverse || sourceResource.type;
+ var targetField = targetDefinition && targetDefinition[targetFieldName];
+ targetResource._dependents = targetResource._dependents.filter(function (r) {
+ return !(r.type === sourceResource.type && r.id === sourceResource.id && r.fieldName === sourceFieldName);
+ });
+ if (targetField) {
+ if (targetField.type === "has-one") {
+ sourceResource._dependents = sourceResource._dependents.filter(function (r) {
+ return !(r.type === targetResource.type && r.id === targetResource.id && r.fieldName === targetFieldName);
+ });
+ targetResource[targetFieldName] = null;
+ } else if (targetField.type === "has-many") {
+ sourceResource._dependents = sourceResource._dependents.filter(function (r) {
+ return !(r.type === targetResource.type && r.id === targetResource.id && r.fieldName === targetFieldName);
+ });
+ targetResource[targetFieldName] = targetResource[targetFieldName].filter(function (r) {
+ return r !== sourceResource;
+ });
+ } else if (targetField.type === "attr") {
+ throw new Error("The the inverse relationship for '" + sourceFieldName + "' is an attribute ('" + targetFieldName + "')");
+ }
+ } else if (sourceField.inverse) {
+ throw new Error("The the inverse relationship for '" + sourceFieldName + "' is missing ('" + sourceField.inverse + "')");
+ }
+ }
+ }]);
+
+ return Store;
+})();
+
+exports["default"] = Store;
+
+Store.AjaxAdapter = _ajaxAdapter2["default"];
+module.exports = exports["default"];
diff --git a/releases/v0.5.0/store.prod.js b/releases/v0.5.0/store.prod.js
new file mode 100644
index 0000000..3669dfa
--- /dev/null
+++ b/releases/v0.5.0/store.prod.js
@@ -0,0 +1,43 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Store = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o
+// For all details and docs: https://github.com/paulmillr/array.prototype.find
+// Fixes and tests supplied by Duncan Hall
+(function(globals){
+ if (Array.prototype.find) return;
+
+ var find = function(predicate) {
+ var list = Object(this);
+ var length = list.length < 0 ? 0 : list.length >>> 0; // ES.ToUint32;
+ if (length === 0) return undefined;
+ if (typeof predicate !== 'function' || Object.prototype.toString.call(predicate) !== '[object Function]') {
+ throw new TypeError('Array#find: predicate must be a function');
+ }
+ var thisArg = arguments[1];
+ for (var i = 0, value; i < length; i++) {
+ value = list[i];
+ if (predicate.call(thisArg, value, i, list)) return value;
+ }
+ return undefined;
+ };
+
+ if (Object.defineProperty) {
+ try {
+ Object.defineProperty(Array.prototype, 'find', {
+ value: find, configurable: true, enumerable: false, writable: true
+ });
+ } catch(e) {}
+ }
+
+ if (!Array.prototype.find) {
+ Array.prototype.find = find;
+ }
+})(this);
+
+},{}],2:[function(require,module,exports){
+"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var n=0;n=200&&i.status<300){var t=JSON.parse(i.responseText);try{e.push(t),a&&a.call(o,e.find(t.data.type,t.data.id))}catch(n){l&&l.call(o,n)}}else l&&l.call(o)},i.send({data:JSON.stringify(e.convert(t,n))})}()}}},{key:"destroy",value:function(e,t,n,a,l,o){var s=this;if(l&&"[object Function]"!=={}.toString.call(l))this.destroy(e,t,n,a,null,l);else{if(!e._types[t])throw new Error("Unknown type '"+t+"'");!function(){var i=new XMLHttpRequest;i.open("DELETE",s._base+"/"+t+"/"+n,!0),i.onload=function(){if(i.status>=200&&i.status<300)try{e.remove(t,n),a&&a.call(o)}catch(s){l.call(o,s)}else l&&l.call(o)},i.send()}()}}},{key:"load",value:function(e,t,n,a,l,o,s){var i=this;if(n&&"[object Function]"==={}.toString.call(n))this.load(e,t,null,null,n,a,l);else if(n&&"object"==typeof n)this.load(e,t,null,n,a,l,o);else if(a&&"[object Function]"==={}.toString.call(a))this.load(e,t,n,{},a,l,o);else if(o&&"[object Function]"!=={}.toString.call(o))this.load(e,t,n,a,l,null,o);else{if(!e._types[t])throw new Error("Unknown type '"+t+"'");!function(){var r=new XMLHttpRequest,c=void 0;if(a=a||{},c=n?i._base+"/"+t+"/"+n:i._base+"/"+t,a){var u=[];a.fields&&(Object.keys(a.fields).forEach(function(e){a["fields["+e+"]"]=a.fields[e]}),delete a.fields),u=Object.keys(a).map(function(e){return e+"="+encodeURIComponent(a[e])}).sort(),u.length&&(c=c+"?"+u.join("&"))}r.open("GET",c,!0),r.onload=function(){if(r.status>=200&&r.status<300)try{e.push(JSON.parse(r.responseText)),l&&l.call(s,n?e.find(t,n):e.find(t))}catch(a){o.call({},a)}else o&&o.call(s)},r.send()}()}}},{key:"update",value:function(e,t,n,a,l,o,s){var i=this;if(o&&"[object Function]"!=={}.toString.call(o))this.update(e,t,n,a,l,null,o);else{if(!e._types[t])throw new Error("Unknown type '"+t+"'");!function(){var r=new XMLHttpRequest,c=e.convert(t,n,a);r.open("PATCH",i._base+"/"+t+"/"+n,!0),r.onload=function(){if(r.status>=200&&r.status<300)try{e.add(c),l&&l.call(s,e.find(c.type,c.id))}catch(t){o&&o.call(s,t)}else o&&o.call(s)},r.send({data:JSON.stringify(c)})}()}}}]),e}();exports["default"]=AjaxAdapter,module.exports=exports["default"];
+
+},{}],3:[function(require,module,exports){
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r