diff --git a/index.html b/index.html index 358097f..fc58022 100644 --- a/index.html +++ b/index.html @@ -184,14 +184,14 @@
- + - Download v0.4.1 + Download v0.5.0
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": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;ICjCqB,WAAW;AAEnB,WAFQ,WAAW,CAElB,OAAO,EAAE;0BAFF,WAAW;;AAG5B,QAAI,CAAC,KAAK,GAAG,AAAC,OAAO,IAAI,OAAO,CAAC,IAAI,IAAK,EAAE,CAAC;GAC9C;;eAJkB,WAAW;;WAMxB,gBAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;;;AAEpD,UAAI,KAAK,IAAI,CAAA,GAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,mBAAmB,EAAE;;AAE5D,YAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;OAEzD,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;;;AAE7B,cAAI,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC;;AAEnC,iBAAO,CAAC,IAAI,CAAC,MAAM,EAAK,MAAK,KAAK,SAAI,IAAI,EAAI,IAAI,CAAC,CAAC;;AAEpD,iBAAO,CAAC,MAAM,GAAG,YAAY;AAC3B,gBAAI,OAAO,CAAC,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;AACjD,kBAAI,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;AAChD,kBAAI;AACF,qBAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACrB,oBAAI,OAAO,EAAE;AACX,yBAAO,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;iBACzE;eACF,CAAC,OAAO,CAAC,EAAE;AACV,oBAAI,KAAK,EAAE;AACT,uBAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;iBACxB;eACF;aACF,MAAM;AACL,kBAAI,KAAK,EAAE;AACT,qBAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;eACrB;aACF;WACF,CAAC;;AAEF,iBAAO,CAAC,IAAI,CAAC;AACX,gBAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;WACnD,CAAC,CAAC;;OAEJ,MAAM;AACL,cAAM,IAAI,KAAK,qBAAkB,IAAI,QAAI,CAAC;OAC3C;KAEF;;;WAEM,iBAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;;;AAEhD,UAAI,KAAK,IAAI,CAAA,GAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,mBAAmB,EAAE;;AAE5D,YAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;OAErD,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;;;AAE7B,cAAI,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC;;AAEnC,iBAAO,CAAC,IAAI,CAAC,QAAQ,EAAK,OAAK,KAAK,SAAI,IAAI,SAAI,EAAE,EAAI,IAAI,CAAC,CAAC;;AAE5D,iBAAO,CAAC,MAAM,GAAG,YAAY;AAC3B,gBAAI,OAAO,CAAC,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;AACjD,kBAAI;AACF,qBAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACvB,oBAAI,OAAO,EAAE;AACX,yBAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;iBACvB;eACF,CAAC,OAAO,CAAC,EAAE;AACV,qBAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;eACxB;aACF,MAAM,IAAI,KAAK,EAAE;AAChB,mBAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;aACrB;WACF,CAAC;;AAEF,iBAAO,CAAC,IAAI,EAAE,CAAC;;OAEhB,MAAM;AACL,cAAM,IAAI,KAAK,qBAAkB,IAAI,QAAI,CAAC;OAC3C;KAEF;;;WAEG,cAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;;;AAEtD,UAAI,EAAE,IAAI,CAAA,GAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,mBAAmB,EAAE;AACtD,YAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;OAC1D,MAAM,IAAI,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE;AACvC,YAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;OAC3D,MAAM,IAAI,OAAO,IAAI,CAAA,GAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,mBAAmB,EAAE;AACvE,YAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;OACzD,MAAM,IAAI,KAAK,IAAI,CAAA,GAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,mBAAmB,EAAE;AACnE,YAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;OAC3D,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;;;AAE7B,cAAI,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC;AACnC,cAAI,GAAG,YAAA,CAAC;;AAER,iBAAO,GAAG,OAAO,IAAI,EAAE,CAAC;AACxB,aAAG,GAAG,EAAE,GAAM,OAAK,KAAK,SAAI,IAAI,SAAI,EAAE,GAAQ,OAAK,KAAK,SAAI,IAAI,AAAE,CAAC;;AAEnE,cAAI,OAAO,EAAE;;AAEX,gBAAI,MAAM,GAAG,EAAE,CAAC;;AAEhB,gBAAI,OAAO,CAAC,MAAM,EAAE;AAClB,oBAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAA,KAAK,EAAI;AAC3C,uBAAO,aAAW,KAAK,OAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;eACrD,CAAC,CAAC;AACH,qBAAO,OAAO,CAAC,MAAM,CAAC;aACvB;;AAED,kBAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,UAAA,GAAG,EAAI;AACvC,qBAAO,GAAG,GAAG,GAAG,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;aACrD,CAAC,CAAC,IAAI,EAAE,CAAC;;AAEV,gBAAI,MAAM,CAAC,MAAM,EAAE;AACjB,iBAAG,GAAM,GAAG,SAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,AAAE,CAAC;aACpC;WAEF;;AAED,iBAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;;AAE/B,iBAAO,CAAC,MAAM,GAAG,YAAY;AAC3B,gBAAI,OAAO,CAAC,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;AACjD,kBAAI;AACF,qBAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;AAC7C,oBAAI,OAAO,EAAE;AACX,yBAAO,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;iBACrE;eACF,CAAC,OAAO,CAAC,EAAE;AACV,qBAAK,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;eACnB;aACF,MAAM,IAAI,KAAK,EAAE;AAChB,mBAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;aACrB;WACF,CAAC;;AAEF,iBAAO,CAAC,IAAI,EAAE,CAAC;;OAEhB,MAAM;AACL,cAAM,IAAI,KAAK,qBAAkB,IAAI,QAAI,CAAC;OAC3C;KAEF;;;WAEK,gBAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;;;AAExD,UAAI,KAAK,IAAI,CAAA,GAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,mBAAmB,EAAE;;AAE5D,YAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;OAE7D,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;;;AAE7B,cAAI,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC;AACnC,cAAI,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;;AAE5C,iBAAO,CAAC,IAAI,CAAC,OAAO,EAAK,OAAK,KAAK,SAAI,IAAI,SAAI,EAAE,EAAI,IAAI,CAAC,CAAC;;AAE3D,iBAAO,CAAC,MAAM,GAAG,YAAY;AAC3B,gBAAI,OAAO,CAAC,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;AACjD,kBAAI;AACF,qBAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAChB,oBAAI,OAAO,EAAE;AACX,yBAAO,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;iBACvD;eACF,CAAC,OAAO,CAAC,EAAE;AACV,oBAAI,KAAK,EAAE;AACT,uBAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;iBACxB;eACF;aACF,MAAM,IAAI,KAAK,EAAE;AAChB,mBAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;aACrB;WACF,CAAC;;AAEF,iBAAO,CAAC,IAAI,CAAC;AACX,gBAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;WAC3B,CAAC,CAAC;;OAEJ,MAAM;AACL,cAAM,IAAI,KAAK,qBAAkB,IAAI,QAAI,CAAC;OAC3C;KAEF;;;SAzLkB,WAAW;;;qBAAX,WAAW;;;;;;;;;;;;;;;;QCAzB,sBAAsB;;2BACL,gBAAgB;;;;IAEnB,KAAK;eAAL,KAAK;;;;;;;;;;;;WAWb,cAAC,IAAI,EAAE,OAAO,EAAE;AACzB,UAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AACpC,eAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;OAC/B,MAAM;AACL,eAAO;AACL,cAAI,EAAE,MAAM;AACZ,qBAAS,OAAO,IAAI,OAAO,WAAQ;AACnC,qBAAW,EAAE,qBAAU,IAAI,EAAE,GAAG,EAAE;AAChC,mBAAO,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;WACxD;AACD,mBAAS,EAAE,mBAAU,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE;AACxC,gBAAI,CAAC,UAAU,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;WAC9C;SACF,CAAC;OACH;KACF;;;;;;;;;;;;;WAWY,gBAAC,IAAI,EAAE,OAAO,EAAE;AAC3B,UAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AACpC,eAAO,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;OACjC,MAAM;AACL,eAAO;AACL,cAAI,EAAE,SAAS;AACf,iBAAO,EAAE,OAAO,IAAI,OAAO,CAAC,OAAO;AACnC,qBAAW,EAAE,qBAAU,IAAI,EAAE,GAAG,EAAE;AAChC,gBAAI,GAAG,IAAI,IAAI,GAAG,CAAC;AACnB,gBAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE;AAClD,kBAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,EAAE;AAC1C,uBAAO,IAAI,CAAC;eACb,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE;AACxC,uBAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;eACxF;aACF;WACF;SACF,CAAC;OACH;KACF;;;;;;;;;;;;;WAWa,iBAAC,IAAI,EAAE,OAAO,EAAE;AAC5B,UAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AACpC,eAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;OAClC,MAAM;AACL,eAAO;AACL,cAAI,EAAE,UAAU;AAChB,qBAAS,EAAE;AACX,iBAAO,EAAE,OAAO,IAAI,OAAO,CAAC,OAAO;AACnC,qBAAW,EAAE,qBAAU,IAAI,EAAE,GAAG,EAAE;;;AAChC,gBAAI,GAAG,IAAI,IAAI,GAAG,CAAC;AACnB,gBAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE;AAClD,kBAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,EAAE;AAC1C,uBAAO,EAAE,CAAC;eACX,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE;AACxC,uBAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAC,CAAC,EAAK;AAC9C,yBAAO,MAAK,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;iBAChC,CAAC,CAAC;eACJ;aACF;WACF;SACF,CAAC;OACH;KACF;;;AAEU,WA3FQ,KAAK,CA2FZ,OAAO,EAAE;0BA3FF,KAAK;;AA4FtB,QAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;AACxB,QAAI,CAAC,oBAAoB,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAC1E,QAAI,CAAC,KAAK,GAAG,EAAE,CAAC;AAChB,QAAI,CAAC,kBAAkB,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AACxE,QAAI,CAAC,MAAM,GAAG,EAAE,CAAC;GAClB;;;;;;;;;;;;eAjGkB,KAAK;;WA4GrB,aAAC,MAAM,EAAE;;;AACV,UAAI,MAAM,EAAE;AACV,YAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,EAAE;;AAC5B,gBAAI,KAAK,GAAG,OAAK,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,OAAK,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC;AAChG,gBAAI,QAAQ,GAAG,OAAK,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AACjD,gBAAI,UAAU,GAAG,OAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1C,kBAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,UAAA,SAAS,EAAI;AAC3C,kBAAI,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;AACxB,uBAAK,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;eACzD;aACF,CAAC,CAAC;AACH,gBAAI,OAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,OAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;AACxG,qBAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,UAAA,CAAC;uBAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;eAAA,CAAC,CAAC;aACjG;AACD,gBAAI,OAAK,oBAAoB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;AACjD,qBAAK,oBAAoB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAA,CAAC;uBAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;eAAA,CAAC,CAAC;aACvF;;SACF,MAAM;AACL,gBAAM,IAAI,SAAS,oCAAoC,CAAC;SACzD;OACF,MAAM;AACL,cAAM,IAAI,SAAS,gCAAgC,CAAC;OACrD;KACF;;;;;;;;;;;;;WAWM,iBAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE;;;AACzB,UAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AACpC,eAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;OAC/C,MAAM,IAAI,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE;AACvC,eAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;OACtC,MAAM;;AACL,cAAI,IAAI,GAAG;AACT,gBAAI,EAAE,IAAI;AACV,sBAAU,EAAE,EAAE;AACd,yBAAa,EAAE,EAAE;WAClB,CAAC;AACF,cAAI,EAAE,EAAE;AACN,gBAAI,CAAC,EAAE,GAAG,EAAE,CAAC;WACd;AACD,cAAI,UAAU,GAAG,OAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxC,gBAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,UAAA,SAAS,EAAI;AAC3C,gBAAI,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;AACxB,wBAAU,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;aAC3D;WACF,CAAC,CAAC;AACH;eAAO,IAAI;YAAC;;;;OACb;KACF;;;;;;;;;;;;;;;;;;;;;;;WAqBK,gBAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;AAC7C,UAAI,IAAI,CAAC,QAAQ,EAAE;AACjB,YAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;OACpE,MAAM;AACL,cAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;OACnH;KACF;;;;;;;;;;;;WAUK,gBAAC,KAAK,EAAE,UAAU,EAAE;;;AACxB,WAAK,GAAG,AAAC,KAAK,CAAC,WAAW,KAAK,KAAK,GAAI,KAAK,GAAG,CAAE,KAAK,CAAE,CAAC;AAC1D,UAAI,UAAU,EAAE;AACd,kBAAU,CAAC,MAAM,GAAG,KAAK,CAAC;AAC1B,aAAK,CAAC,OAAO,CAAC,UAAA,IAAI,EAAI;AACpB,cAAI,CAAC,OAAK,MAAM,CAAC,IAAI,CAAC,EAAE;AACtB,mBAAK,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC;WAChC,MAAM;AACL,kBAAM,IAAI,KAAK,gBAAc,IAAI,iCAA8B,CAAC;WACjE;SACF,CAAC,CAAC;OACJ,MAAM;AACL,cAAM,IAAI,KAAK,kDAAgD,KAAK,CAAC,CAAC,CAAC,QAAK,CAAC;OAC9E;KACF;;;;;;;;;;;;;;;;;;;;;;;WAqBM,iBAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;AACzC,UAAI,IAAI,CAAC,QAAQ,EAAE;AACjB,YAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;OAChE,MAAM;AACL,cAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;OACnH;KACF;;;;;;;;;;;;;;;;WAcG,cAAC,IAAI,EAAE,EAAE,EAAE;;;AACb,UAAI,IAAI,EAAE;;AACR,cAAI,UAAU,GAAG,OAAK,MAAM,CAAC,IAAI,CAAC,CAAC;AACnC,cAAI,UAAU,EAAE;AACd,gBAAI,CAAC,OAAK,KAAK,CAAC,IAAI,CAAC,EAAE;;AACrB,oBAAI,UAAU,GAAG,EAAE,CAAC;AACpB,0BAAU,CAAC,MAAM,CAAC,OAAO,CAAC,UAAA,CAAC;yBAAI,OAAK,KAAK,CAAC,CAAC,CAAC,GAAG,UAAU;iBAAA,CAAC,CAAC;;aAC5D;AACD,gBAAI,EAAE,EAAE;AACN,kBAAI,CAAC,OAAK,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE;AACzB,uBAAK,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG;AACrB,6BAAW,EAAE,EAAE;AACf,sBAAI,EAAE,IAAI;AACV,oBAAE,EAAE,EAAE;iBACP,CAAC;AACF,sBAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,UAAA,GAAG,EAAI;AACrC,sBAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;AAClB,2BAAK,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,WAAQ,CAAC;mBACrD;iBACF,CAAC,CAAC;eACJ;AACD;mBAAO,OAAK,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAAC;aAC7B,MAAM;AACL;mBAAO,MAAM,CAAC,IAAI,CAAC,OAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,UAAA,CAAC;yBAAI,OAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;iBAAA,CAAC;gBAAC;aACpE;WACF,MAAM;AACL,kBAAM,IAAI,SAAS,oBAAkB,IAAI,OAAI,CAAC;WAC/C;;;;OACF,MAAM;AACL,cAAM,IAAI,SAAS,2BAA2B,CAAC;OAChD;KACF;;;;;;;;;;;;;;;;;;;;;;;;WAsBG,cAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;AAC/C,UAAI,IAAI,CAAC,QAAQ,EAAE;AACjB,YAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;OACtE,MAAM;AACL,cAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;OACnH;KACF;;;;;;;;;;;;;;WAYE,aAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE;;;AAC7B,UAAI,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE;AACtE,YAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;AACrB,cAAI,EAAE,IAAI,CAAC,GAAE,CAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,mBAAmB,EAAE;AACxD,gBAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;WACtD,MAAM;;AAEL,gBAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,UAAA,IAAI,EAAI;AACvC,kBAAI,EAAE,EAAE;AACN,oBAAI,OAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,OAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE;AACpF,yBAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,OAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,UAAA,CAAC,EAAI;AAC9F,2BAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;mBAC1B,CAAC,CAAC;iBACJ;eACF,MAAM,IAAI,OAAK,oBAAoB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE;AACjD,uBAAK,oBAAoB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,OAAK,oBAAoB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,UAAA,CAAC,EAAI;AAC1F,yBAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;iBAC1B,CAAC,CAAC;eACJ;aACF,CAAC,CAAC;WACJ;SACF,MAAM;AACL,gBAAM,IAAI,KAAK,oBAAkB,IAAI,OAAI,CAAC;SAC3C;OACF,MAAM;AACL,cAAM,IAAI,KAAK,qBAAmB,KAAK,OAAI,CAAC;OAC7C;KACF;;;;;;;;;;;;;;;WAaC,YAAC,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE;;;AACrC,UAAI,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE;AACtE,YAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;AACrB,cAAI,EAAE,IAAI,CAAC,GAAE,CAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,mBAAmB,EAAE;AACxD,gBAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;WACrD,MAAM;;AAEL,gBAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,UAAA,IAAI,EAAI;AACvC,kBAAI,EAAE,EAAE;AACN,uBAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,OAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AAClF,uBAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,OAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;AAC1F,oBAAI,CAAC,OAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,UAAA,CAAC;yBAAI,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ;iBAAA,CAAC,EAAE;AAC1E,yBAAK,kBAAkB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAE,QAAQ,EAAE,OAAO,CAAE,CAAC,CAAC;iBACtE;eACF,MAAM;AACL,uBAAK,oBAAoB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,OAAK,oBAAoB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AACtF,oBAAI,CAAC,OAAK,oBAAoB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAA,CAAC;yBAAI,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ;iBAAA,CAAC,EAAE;AACxE,yBAAK,oBAAoB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAE,QAAQ,EAAE,OAAO,CAAE,CAAC,CAAC;iBACpE;eACF;aACF,CAAC,CAAC;WACJ;SACF,MAAM;AACL,gBAAM,IAAI,KAAK,oBAAkB,IAAI,OAAI,CAAC;SAC3C;OACF,MAAM;AACL,cAAM,IAAI,KAAK,qBAAmB,KAAK,OAAI,CAAC;OAC7C;KACF;;;;;;;;;;;;;WAWG,cAAC,IAAI,EAAE;;;AACT,UAAI,IAAI,CAAC,IAAI,CAAC,WAAW,KAAK,KAAK,EAAE;AACnC,YAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAA,CAAC;iBAAI,OAAK,GAAG,CAAC,CAAC,CAAC;SAAA,CAAC,CAAC;OACrC,MAAM;AACL,YAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;OACrB;AACD,UAAI,IAAI,CAAC,QAAQ,EAAE;AACjB,YAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAA,CAAC;iBAAI,OAAK,GAAG,CAAC,CAAC,CAAC;SAAA,CAAC,CAAC;OACzC;KACF;;;;;;;;;;;;;WAWK,gBAAC,IAAI,EAAE,EAAE,EAAE;;;AACf,UAAI,IAAI,EAAE;AACR,YAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;AACrB,cAAI,EAAE,EAAE;;AACN,kBAAI,QAAQ,GAAG,OAAK,KAAK,CAAC,IAAI,CAAC,IAAI,OAAK,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;AACxD,kBAAI,QAAQ,EAAE;AACZ,uBAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AACvB,oBAAI,OAAK,kBAAkB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,OAAK,kBAAkB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE;AAC3F,yBAAK,kBAAkB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,UAAA,CAAC;2BAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;mBAAA,CAAC,CAAC;iBACvF;AACD,oBAAI,OAAK,oBAAoB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE;AAC9C,yBAAK,oBAAoB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAA,CAAC;2BAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;mBAAA,CAAC,CAAC;iBACpF;eACF;;WACF,MAAM;AACL,kBAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,UAAA,EAAE;qBAAI,OAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;aAAA,CAAC,CAAC;WACpE;SACF,MAAM;AACL,gBAAM,IAAI,SAAS,oBAAkB,IAAI,OAAI,CAAC;SAC/C;OACF,MAAM;AACL,cAAM,IAAI,SAAS,qCAAqC,CAAC;OAC1D;KACF;;;;;;;;;;;;;;;;;;;;;;;;WAsBK,gBAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;AACjD,UAAI,IAAI,CAAC,QAAQ,EAAE;AACjB,YAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;OACxE,MAAM;AACL,cAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;OACnH;KACF;;;WAEQ,mBAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE;;;AACjD,UAAI,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;AAClC,UAAI,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAC/D,UAAI,OAAO,QAAQ,KAAK,WAAW,EAAE;AACnC,YAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE;AAC5B,cAAI,QAAQ,CAAC,SAAS,CAAC,EAAE;AACvB,gBAAI,CAAC,0BAA0B,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;WAClF;AACD,cAAI,QAAQ,EAAE;AACZ,gBAAI,CAAC,uBAAuB,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;WACpE;SACF,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE;AACpC,kBAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,UAAA,CAAC,EAAI;AAC/B,gBAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACzC,sBAAK,0BAA0B,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;aAChE;WACF,CAAC,CAAC;AACH,kBAAQ,CAAC,OAAO,CAAC,UAAA,CAAC,EAAI;AACpB,oBAAK,uBAAuB,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;WAC7D,CAAC,CAAC;SACJ;AACD,gBAAQ,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;OAChC;KACF;;;WAEsB,iCAAC,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE;AACpF,UAAI,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACxD,UAAI,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACxD,UAAI,gBAAgB,EAAE;AACpB,YAAI,eAAe,GAAG,CAAE,WAAW,CAAC,OAAO,CAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAA,CAAC;iBAAI,gBAAgB,CAAC,CAAC,CAAC;SAAA,CAAC,CAAC;AAC7G,YAAI,WAAW,GAAG,gBAAgB,IAAI,gBAAgB,CAAC,eAAe,CAAC,CAAC;AACxE,sBAAc,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;AAClH,YAAI,WAAW,EAAE;AACf,cAAI,WAAW,CAAC,IAAI,KAAK,SAAS,EAAE;AAClC,0BAAc,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;AAClH,0BAAc,CAAC,eAAe,CAAC,GAAG,cAAc,CAAC;WAClD,MAAM,IAAI,WAAW,CAAC,IAAI,KAAK,UAAU,EAAE;AAC1C,0BAAc,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;AAClH,gBAAI,cAAc,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE;AAClE,4BAAc,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;aACtD;WACF,MAAM,IAAI,WAAW,CAAC,IAAI,KAAK,MAAM,EAAE;AACtC,kBAAM,IAAI,KAAK,wCAAsC,eAAe,4BAAuB,eAAe,QAAK,CAAC;WACjH;SACF,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE;AAC9B,gBAAM,IAAI,KAAK,wCAAsC,eAAe,uBAAkB,WAAW,CAAC,OAAO,QAAK,CAAC;SAChH;OACF;KACF;;;WAEM,iBAAC,QAAQ,EAAE;;;AAChB,cAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,UAAA,SAAS,EAAI;AACxC,YAAI,iBAAiB,GAAG,QAAK,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;AACjE,gBAAQ,QAAK,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI;AAC3D,eAAK,SAAS;AAAE;AACd,+BAAiB,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;AAC9C,oBAAM;aACP;AAAA,AACD,eAAK,UAAU;AAAE;AACf,kBAAI,KAAK,GAAG,iBAAiB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACrE,kBAAI,KAAK,KAAK,CAAC,CAAC,EAAE;AAChB,iCAAiB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;eACzD;AACD,oBAAM;aACP;AAAA,AACD;AAAS;AACP,oBAAM;aACP;AAAA,SACF;;AAED,yBAAiB,CAAC,WAAW,GAAG,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,UAAA,CAAC,EAAI;AACxE,iBAAO,EAAE,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,CAAA,AAAC,CAAC;SAC5D,CAAC,CAAC;OACJ,CAAC,CAAC;AACH,aAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;KAC/C;;;WAEyB,oCAAC,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE;AACvF,UAAI,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACxD,UAAI,eAAe,GAAG,WAAW,CAAC,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC;AACjE,UAAI,WAAW,GAAG,gBAAgB,IAAI,gBAAgB,CAAC,eAAe,CAAC,CAAC;AACxE,oBAAc,CAAC,WAAW,GAAG,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC,UAAA,CAAC,EAAI;AAClE,eAAO,EAAE,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC,SAAS,KAAK,eAAe,CAAA,AAAC,CAAC;OAC3G,CAAC,CAAC;AACH,UAAI,WAAW,EAAE;AACf,YAAI,WAAW,CAAC,IAAI,KAAK,SAAS,EAAE;AAClC,wBAAc,CAAC,WAAW,GAAG,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC,UAAA,CAAC,EAAI;AAClE,mBAAO,EAAE,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC,SAAS,KAAK,eAAe,CAAA,AAAC,CAAC;WAC3G,CAAC,CAAC;AACH,wBAAc,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;SACxC,MAAM,IAAI,WAAW,CAAC,IAAI,KAAK,UAAU,EAAE;AAC1C,wBAAc,CAAC,WAAW,GAAG,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC,UAAA,CAAC,EAAI;AAClE,mBAAO,EAAE,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC,SAAS,KAAK,eAAe,CAAA,AAAC,CAAC;WAC3G,CAAC,CAAC;AACH,wBAAc,CAAC,eAAe,CAAC,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,UAAA,CAAC,EAAI;AAC5E,mBAAO,CAAC,KAAK,cAAc,CAAC;WAC7B,CAAC,CAAC;SACJ,MAAM,IAAI,WAAW,CAAC,IAAI,KAAK,MAAM,EAAE;AACtC,gBAAM,IAAI,KAAK,wCAAsC,eAAe,4BAAuB,eAAe,QAAK,CAAC;SACjH;OACF,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE;AAC9B,cAAM,IAAI,KAAK,wCAAsC,eAAe,uBAAkB,WAAW,CAAC,OAAO,QAAK,CAAC;OAChH;KACF;;;SAtkBkB,KAAK;;;qBAAL,KAAK;;AA0kB1B,KAAK,CAAC,WAAW,2BAAc,CAAC", + "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