diff --git a/dist/mobx-async-store.cjs.js b/dist/mobx-async-store.cjs.js index 8295e541..d7dc513b 100644 --- a/dist/mobx-async-store.cjs.js +++ b/dist/mobx-async-store.cjs.js @@ -271,8 +271,8 @@ function ObjectPromiseProxy(promise, target) { // uuid id as its only reference to the newly persisted record. // TODO: Figure out a way to update associated records to use the // newly persisted id. - target.store.data[target.type].records[tmpId] = target; - target.store.data[target.type].records[target.id] = target; + target.store.data[target.type].records.set(String(tmpId), target); + target.store.data[target.type].records.set(String(target.id), target); }); return _context.abrupt("return", target); @@ -1506,8 +1506,8 @@ function () { value: function reset(type) { if (type) { this.data[type] = { - records: {}, - cache: {} + records: mobx.observable.map({}), + cache: mobx.observable.map({}) }; } else { this.initializeObservableDataProperty(); @@ -1578,8 +1578,8 @@ function () { types.forEach(function (modelKlass) { _this2.data[modelKlass.type] = { - records: {}, - cache: {} + records: mobx.observable.map({}), + cache: mobx.observable.map({}) }; }); } @@ -1666,7 +1666,7 @@ function () { throw new Error("Could not find a collection for type '".concat(type, "'")); } - var record = this.getType(type).records[id]; + var record = this.getType(type).records.get(String(id)); if (!record || record === 'undefined') return; return record; } @@ -1681,7 +1681,7 @@ function () { }, { key: "getRecords", value: function getRecords(type) { - var records = Object.values(this.getType(type).records).filter(function (value) { + var records = Array.from(this.getType(type).records.values()).filter(function (value) { return value && value !== 'undefined'; }); // NOTE: Handles a scenario where the store keeps around a reference // to a newly persisted record by its temp uuid. This is required @@ -1739,7 +1739,7 @@ function () { }, { key: "getCachedIds", value: function getCachedIds(type, url) { - var ids = this.getType(type).cache[url]; + var ids = this.getType(type).cache.get(url); if (!ids) return []; var idsSet = new Set(mobx.toJS(ids)); return Array.from(idsSet); @@ -1747,7 +1747,7 @@ function () { /** * Gets records from store based on cached query * - * @method getCachedIds + * @method getCachedId * @param {String} type * @param {String} url * @return {Array} array of ids @@ -1756,7 +1756,7 @@ function () { }, { key: "getCachedId", value: function getCachedId(type, id) { - return this.getType(type).cache[id]; + return this.getType(type).cache.get(String(id)); } /** * Get multiple records by id @@ -1824,8 +1824,6 @@ function () { }, { key: "createOrUpdateModel", value: function createOrUpdateModel(dataObject) { - var _this4 = this; - var _dataObject$attribute = dataObject.attributes, attributes = _dataObject$attribute === void 0 ? {} : _dataObject$attribute, id = dataObject.id, @@ -1838,7 +1836,6 @@ function () { // Update existing object attributes Object.keys(attributes).forEach(function (key) { mobx.set(record, key, attributes[key]); - mobx.set(_this4.data[type].records, id, record); }); // If relationships are present, update relationships if (relationships) { @@ -1847,7 +1844,6 @@ function () { if (!relationships[key].meta) { // defensive against existingRecord.relationships being undefined mobx.set(record, 'relationships', _objectSpread$2({}, record.relationships, _defineProperty({}, key, relationships[key]))); - mobx.set(_this4.data[type].records, id, record); } }); } @@ -1860,9 +1856,9 @@ function () { attributes: attributes, relationships: relationships }); - this.data[type].records[record.id] = record; } + this.data[type].records.set(String(record.id), record); return record; } /** @@ -1875,15 +1871,15 @@ function () { }, { key: "createModelsFromData", value: function createModelsFromData(data) { - var _this5 = this; + var _this4 = this; return mobx.transaction(function () { return data.map(function (dataObject) { // Only build objects for which we have a type defined. // And ignore silently anything else included in the JSON response. // TODO: Put some console message in development mode - if (_this5.getType(dataObject.type)) { - return _this5.createOrUpdateModel(dataObject); + if (_this4.getType(dataObject.type)) { + return _this4.createOrUpdateModel(dataObject); } }); }); @@ -1950,7 +1946,7 @@ function () { var _fetchAll = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee(type, queryParams) { - var _this6 = this; + var _this5 = this; var store, url, response, json; return _regeneratorRuntime.wrap(function _callee$(_context) { @@ -1972,7 +1968,7 @@ function () { break; } - this.data[type].cache[url] = []; + this.data[type].cache.set(url, []); _context.next = 9; return response.json(); @@ -1990,15 +1986,18 @@ function () { attributes = _dataObject$attribute2 === void 0 ? {} : _dataObject$attribute2, _dataObject$relations2 = dataObject.relationships, relationships = _dataObject$relations2 === void 0 ? {} : _dataObject$relations2; - var ModelKlass = _this6.modelTypeIndex[type]; + var ModelKlass = _this5.modelTypeIndex[type]; var record = new ModelKlass(_objectSpread$2({ store: store, relationships: relationships }, attributes)); - _this6.data[type].cache[url].push(id); + var cachedIds = _this5.data[type].cache.get(url); + + _this5.data[type].cache.set(url, [].concat(_toConsumableArray(cachedIds), [id])); + + _this5.data[type].records.set(String(id), record); - _this6.data[type].records[id] = record; return record; }); })); @@ -2051,7 +2050,7 @@ function () { response = _context2.sent; if (!(response.status === 200)) { - _context2.next = 16; + _context2.next = 15; break; } @@ -2067,14 +2066,13 @@ function () { } record = this.createOrUpdateModel(data); - this.data[type].cache[url] = []; - this.data[type].cache[url].push(record.id); + this.data[type].cache.set(url, [record.id]); return _context2.abrupt("return", record); - case 16: + case 15: return _context2.abrupt("return", null); - case 17: + case 16: case "end": return _context2.stop(); } @@ -2103,17 +2101,18 @@ function () { enumerable: true, writable: true, initializer: function initializer() { - var _this7 = this; + var _this6 = this; return function (type, attributes) { var id = dbOrNewId(attributes); - var model = _this7.createModel(type, id, { + var model = _this6.createModel(type, id, { attributes: attributes }); // Add the model to the type records index - _this7.data[type].records[id] = model; + _this6.data[type].records.set(String(id), model); + return model; }; } @@ -2122,18 +2121,10 @@ function () { enumerable: true, writable: true, initializer: function initializer() { - var _this8 = this; + var _this7 = this; return function (type, id) { - var records = _this8.getRecords(type); - - _this8.data[type].records = records.reduce(function (hash, record) { - if (String(record.id) !== String(id)) { - hash[record.id] = record; - } - - return hash; - }, {}); + _this7.data[type].records.delete(String(id)); }; } })), _class$1); diff --git a/dist/mobx-async-store.esm.js b/dist/mobx-async-store.esm.js index 47059427..1daa8b33 100644 --- a/dist/mobx-async-store.esm.js +++ b/dist/mobx-async-store.esm.js @@ -265,8 +265,8 @@ function ObjectPromiseProxy(promise, target) { // uuid id as its only reference to the newly persisted record. // TODO: Figure out a way to update associated records to use the // newly persisted id. - target.store.data[target.type].records[tmpId] = target; - target.store.data[target.type].records[target.id] = target; + target.store.data[target.type].records.set(String(tmpId), target); + target.store.data[target.type].records.set(String(target.id), target); }); return _context.abrupt("return", target); @@ -1500,8 +1500,8 @@ function () { value: function reset(type) { if (type) { this.data[type] = { - records: {}, - cache: {} + records: observable.map({}), + cache: observable.map({}) }; } else { this.initializeObservableDataProperty(); @@ -1572,8 +1572,8 @@ function () { types.forEach(function (modelKlass) { _this2.data[modelKlass.type] = { - records: {}, - cache: {} + records: observable.map({}), + cache: observable.map({}) }; }); } @@ -1660,7 +1660,7 @@ function () { throw new Error("Could not find a collection for type '".concat(type, "'")); } - var record = this.getType(type).records[id]; + var record = this.getType(type).records.get(String(id)); if (!record || record === 'undefined') return; return record; } @@ -1675,7 +1675,7 @@ function () { }, { key: "getRecords", value: function getRecords(type) { - var records = Object.values(this.getType(type).records).filter(function (value) { + var records = Array.from(this.getType(type).records.values()).filter(function (value) { return value && value !== 'undefined'; }); // NOTE: Handles a scenario where the store keeps around a reference // to a newly persisted record by its temp uuid. This is required @@ -1733,7 +1733,7 @@ function () { }, { key: "getCachedIds", value: function getCachedIds(type, url) { - var ids = this.getType(type).cache[url]; + var ids = this.getType(type).cache.get(url); if (!ids) return []; var idsSet = new Set(toJS(ids)); return Array.from(idsSet); @@ -1741,7 +1741,7 @@ function () { /** * Gets records from store based on cached query * - * @method getCachedIds + * @method getCachedId * @param {String} type * @param {String} url * @return {Array} array of ids @@ -1750,7 +1750,7 @@ function () { }, { key: "getCachedId", value: function getCachedId(type, id) { - return this.getType(type).cache[id]; + return this.getType(type).cache.get(String(id)); } /** * Get multiple records by id @@ -1818,8 +1818,6 @@ function () { }, { key: "createOrUpdateModel", value: function createOrUpdateModel(dataObject) { - var _this4 = this; - var _dataObject$attribute = dataObject.attributes, attributes = _dataObject$attribute === void 0 ? {} : _dataObject$attribute, id = dataObject.id, @@ -1832,7 +1830,6 @@ function () { // Update existing object attributes Object.keys(attributes).forEach(function (key) { set(record, key, attributes[key]); - set(_this4.data[type].records, id, record); }); // If relationships are present, update relationships if (relationships) { @@ -1841,7 +1838,6 @@ function () { if (!relationships[key].meta) { // defensive against existingRecord.relationships being undefined set(record, 'relationships', _objectSpread$2({}, record.relationships, _defineProperty({}, key, relationships[key]))); - set(_this4.data[type].records, id, record); } }); } @@ -1854,9 +1850,9 @@ function () { attributes: attributes, relationships: relationships }); - this.data[type].records[record.id] = record; } + this.data[type].records.set(String(record.id), record); return record; } /** @@ -1869,15 +1865,15 @@ function () { }, { key: "createModelsFromData", value: function createModelsFromData(data) { - var _this5 = this; + var _this4 = this; return transaction(function () { return data.map(function (dataObject) { // Only build objects for which we have a type defined. // And ignore silently anything else included in the JSON response. // TODO: Put some console message in development mode - if (_this5.getType(dataObject.type)) { - return _this5.createOrUpdateModel(dataObject); + if (_this4.getType(dataObject.type)) { + return _this4.createOrUpdateModel(dataObject); } }); }); @@ -1944,7 +1940,7 @@ function () { var _fetchAll = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee(type, queryParams) { - var _this6 = this; + var _this5 = this; var store, url, response, json; return _regeneratorRuntime.wrap(function _callee$(_context) { @@ -1966,7 +1962,7 @@ function () { break; } - this.data[type].cache[url] = []; + this.data[type].cache.set(url, []); _context.next = 9; return response.json(); @@ -1984,15 +1980,18 @@ function () { attributes = _dataObject$attribute2 === void 0 ? {} : _dataObject$attribute2, _dataObject$relations2 = dataObject.relationships, relationships = _dataObject$relations2 === void 0 ? {} : _dataObject$relations2; - var ModelKlass = _this6.modelTypeIndex[type]; + var ModelKlass = _this5.modelTypeIndex[type]; var record = new ModelKlass(_objectSpread$2({ store: store, relationships: relationships }, attributes)); - _this6.data[type].cache[url].push(id); + var cachedIds = _this5.data[type].cache.get(url); + + _this5.data[type].cache.set(url, [].concat(_toConsumableArray(cachedIds), [id])); + + _this5.data[type].records.set(String(id), record); - _this6.data[type].records[id] = record; return record; }); })); @@ -2045,7 +2044,7 @@ function () { response = _context2.sent; if (!(response.status === 200)) { - _context2.next = 16; + _context2.next = 15; break; } @@ -2061,14 +2060,13 @@ function () { } record = this.createOrUpdateModel(data); - this.data[type].cache[url] = []; - this.data[type].cache[url].push(record.id); + this.data[type].cache.set(url, [record.id]); return _context2.abrupt("return", record); - case 16: + case 15: return _context2.abrupt("return", null); - case 17: + case 16: case "end": return _context2.stop(); } @@ -2097,17 +2095,18 @@ function () { enumerable: true, writable: true, initializer: function initializer() { - var _this7 = this; + var _this6 = this; return function (type, attributes) { var id = dbOrNewId(attributes); - var model = _this7.createModel(type, id, { + var model = _this6.createModel(type, id, { attributes: attributes }); // Add the model to the type records index - _this7.data[type].records[id] = model; + _this6.data[type].records.set(String(id), model); + return model; }; } @@ -2116,18 +2115,10 @@ function () { enumerable: true, writable: true, initializer: function initializer() { - var _this8 = this; + var _this7 = this; return function (type, id) { - var records = _this8.getRecords(type); - - _this8.data[type].records = records.reduce(function (hash, record) { - if (String(record.id) !== String(id)) { - hash[record.id] = record; - } - - return hash; - }, {}); + _this7.data[type].records.delete(String(id)); }; } })), _class$1); diff --git a/package.json b/package.json index 4a60d965..60e11cea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@artemisag/mobx-async-store", - "version": "1.0.24", + "version": "1.0.25", "module": "dist/mobx-async-store.esm.js", "browser": "dist/mobx-async-store.cjs.js", "main": "dist/mobx-async-store.cjs.js", diff --git a/spec/Model.spec.js b/spec/Model.spec.js index e44cefd3..b14ff6b6 100644 --- a/spec/Model.spec.js +++ b/spec/Model.spec.js @@ -279,10 +279,7 @@ describe('Model', () => { }) it('builds relatedToMany relationship with existing models', async () => { - store.add('notes', { - id: 1, - description: 'Example description' - }) + store.add('notes', { id: 1, description: 'Example description' }) fetch.mockResponse(exampleRelatedToManyResponse) const todo = await store.findOne('organizations', 1) diff --git a/spec/Store.spec.js b/spec/Store.spec.js index e56fa9a7..02fe20c0 100644 --- a/spec/Store.spec.js +++ b/spec/Store.spec.js @@ -66,7 +66,7 @@ const mockTodoData = { id: '1', type: 'todos', attributes: { - id: 1, + id: '1', title: 'Do taxes' } } @@ -427,10 +427,11 @@ describe('Store', () => { const todoData = { attributes: { title: 'hello!' }, relationships: { - category: { data: { id: '5', type: 'categories' } } + category: { data: { id: category.id, type: 'categories' } } } } const todo = store.createModel('todos', 1, todoData) + expect(todo.id).toEqual(1) expect(todo.category.id).toEqual(category.id) expect(todo.category.name).toEqual(category.name) }) @@ -440,7 +441,7 @@ describe('Store', () => { const todoData = { attributes: { title: 'hello!' }, relationships: { - tags: { data: [{ id: '3', type: 'tags' }] } + tags: { data: [{ id: tag.id, type: 'tags' }] } } } const todo = store.createModel('todos', 1, todoData) @@ -454,7 +455,7 @@ describe('Store', () => { const todoData = { attributes: { title: 'hello!' }, relationships: { - note: { data: { id: '17', type: 'notes' } } + note: { data: { id: note.id, type: 'notes' } } } } const todo = store.createModel('todos', 1, todoData) @@ -467,7 +468,7 @@ describe('Store', () => { const todoData = { attributes: { title: 'hello!' }, relationships: { - notes: { data: [{ id: '3', type: 'notes' }] } + notes: { data: [{ id: note.id, type: 'notes' }] } } } const todo = store.createModel('todos', 1, todoData) diff --git a/src/ObjectPromiseProxy.js b/src/ObjectPromiseProxy.js index bc2b0ba9..27c17889 100644 --- a/src/ObjectPromiseProxy.js +++ b/src/ObjectPromiseProxy.js @@ -39,8 +39,8 @@ function ObjectPromiseProxy (promise, target) { // uuid id as its only reference to the newly persisted record. // TODO: Figure out a way to update associated records to use the // newly persisted id. - target.store.data[target.type].records[tmpId] = target - target.store.data[target.type].records[target.id] = target + target.store.data[target.type].records.set(String(tmpId), target) + target.store.data[target.type].records.set(String(target.id), target) }) return target diff --git a/src/Store.js b/src/Store.js index f1f1ded2..872560b3 100644 --- a/src/Store.js +++ b/src/Store.js @@ -63,7 +63,7 @@ class Store { const model = this.createModel(type, id, { attributes }) // Add the model to the type records index - this.data[type].records[id] = model + this.data[type].records.set(String(id), model) return model } @@ -89,14 +89,7 @@ class Store { */ @action remove = (type, id) => { - const records = this.getRecords(type) - - this.data[type].records = records.reduce((hash, record) => { - if (String(record.id) !== String(id)) { - hash[record.id] = record - } - return hash - }, {}) + this.data[type].records.delete(String(id)) } /** @@ -300,7 +293,10 @@ class Store { */ reset (type) { if (type) { - this.data[type] = { records: {}, cache: {} } + this.data[type] = { + records: observable.map({}), + cache: observable.map({}) + } } else { this.initializeObservableDataProperty() } @@ -359,7 +355,10 @@ class Store { // NOTE: Is there a performance cost to setting // each property individually? types.forEach(modelKlass => { - this.data[modelKlass.type] = { records: {}, cache: {} } + this.data[modelKlass.type] = { + records: observable.map({}), + cache: observable.map({}) + } }) } @@ -420,7 +419,7 @@ class Store { throw new Error(`Could not find a collection for type '${type}'`) } - const record = this.getType(type).records[id] + const record = this.getType(type).records.get(String(id)) if (!record || record === 'undefined') return @@ -435,8 +434,8 @@ class Store { * @return {Array} array of objects */ getRecords (type) { - const records = Object.values(this.getType(type).records) - .filter(value => value && value !== 'undefined') + const records = Array.from(this.getType(type).records.values()) + .filter(value => value && value !== 'undefined') // NOTE: Handles a scenario where the store keeps around a reference // to a newly persisted record by its temp uuid. This is required @@ -488,7 +487,7 @@ class Store { * @return {Array} array of ids */ getCachedIds (type, url) { - const ids = this.getType(type).cache[url] + const ids = this.getType(type).cache.get(url) if (!ids) return [] const idsSet = new Set(toJS(ids)) return Array.from(idsSet) @@ -497,13 +496,13 @@ class Store { /** * Gets records from store based on cached query * - * @method getCachedIds + * @method getCachedId * @param {String} type * @param {String} url * @return {Array} array of ids */ getCachedId (type, id) { - return this.getType(type).cache[id] + return this.getType(type).cache.get(String(id)) } /** @@ -564,7 +563,6 @@ class Store { // Update existing object attributes Object.keys(attributes).forEach(key => { set(record, key, attributes[key]) - set(this.data[type].records, id, record) }) // If relationships are present, update relationships @@ -574,17 +572,15 @@ class Store { if (!relationships[key].meta) { // defensive against existingRecord.relationships being undefined set(record, 'relationships', { ...record.relationships, [key]: relationships[key] }) - set(this.data[type].records, id, record) } }) } - record._takeSnapshot({ persisted: true }) } else { record = this.createModel(type, id, { attributes, relationships }) - this.data[type].records[record.id] = record } + this.data[type].records.set(String(record.id), record) return record } @@ -653,8 +649,9 @@ class Store { const response = await this.fetch(url, { method: 'GET' }) if (response.status === 200) { - this.data[type].cache[url] = [] + this.data[type].cache.set(url, []) const json = await response.json() + if (json.included) { this.createModelsFromData(json.included) } @@ -663,9 +660,9 @@ class Store { const { id, attributes = {}, relationships = {} } = dataObject const ModelKlass = this.modelTypeIndex[type] const record = new ModelKlass({ store, relationships, ...attributes }) - this.data[type].cache[url].push(id) - this.data[type].records[id] = record - + const cachedIds = this.data[type].cache.get(url) + this.data[type].cache.set(url, [...cachedIds, id]) + this.data[type].records.set(String(id), record) return record })) } else { @@ -689,7 +686,6 @@ class Store { // Handle response if (response.status === 200) { const json = await response.json() - const { data, included } = json if (included) { @@ -698,8 +694,7 @@ class Store { const record = this.createOrUpdateModel(data) - this.data[type].cache[url] = [] - this.data[type].cache[url].push(record.id) + this.data[type].cache.set(url, [record.id]) return record } else {