From c7e4a36776ef01d0ec27e905d066dfca1b480866 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Wed, 22 May 2024 12:08:06 -0700 Subject: [PATCH 1/3] Add getValues method for fetching array of docs from collection --- src/Model/collections.ts | 13 +++++++++++++ test/Model/collections.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 test/Model/collections.js diff --git a/src/Model/collections.ts b/src/Model/collections.ts index 1f9531b9..facdbdae 100644 --- a/src/Model/collections.ts +++ b/src/Model/collections.ts @@ -2,6 +2,7 @@ import { Doc } from './Doc'; import { Model, RootModel } from './Model'; import { JSONObject } from 'sharedb/lib/sharedb'; import type { Path, ReadonlyDeep, ShallowCopiedValue, Segments } from '../types'; + var LocalDoc = require('./LocalDoc'); var util = require('../util'); @@ -78,6 +79,14 @@ declare module './Model' { _get(segments: Segments): any; _getCopy(segments: Segments): any; _getDeepCopy(segments: Segments): any; + + /** + * Gets array of values of collection at this models path or relative subpath + * + * If no values exist at subpath, an empty array is returned + * @param subpath + */ + getValues(subpath?: Path): ReadonlyDeep[]; } } @@ -124,6 +133,10 @@ Model.prototype._getDeepCopy = function(segments) { return util.deepCopy(value); }; +Model.prototype.getValues = function(subpath?: Path) { + return this.filter(subpath, null).get(); +} + Model.prototype.getOrCreateCollection = function(name) { var collection = this.root.collections[name]; if (collection) return collection; diff --git a/test/Model/collections.js b/test/Model/collections.js new file mode 100644 index 00000000..62299081 --- /dev/null +++ b/test/Model/collections.js @@ -0,0 +1,30 @@ +const {expect} = require('../util'); +const {RootModel} = require('../../lib'); + +describe('collections', () => { + describe('getValues', () => { + it('returns array of values from collection', () => { + const model = new RootModel(); + model.add('_test_docs', {name: 'foo'}); + model.add('_test_docs', {name: 'bar'}); + + const values = model.getValues('_test_docs'); + + expect(values).to.be.instanceOf(Array); + expect(values).to.have.lengthOf(2); + + ['foo', 'bar'].forEach((value, index) => { + expect(values[index]).to.have.property('name', value); + }); + }); + + it('return empty array when no values at subpath', () => { + const model = new RootModel(); + + const values = model.getValues('_test_docs'); + + expect(values).to.be.instanceOf(Array); + expect(values).to.have.lengthOf(0); + }); + }); +}); From f9361c1087b62f8bbb510a602ef609ede4fc5c1a Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Thu, 23 May 2024 12:32:42 -0700 Subject: [PATCH 2/3] Update getValues logic; add test case for error on non-object value --- src/Model/collections.ts | 11 +++++++++-- test/Model/collections.js | 13 ++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Model/collections.ts b/src/Model/collections.ts index facdbdae..874000c4 100644 --- a/src/Model/collections.ts +++ b/src/Model/collections.ts @@ -81,7 +81,7 @@ declare module './Model' { _getDeepCopy(segments: Segments): any; /** - * Gets array of values of collection at this models path or relative subpath + * Gets array of values of collection at this model's path or relative subpath * * If no values exist at subpath, an empty array is returned * @param subpath @@ -134,7 +134,14 @@ Model.prototype._getDeepCopy = function(segments) { }; Model.prototype.getValues = function(subpath?: Path) { - return this.filter(subpath, null).get(); + const value = this.get(subpath); + if (value == null) { + return []; + } + if (typeof value !== 'object') { + throw new Error(`Found non-object type for getValues('${this.path(subpath)}')`); + } + return Object.values(value) as ReadonlyDeep[]; } Model.prototype.getOrCreateCollection = function(name) { diff --git a/test/Model/collections.js b/test/Model/collections.js index 62299081..a51a68f2 100644 --- a/test/Model/collections.js +++ b/test/Model/collections.js @@ -7,12 +7,9 @@ describe('collections', () => { const model = new RootModel(); model.add('_test_docs', {name: 'foo'}); model.add('_test_docs', {name: 'bar'}); - const values = model.getValues('_test_docs'); - expect(values).to.be.instanceOf(Array); expect(values).to.have.lengthOf(2); - ['foo', 'bar'].forEach((value, index) => { expect(values[index]).to.have.property('name', value); }); @@ -20,11 +17,17 @@ describe('collections', () => { it('return empty array when no values at subpath', () => { const model = new RootModel(); - const values = model.getValues('_test_docs'); - expect(values).to.be.instanceOf(Array); expect(values).to.have.lengthOf(0); }); + + it('throws error if non-object result at path', () => { + const model = new RootModel(); + const id = model.add('_colors', {rgb: 3}); + expect( + () => model.getValues(`_colors.${id}.rgb`), + ).to.throw(`Found non-object type for getValues('_colors.${id}.rgb')`); + }); }); }); From 519ee8012bd7362cc238d97766a9075610c68b16 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Thu, 23 May 2024 13:17:28 -0700 Subject: [PATCH 3/3] Lint fix --- test/Model/collections.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Model/collections.js b/test/Model/collections.js index a51a68f2..1e533706 100644 --- a/test/Model/collections.js +++ b/test/Model/collections.js @@ -26,7 +26,7 @@ describe('collections', () => { const model = new RootModel(); const id = model.add('_colors', {rgb: 3}); expect( - () => model.getValues(`_colors.${id}.rgb`), + () => model.getValues(`_colors.${id}.rgb`) ).to.throw(`Found non-object type for getValues('_colors.${id}.rgb')`); }); });