From b5c3f902f162023654b11c70955d981fe395bc44 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Fri, 24 Feb 2023 18:25:26 +0530 Subject: [PATCH 01/13] rxdata with lokijs --- package-lock.json | 44 +++++++++++--------------------- package.json | 5 ++-- src/__tests__/collection.spec.ts | 28 +++++++++++++++++--- src/__tests__/database.spec.ts | 15 ++++++++--- src/__tests__/utils.ts | 22 +++++++++++++++- src/collection.ts | 34 ++++++++++++------------ src/database.ts | 6 ++--- 7 files changed, 95 insertions(+), 59 deletions(-) diff --git a/package-lock.json b/package-lock.json index e46620d..7f5ec79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -209,6 +209,11 @@ "integrity": "sha512-0VU8WsYEOYmoxVtUuafB66/+9G8gMdGAC3dhCE/CMpjXgNIz9fwC6g41kRlNxFgpQI/uX/aWNLArNg7KmeFYvw==", "dev": true }, + "@types/lokijs": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@types/lokijs/-/lokijs-1.5.7.tgz", + "integrity": "sha512-WEFQLgO3u2Wa7yFybqkTZYumqF1GcHvUwx8Tv2SUHy2qpnIainMMoLmEUGdjhPNp/v5pyC9e91fSMC3mkxBIDw==" + }, "@webassemblyjs/ast": { "version": "1.7.11", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", @@ -2526,11 +2531,6 @@ "minimatch": "^3.0.4" } }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -3053,14 +3053,6 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, - "lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", - "requires": { - "immediate": "~3.0.5" - } - }, "loader-runner": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", @@ -3078,22 +3070,6 @@ "json5": "^0.5.0" } }, - "localforage": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.7.3.tgz", - "integrity": "sha512-1TulyYfc4udS7ECSBT2vwJksWbkwwTX8BzeUIiq8Y07Riy7bDAAnxDaPU/tWyOVmQAcWJIEIFP9lPfBGqVoPgQ==", - "requires": { - "lie": "3.1.1" - } - }, - "localforage-setitems": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/localforage-setitems/-/localforage-setitems-1.4.0.tgz", - "integrity": "sha1-NrhZDVB9+1yAQDPih+zljYiZbV8=", - "requires": { - "localforage": ">=1.4.0" - } - }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -3126,6 +3102,11 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, + "lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -3206,6 +3187,11 @@ "object.assign": "^4.1.0" } }, + "lokijs": { + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/lokijs/-/lokijs-1.5.12.tgz", + "integrity": "sha512-Q5ALD6JiS6xAUWCwX3taQmgwxyveCtIIuL08+ml0nHwT3k0S/GIFJN+Hd38b1qYIMaE5X++iqsqWVksz7SYW+Q==" + }, "loose-envify": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", diff --git a/package.json b/package.json index 23b65a0..6e482ac 100644 --- a/package.json +++ b/package.json @@ -39,10 +39,11 @@ "dependencies": { "@creately/lschannel": "^2.0.3", "@creately/mungo": "^1.2.1", - "localforage": "^1.7.3", - "localforage-setitems": "^1.4.0", + "@types/lokijs": "^1.5.7", "lodash.clonedeep": "^4.5.0", "lodash.isequal": "^4.5.0", + "lodash.omit": "^4.5.0", + "lokijs": "^1.5.12", "mingo": "^2.2.6", "rxjs": "^6.0.0" } diff --git a/src/__tests__/collection.spec.ts b/src/__tests__/collection.spec.ts index 08ed8a8..86adbc1 100644 --- a/src/__tests__/collection.spec.ts +++ b/src/__tests__/collection.spec.ts @@ -14,6 +14,13 @@ describe('Collection', () => { return { name, col }; } + let prepareOut = (val: any) => { + val.forEach((d: any) => { + delete d.meta; + delete d.$loki; + }); + }; + afterEach(() => { try { database.close(); @@ -98,6 +105,7 @@ describe('Collection', () => { const promise = watchN(col, 1); await col.insert(TEST_DOCS); const out = await promise; + prepareOut(out[0].docs); expect(out).toEqual([{ id: (jasmine.any(Number) as any) as number, type: 'insert', docs: [...TEST_DOCS] }]); done(); }); @@ -107,6 +115,7 @@ describe('Collection', () => { const watchPromise = watchN(col, 1, { z: 3 }); await col.insert(TEST_DOCS); const out = await watchPromise; + prepareOut(out[0].docs); expect(out).toEqual([ { id: (jasmine.any(Number) as any) as number, type: 'insert', docs: TEST_DOCS.filter(doc => doc.z === 3) }, ]); @@ -208,7 +217,8 @@ describe('Collection', () => { done(); }); - it('should not re-emit the same result if documents in the result did not change', async done => { + // FIXME - remove x and find why this fails + xit('should not re-emit the same result if documents in the result did not change', async done => { const { col } = await prepare(); await col.insert(TEST_DOCS); const promise = findN(col, 2, { z: 3 }); @@ -217,7 +227,12 @@ describe('Collection', () => { const out = await promise; expect(out).toEqual([ [{ id: 'd113', x: 1, y: 1, z: 3 }, { id: 'd123', x: 1, y: 2, z: 3 }], - [{ id: 'd113', x: 1, y: 1, z: 3, a: 2 }, { id: 'd123', x: 1, y: 2, z: 3, a: 2 }], + [ + { id: 'd113', x: 1, y: 1, z: 3, a: 2 }, + { id: 'd123', x: 1, y: 2, z: 3, a: 2 }, + { id: 'd113', x: 1, y: 1, z: 3, a: 2 }, + { id: 'd123', x: 1, y: 2, z: 3, a: 2 }, + ], ]); done(); }); @@ -281,7 +296,8 @@ describe('Collection', () => { done(); }); - it('should not re-emit the same result if documents in the result did not change', async done => { + // FIXME - remove x and find why this fails + xit('should not re-emit the same result if documents in the result did not change', async done => { const { col } = await prepare(); await col.insert(TEST_DOCS); const promise = find1N(col, 2, { z: 3 }); @@ -315,6 +331,7 @@ describe('Collection', () => { const { col } = await prepare(); await Promise.all(TEST_DOCS.map(doc => col.insert(doc))); const out = await findN(col, 1, {}); + prepareOut(out); expect(out).toEqual([[...TEST_DOCS]]); done(); }); @@ -323,6 +340,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, {}); + prepareOut(out); expect(out).toEqual([[...TEST_DOCS]]); done(); }); @@ -332,6 +350,7 @@ describe('Collection', () => { const promise = watchN(col, 1); await col.insert(TEST_DOCS); const out = await promise; + prepareOut(out[0].docs); expect(out).toEqual([{ id: (jasmine.any(Number) as any) as number, type: 'insert', docs: [...TEST_DOCS] }]); done(); }); @@ -352,6 +371,7 @@ describe('Collection', () => { await col.insert(TEST_DOCS); await col.update({ z: 3 }, { $set: { a: 1 } }); const out = await findN(col, 1, {}); + prepareOut(out); expect(out).toEqual([ [ { id: 'd111', x: 1, y: 1, z: 1 }, @@ -371,6 +391,7 @@ describe('Collection', () => { await col.insert(TEST_DOCS); await col.update({ z: 3 }, { $set: { 'a.b': 1 } }); const out = await findN(col, 1, {}); + prepareOut(out); expect(out).toEqual([ [ { id: 'd111', x: 1, y: 1, z: 1 }, @@ -393,6 +414,7 @@ describe('Collection', () => { const promise = watchN(col, 1); await col.update({ z: 3 }, { $set: { a: 1 } }); const out = await promise; + prepareOut(out[0].docs); expect(out).toEqual([ { id: (jasmine.any(Number) as any) as number, diff --git a/src/__tests__/database.spec.ts b/src/__tests__/database.spec.ts index 5404617..11aa4be 100644 --- a/src/__tests__/database.spec.ts +++ b/src/__tests__/database.spec.ts @@ -92,10 +92,19 @@ describe('Database', () => { it('should remove all documents in all collections in the database', async done => { const { db } = prepare(); - const c1 = db.collection('test'); + const c1 = db.collection('test1'); await c1.insert([{ id: 'd1' }]); - expect(await findN(c1, 1)).toEqual([[{ id: 'd1' }]]); - await db.drop(); + const out = await findN(c1, 1); + console.log('out', out); + expect(out).toEqual([[{ id: 'd1' }]]); + + try { + const d = await db.drop(); + console.log('out d', d); + } catch (error) { + console.log('error', error); + } + expect(await findN(c1, 1)).toEqual([[]]); done(); }); diff --git a/src/__tests__/utils.ts b/src/__tests__/utils.ts index ad0b2d7..323eb8a 100644 --- a/src/__tests__/utils.ts +++ b/src/__tests__/utils.ts @@ -1,4 +1,4 @@ -import { take, toArray } from 'rxjs/operators'; +import { tap, take, toArray } from 'rxjs/operators'; import { Collection, DocumentChange, IDocument } from '../collection'; export function findN(c: Collection, n: number, ...args: any[]): Promise { @@ -6,6 +6,14 @@ export function findN(c: Collection, n: number, ...args: .find(...args) .pipe( take(n), + tap(v => + v.forEach((doc: any) => { + if (doc) { + delete doc.meta; + delete doc.$loki; + } + }) + ), toArray() ) .toPromise(); @@ -16,6 +24,12 @@ export function find1N(c: Collection, n: number, ...args .findOne(...args) .pipe( take(n), + tap((doc: any) => { + if (doc) { + delete doc.meta; + delete doc.$loki; + } + }), toArray() ) .toPromise(); @@ -26,6 +40,12 @@ export function watchN(c: Collection, n: number, ...args .watch(...args) .pipe( take(n), + tap((doc: any) => { + if (doc) { + delete doc.meta; + delete doc.$loki; + } + }), toArray() ) .toPromise(); diff --git a/src/collection.ts b/src/collection.ts index 28237f5..6736749 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -1,8 +1,5 @@ -/// - import mingo from 'mingo'; -import * as LocalForage from 'localforage'; -import 'localforage-setitems'; +import * as Loki from 'lokijs'; import * as isequal from 'lodash.isequal'; import * as cloneDeep from 'lodash.clonedeep'; import { Observable, Subject, empty, of, defer, from, Subscription } from 'rxjs'; @@ -72,13 +69,14 @@ export type DocumentChange = InsertDocumentChange | RemoveDocumentChange { + public static loki = new Loki('rxdatalokijs'); // allDocs // allDocs emits all documents in the collection when they get modified. protected allDocs: Subject; // storage // storage stores documents in a suitable storage backend. - protected storage: LocalForage; + protected storage: Loki.Collection; // cachedDocs // cachedDocs is an in memory cache of all documents in the database. @@ -107,7 +105,7 @@ export class Collection { // constructor constructor(public name: string) { this.allDocs = new Subject(); - this.storage = LocalForage.createInstance({ name }); + this.storage = Collection.loki.addCollection(name); this.changes = Channel.create(`rxdata.${name}.channel`); this.changesSub = this.changes.pipe(concatMap(change => from(this.apply(change)))).subscribe(); } @@ -178,7 +176,7 @@ export class Collection { // with the id already exists in the collection, it will be replaced. public async insert(docOrDocs: T | T[]): Promise { const docs: T[] = cloneDeep(Array.isArray(docOrDocs) ? docOrDocs : [docOrDocs]); - await this.storage.setItems(docs.map(doc => ({ key: (doc as any).id, value: doc }))); + this.storage.insert(docs); await this.emitAndApply({ id: this.nextChangeId(), type: 'insert', docs: docs }); } @@ -189,8 +187,10 @@ export class Collection { const modifier = cloneDeep(_modifier); const filter = this.createFilter(selector); const docs: T[] = cloneDeep((await this.load()).filter(doc => filter(doc))); - docs.forEach(doc => modify(doc, modifier)); - await this.storage.setItems(docs.map(doc => ({ key: (doc as any).id, value: doc }))); + docs.forEach(doc => { + modify(doc, modifier); + this.storage.update(doc); + }); await this.emitAndApply({ id: this.nextChangeId(), type: 'update', docs: docs, modifier: modifier }); } @@ -200,10 +200,15 @@ export class Collection { public async remove(selector: Selector): Promise { const filter = this.createFilter(selector); const docs = (await this.load()).filter(doc => filter(doc)); - await Promise.all(docs.map(doc => this.storage.removeItem((doc as any).id))); + docs.map(doc => this.storage.remove(doc)); await this.emitAndApply({ id: this.nextChangeId(), type: 'remove', docs: docs }); } + public async dropCollection() { + Collection.loki.removeCollection(this.name); + await this.reload(); + } + // filter // filter returns an array of documents which match the selector and // filter options. The selector, options and all option fields are optional. @@ -254,14 +259,7 @@ export class Collection { // loadAll loads all documents from storage without filtering. // Returns a promise which resolves to an array of documents. protected async loadAll(): Promise { - const docs: T[] = []; - await this.storage.iterate((doc: T) => { - docs.push(doc); - // If a non-undefined value is returned, - // the localforage iterator will stop. - return undefined; - }); - return docs; + return Promise.resolve(this.storage.data); } // refresh diff --git a/src/database.ts b/src/database.ts index 7b34c2c..607207d 100644 --- a/src/database.ts +++ b/src/database.ts @@ -53,10 +53,10 @@ export class Database { // drop clears all data in all collections in the database. // It also closes all active subscriptions in all collections. public async drop(): Promise { - this.collections = new Map(); - const collections = this.collectionsList; this.collectionsList = []; - await Promise.all(collections.map(name => new Collection(name).remove({}))); + this.collections.forEach(async c => await c.dropCollection()); + this.collections = new Map(); + await Promise.resolve(); } // collectionsListKey From 6f31166fbee3a63f42d4088abd7e4665f491b3e9 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Fri, 24 Feb 2023 18:26:06 +0530 Subject: [PATCH 02/13] updated package lock --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e482ac..b2c1a30 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@creately/rxdata", - "version": "5.1.4", + "version": "6.0.0", "description": "", "main": "dist/index.js", "typings": "dist/index.d.ts", From f4bde5d13c858ccdffa7f4c3710b4ccb762a3fa8 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Wed, 15 Mar 2023 19:04:38 +0530 Subject: [PATCH 03/13] Removed rxdata cache and updated unit tests --- package-lock.json | 2 +- package.json | 2 +- src/__tests__/collection.spec.ts | 45 +++++++++++++++++++------------- src/__tests__/database.spec.ts | 17 +++++++++--- src/__tests__/utils.ts | 22 +--------------- src/collection.ts | 39 +++------------------------ 6 files changed, 47 insertions(+), 80 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f5ec79..53a1549 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@creately/rxdata", - "version": "5.1.4", + "version": "6.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b2c1a30..a63106a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@creately/rxdata", - "version": "6.0.0", + "version": "6.0.1", "description": "", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/src/__tests__/collection.spec.ts b/src/__tests__/collection.spec.ts index 86adbc1..4fbcad9 100644 --- a/src/__tests__/collection.spec.ts +++ b/src/__tests__/collection.spec.ts @@ -14,7 +14,7 @@ describe('Collection', () => { return { name, col }; } - let prepareOut = (val: any) => { + const prepareOut = (val: any[]) => { val.forEach((d: any) => { delete d.meta; delete d.$loki; @@ -145,6 +145,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1); + prepareOut(out[0]); expect(out).toEqual([[...TEST_DOCS]]); done(); }); @@ -153,6 +154,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { x: -1 }); + prepareOut(out[0]); expect(out).toEqual([[]]); done(); }); @@ -161,6 +163,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { id: 'd000' }); + prepareOut(out[0]); expect(out).toEqual([[]]); done(); }); @@ -169,6 +172,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { z: 3 }); + prepareOut(out[0]); expect(out).toEqual([TEST_DOCS.filter(doc => doc.z === 3)]); done(); }); @@ -177,6 +181,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { id: 'd111' }); + prepareOut(out[0]); expect(out).toEqual([TEST_DOCS.filter(doc => doc.id === 'd111')]); done(); }); @@ -185,6 +190,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { id: { $in: ['d111', 'd112'] } }); + prepareOut(out[0]); expect(out).toEqual([TEST_DOCS.filter(doc => doc.id === 'd111' || doc.id === 'd112')]); done(); }); @@ -193,6 +199,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { y: 2 }, { sort: { z: -1 } }); + prepareOut(out[0]); expect(out).toEqual([TEST_DOCS.filter(doc => doc.y === 2).reverse()]); done(); }); @@ -201,6 +208,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { y: 2 }, { sort: { z: -1 }, skip: 1 }); + prepareOut(out[0]); expect(out).toEqual([ TEST_DOCS.filter(doc => doc.y === 2) .reverse() @@ -213,26 +221,23 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { y: 2 }, { limit: 2 }); - expect(out).toEqual([TEST_DOCS.filter(doc => doc.y === 2).slice(0, 2)]); + prepareOut(out[0]); + expect( out ).toEqual([TEST_DOCS.filter(doc => doc.y === 2).slice(0, 2)]); done(); }); - // FIXME - remove x and find why this fails - xit('should not re-emit the same result if documents in the result did not change', async done => { + it('should not re-emit the same result if documents in the result did not change', async done => { const { col } = await prepare(); await col.insert(TEST_DOCS); const promise = findN(col, 2, { z: 3 }); await col.update({ z: 2 }, { $set: { a: 1 } }); await col.update({ z: 3 }, { $set: { a: 2 } }); const out = await promise; + prepareOut(out[0]); + prepareOut(out[1]); expect(out).toEqual([ [{ id: 'd113', x: 1, y: 1, z: 3 }, { id: 'd123', x: 1, y: 2, z: 3 }], - [ - { id: 'd113', x: 1, y: 1, z: 3, a: 2 }, - { id: 'd123', x: 1, y: 2, z: 3, a: 2 }, - { id: 'd113', x: 1, y: 1, z: 3, a: 2 }, - { id: 'd123', x: 1, y: 2, z: 3, a: 2 }, - ], + [{ id: 'd113', x: 1, y: 1, z: 3, a: 2 }, { id: 'd123', x: 1, y: 2, z: 3, a: 2 }], ]); done(); }); @@ -284,6 +289,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await find1N(col, 1, { y: 2 }, { sort: { z: -1 } }); + prepareOut(out); expect(out).toEqual([TEST_DOCS.filter(doc => doc.y === 2).reverse()[0]]); done(); }); @@ -292,19 +298,20 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await find1N(col, 1, { y: 2 }, { sort: { z: -1 }, skip: 1 }); + prepareOut(out); expect(out).toEqual([TEST_DOCS.filter(doc => doc.y === 2).reverse()[1]]); done(); }); - // FIXME - remove x and find why this fails - xit('should not re-emit the same result if documents in the result did not change', async done => { + it('should not re-emit the same result if documents in the result did not change', async done => { const { col } = await prepare(); await col.insert(TEST_DOCS); const promise = find1N(col, 2, { z: 3 }); await col.update({ z: 2 }, { $set: { a: 1 } }); await col.update({ z: 3 }, { $set: { a: 2 } }); const out = await promise; - expect(out).toEqual([{ id: 'd113', x: 1, y: 1, z: 3 }, { id: 'd113', x: 1, y: 1, z: 3, a: 2 }]); + prepareOut(out); + expect( out ).toEqual([{ id: 'd113', x: 1, y: 1, z: 3 }, { id: 'd113', x: 1, y: 1, z: 3, a: 2 }]); done(); }); @@ -331,7 +338,7 @@ describe('Collection', () => { const { col } = await prepare(); await Promise.all(TEST_DOCS.map(doc => col.insert(doc))); const out = await findN(col, 1, {}); - prepareOut(out); + prepareOut(out[0]); expect(out).toEqual([[...TEST_DOCS]]); done(); }); @@ -340,7 +347,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, {}); - prepareOut(out); + prepareOut(out[0]); expect(out).toEqual([[...TEST_DOCS]]); done(); }); @@ -371,7 +378,7 @@ describe('Collection', () => { await col.insert(TEST_DOCS); await col.update({ z: 3 }, { $set: { a: 1 } }); const out = await findN(col, 1, {}); - prepareOut(out); + prepareOut(out[0]); expect(out).toEqual([ [ { id: 'd111', x: 1, y: 1, z: 1 }, @@ -391,7 +398,7 @@ describe('Collection', () => { await col.insert(TEST_DOCS); await col.update({ z: 3 }, { $set: { 'a.b': 1 } }); const out = await findN(col, 1, {}); - prepareOut(out); + prepareOut(out[0]); expect(out).toEqual([ [ { id: 'd111', x: 1, y: 1, z: 1 }, @@ -442,7 +449,8 @@ describe('Collection', () => { await col.insert(TEST_DOCS); await col.remove({ z: 3 }); const out = await findN(col, 1, {}); - expect(out).toEqual([ + prepareOut(out[0]); + expect( out ).toEqual([ [ { id: 'd111', x: 1, y: 1, z: 1 }, { id: 'd112', x: 1, y: 1, z: 2 }, @@ -459,6 +467,7 @@ describe('Collection', () => { const promise = watchN(col, 1); await col.remove({ z: 3 }); const out = await promise; + prepareOut( out ); expect(out).toEqual([ { id: (jasmine.any(Number) as any) as number, diff --git a/src/__tests__/database.spec.ts b/src/__tests__/database.spec.ts index 11aa4be..e02636e 100644 --- a/src/__tests__/database.spec.ts +++ b/src/__tests__/database.spec.ts @@ -10,6 +10,13 @@ describe('Database', () => { return { db }; } + const prepareOut = (val: any[]) => { + val.forEach((d: any) => { + delete d.meta; + delete d.$loki; + }); + }; + afterEach(() => { try { database.close(); @@ -77,6 +84,7 @@ describe('Database', () => { const c2 = d2.collection('test'); await c1.insert({ id: 'd1' }); const out = await findN(c2, 1); + prepareOut(out[0]); expect(out).toEqual([[{ id: 'd1' }]]); done(); }); @@ -94,8 +102,8 @@ describe('Database', () => { const { db } = prepare(); const c1 = db.collection('test1'); await c1.insert([{ id: 'd1' }]); - const out = await findN(c1, 1); - console.log('out', out); + let out = await findN(c1, 1); + prepareOut(out[0]); expect(out).toEqual([[{ id: 'd1' }]]); try { @@ -104,8 +112,9 @@ describe('Database', () => { } catch (error) { console.log('error', error); } - - expect(await findN(c1, 1)).toEqual([[]]); + out = await findN(c1, 1); + prepareOut(out[0]); + expect(out).toEqual([[]]); done(); }); }); diff --git a/src/__tests__/utils.ts b/src/__tests__/utils.ts index 323eb8a..ad0b2d7 100644 --- a/src/__tests__/utils.ts +++ b/src/__tests__/utils.ts @@ -1,4 +1,4 @@ -import { tap, take, toArray } from 'rxjs/operators'; +import { take, toArray } from 'rxjs/operators'; import { Collection, DocumentChange, IDocument } from '../collection'; export function findN(c: Collection, n: number, ...args: any[]): Promise { @@ -6,14 +6,6 @@ export function findN(c: Collection, n: number, ...args: .find(...args) .pipe( take(n), - tap(v => - v.forEach((doc: any) => { - if (doc) { - delete doc.meta; - delete doc.$loki; - } - }) - ), toArray() ) .toPromise(); @@ -24,12 +16,6 @@ export function find1N(c: Collection, n: number, ...args .findOne(...args) .pipe( take(n), - tap((doc: any) => { - if (doc) { - delete doc.meta; - delete doc.$loki; - } - }), toArray() ) .toPromise(); @@ -40,12 +26,6 @@ export function watchN(c: Collection, n: number, ...args .watch(...args) .pipe( take(n), - tap((doc: any) => { - if (doc) { - delete doc.meta; - delete doc.$loki; - } - }), toArray() ) .toPromise(); diff --git a/src/collection.ts b/src/collection.ts index 6736749..2895b57 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -78,10 +78,6 @@ export class Collection { // storage stores documents in a suitable storage backend. protected storage: Loki.Collection; - // cachedDocs - // cachedDocs is an in memory cache of all documents in the database. - protected cachedDocs: T[] | null = null; - // channel // channel sends/receives messages between browser tabs. protected changes: Channel>; @@ -236,13 +232,7 @@ export class Collection { // load // load loads all documents from the database to the in-memory cache. protected load(): Promise { - if (this.cachedDocs) { - return Promise.resolve(this.cachedDocs); - } - if (!this.loadPromise) { - this.loadPromise = this.loadAll().then(docs => (this.cachedDocs = docs)); - } - return this.loadPromise.then(() => this.cachedDocs as T[]); + return Promise.resolve(this.storage.data); } // Reload @@ -250,8 +240,7 @@ export class Collection { // the cachedDocs and emit the updated docs. public async reload() { return this.loadAll().then(docs => { - this.cachedDocs = docs; - this.allDocs.next(this.cachedDocs); + this.allDocs.next( docs ); }); } @@ -266,27 +255,7 @@ export class Collection { // refresh loads all documents from localForage storage and emits it // to all listening queries. Called when the collection gets changed. protected async apply(change: DocumentChange) { - if (!this.cachedDocs) { - this.cachedDocs = await this.load(); - } - if (change.type === 'insert' || change.type === 'update') { - for (const doc of change.docs) { - const index = this.cachedDocs.findIndex(d => d.id === doc.id); - if (index === -1) { - this.cachedDocs.push(doc); - } else { - this.cachedDocs[index] = doc; - } - } - } else if (change.type === 'remove') { - for (const doc of change.docs) { - const index = this.cachedDocs.findIndex(d => d.id === doc.id); - if (index !== -1) { - this.cachedDocs.splice(index, 1); - } - } - } - this.allDocs.next(this.cachedDocs); + this.allDocs.next(this.storage.data); const resolveFn = this.changeResolve[change.id]; if (resolveFn) { resolveFn(); @@ -304,7 +273,7 @@ export class Collection { // emitAndApply emits the change and waits until it is applied. private async emitAndApply(change: DocumentChange): Promise { await new Promise(resolve => { - this.changeResolve[change.id] = resolve; + this.changeResolve[change.id] = resolve as any; this.changes.next(change); }); } From 2dc4d3f06cfe15d86241bc1380d42b4821fc8752 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Mon, 20 Mar 2023 15:15:03 +0530 Subject: [PATCH 04/13] Omit $loki and meta props added by loki from the docs --- src/__module.d.ts | 1 + src/__tests__/collection.spec.ts | 37 +++----------------------------- src/collection.ts | 13 ++++++++--- 3 files changed, 14 insertions(+), 37 deletions(-) diff --git a/src/__module.d.ts b/src/__module.d.ts index 265677d..669f5a7 100644 --- a/src/__module.d.ts +++ b/src/__module.d.ts @@ -2,3 +2,4 @@ declare module 'mingo'; declare module 'clone'; declare module 'lodash.isequal'; declare module 'lodash.clonedeep'; +declare module 'lodash.omit'; diff --git a/src/__tests__/collection.spec.ts b/src/__tests__/collection.spec.ts index 4fbcad9..08ed8a8 100644 --- a/src/__tests__/collection.spec.ts +++ b/src/__tests__/collection.spec.ts @@ -14,13 +14,6 @@ describe('Collection', () => { return { name, col }; } - const prepareOut = (val: any[]) => { - val.forEach((d: any) => { - delete d.meta; - delete d.$loki; - }); - }; - afterEach(() => { try { database.close(); @@ -105,7 +98,6 @@ describe('Collection', () => { const promise = watchN(col, 1); await col.insert(TEST_DOCS); const out = await promise; - prepareOut(out[0].docs); expect(out).toEqual([{ id: (jasmine.any(Number) as any) as number, type: 'insert', docs: [...TEST_DOCS] }]); done(); }); @@ -115,7 +107,6 @@ describe('Collection', () => { const watchPromise = watchN(col, 1, { z: 3 }); await col.insert(TEST_DOCS); const out = await watchPromise; - prepareOut(out[0].docs); expect(out).toEqual([ { id: (jasmine.any(Number) as any) as number, type: 'insert', docs: TEST_DOCS.filter(doc => doc.z === 3) }, ]); @@ -145,7 +136,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1); - prepareOut(out[0]); expect(out).toEqual([[...TEST_DOCS]]); done(); }); @@ -154,7 +144,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { x: -1 }); - prepareOut(out[0]); expect(out).toEqual([[]]); done(); }); @@ -163,7 +152,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { id: 'd000' }); - prepareOut(out[0]); expect(out).toEqual([[]]); done(); }); @@ -172,7 +160,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { z: 3 }); - prepareOut(out[0]); expect(out).toEqual([TEST_DOCS.filter(doc => doc.z === 3)]); done(); }); @@ -181,7 +168,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { id: 'd111' }); - prepareOut(out[0]); expect(out).toEqual([TEST_DOCS.filter(doc => doc.id === 'd111')]); done(); }); @@ -190,7 +176,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { id: { $in: ['d111', 'd112'] } }); - prepareOut(out[0]); expect(out).toEqual([TEST_DOCS.filter(doc => doc.id === 'd111' || doc.id === 'd112')]); done(); }); @@ -199,7 +184,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { y: 2 }, { sort: { z: -1 } }); - prepareOut(out[0]); expect(out).toEqual([TEST_DOCS.filter(doc => doc.y === 2).reverse()]); done(); }); @@ -208,7 +192,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { y: 2 }, { sort: { z: -1 }, skip: 1 }); - prepareOut(out[0]); expect(out).toEqual([ TEST_DOCS.filter(doc => doc.y === 2) .reverse() @@ -221,8 +204,7 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, { y: 2 }, { limit: 2 }); - prepareOut(out[0]); - expect( out ).toEqual([TEST_DOCS.filter(doc => doc.y === 2).slice(0, 2)]); + expect(out).toEqual([TEST_DOCS.filter(doc => doc.y === 2).slice(0, 2)]); done(); }); @@ -233,8 +215,6 @@ describe('Collection', () => { await col.update({ z: 2 }, { $set: { a: 1 } }); await col.update({ z: 3 }, { $set: { a: 2 } }); const out = await promise; - prepareOut(out[0]); - prepareOut(out[1]); expect(out).toEqual([ [{ id: 'd113', x: 1, y: 1, z: 3 }, { id: 'd123', x: 1, y: 2, z: 3 }], [{ id: 'd113', x: 1, y: 1, z: 3, a: 2 }, { id: 'd123', x: 1, y: 2, z: 3, a: 2 }], @@ -289,7 +269,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await find1N(col, 1, { y: 2 }, { sort: { z: -1 } }); - prepareOut(out); expect(out).toEqual([TEST_DOCS.filter(doc => doc.y === 2).reverse()[0]]); done(); }); @@ -298,7 +277,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await find1N(col, 1, { y: 2 }, { sort: { z: -1 }, skip: 1 }); - prepareOut(out); expect(out).toEqual([TEST_DOCS.filter(doc => doc.y === 2).reverse()[1]]); done(); }); @@ -310,8 +288,7 @@ describe('Collection', () => { await col.update({ z: 2 }, { $set: { a: 1 } }); await col.update({ z: 3 }, { $set: { a: 2 } }); const out = await promise; - prepareOut(out); - expect( out ).toEqual([{ id: 'd113', x: 1, y: 1, z: 3 }, { id: 'd113', x: 1, y: 1, z: 3, a: 2 }]); + expect(out).toEqual([{ id: 'd113', x: 1, y: 1, z: 3 }, { id: 'd113', x: 1, y: 1, z: 3, a: 2 }]); done(); }); @@ -338,7 +315,6 @@ describe('Collection', () => { const { col } = await prepare(); await Promise.all(TEST_DOCS.map(doc => col.insert(doc))); const out = await findN(col, 1, {}); - prepareOut(out[0]); expect(out).toEqual([[...TEST_DOCS]]); done(); }); @@ -347,7 +323,6 @@ describe('Collection', () => { const { col } = await prepare(); await col.insert(TEST_DOCS); const out = await findN(col, 1, {}); - prepareOut(out[0]); expect(out).toEqual([[...TEST_DOCS]]); done(); }); @@ -357,7 +332,6 @@ describe('Collection', () => { const promise = watchN(col, 1); await col.insert(TEST_DOCS); const out = await promise; - prepareOut(out[0].docs); expect(out).toEqual([{ id: (jasmine.any(Number) as any) as number, type: 'insert', docs: [...TEST_DOCS] }]); done(); }); @@ -378,7 +352,6 @@ describe('Collection', () => { await col.insert(TEST_DOCS); await col.update({ z: 3 }, { $set: { a: 1 } }); const out = await findN(col, 1, {}); - prepareOut(out[0]); expect(out).toEqual([ [ { id: 'd111', x: 1, y: 1, z: 1 }, @@ -398,7 +371,6 @@ describe('Collection', () => { await col.insert(TEST_DOCS); await col.update({ z: 3 }, { $set: { 'a.b': 1 } }); const out = await findN(col, 1, {}); - prepareOut(out[0]); expect(out).toEqual([ [ { id: 'd111', x: 1, y: 1, z: 1 }, @@ -421,7 +393,6 @@ describe('Collection', () => { const promise = watchN(col, 1); await col.update({ z: 3 }, { $set: { a: 1 } }); const out = await promise; - prepareOut(out[0].docs); expect(out).toEqual([ { id: (jasmine.any(Number) as any) as number, @@ -449,8 +420,7 @@ describe('Collection', () => { await col.insert(TEST_DOCS); await col.remove({ z: 3 }); const out = await findN(col, 1, {}); - prepareOut(out[0]); - expect( out ).toEqual([ + expect(out).toEqual([ [ { id: 'd111', x: 1, y: 1, z: 1 }, { id: 'd112', x: 1, y: 1, z: 2 }, @@ -467,7 +437,6 @@ describe('Collection', () => { const promise = watchN(col, 1); await col.remove({ z: 3 }); const out = await promise; - prepareOut( out ); expect(out).toEqual([ { id: (jasmine.any(Number) as any) as number, diff --git a/src/collection.ts b/src/collection.ts index 2895b57..eae236d 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -2,6 +2,7 @@ import mingo from 'mingo'; import * as Loki from 'lokijs'; import * as isequal from 'lodash.isequal'; import * as cloneDeep from 'lodash.clonedeep'; +import * as omit from 'lodash.omit'; import { Observable, Subject, empty, of, defer, from, Subscription } from 'rxjs'; import { switchMap, concatMap, concat, map, distinctUntilChanged } from 'rxjs/operators'; import { modify } from '@creately/mungo'; @@ -124,12 +125,18 @@ export class Collection { // made to documents which match the selector. public watch(selector?: Selector): Observable> { if (!selector) { - return this.changes.asObservable(); + return this.changes.asObservable().pipe( map( change => { + change.docs = change.docs.map(doc => omit( doc, '$loki', 'meta' )); + return change; + })); } const mq = new mingo.Query(selector); return this.changes.pipe( switchMap(change => { - const docs = change.docs.filter(doc => mq.test(doc)); + const docs = change.docs + .filter(doc => mq.test(doc)) + .map(doc => omit( doc, '$loki', 'meta' )); + change.docs = docs; if (!docs.length) { return empty(); } @@ -219,7 +226,7 @@ export class Collection { if (options.limit) { cursor = cursor.limit(options.limit); } - return cursor.all(); + return cursor.all().map(( doc: any ) => omit( doc, '$loki', 'meta' )); } // createFilter From cb50dff716c3557863725071b7f167026671a1fe Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Mon, 20 Mar 2023 15:17:08 +0530 Subject: [PATCH 05/13] Updated package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a63106a..3b99c67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@creately/rxdata", - "version": "6.0.1", + "version": "6.2.0", "description": "", "main": "dist/index.js", "typings": "dist/index.d.ts", From ffca9511ce51c94a8b3e468420901d7c08baeb59 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Mon, 20 Mar 2023 15:37:04 +0530 Subject: [PATCH 06/13] Updated tests --- src/__tests__/database.spec.ts | 26 ++++---------------------- src/collection.ts | 18 +++++++++--------- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/src/__tests__/database.spec.ts b/src/__tests__/database.spec.ts index e02636e..5404617 100644 --- a/src/__tests__/database.spec.ts +++ b/src/__tests__/database.spec.ts @@ -10,13 +10,6 @@ describe('Database', () => { return { db }; } - const prepareOut = (val: any[]) => { - val.forEach((d: any) => { - delete d.meta; - delete d.$loki; - }); - }; - afterEach(() => { try { database.close(); @@ -84,7 +77,6 @@ describe('Database', () => { const c2 = d2.collection('test'); await c1.insert({ id: 'd1' }); const out = await findN(c2, 1); - prepareOut(out[0]); expect(out).toEqual([[{ id: 'd1' }]]); done(); }); @@ -100,21 +92,11 @@ describe('Database', () => { it('should remove all documents in all collections in the database', async done => { const { db } = prepare(); - const c1 = db.collection('test1'); + const c1 = db.collection('test'); await c1.insert([{ id: 'd1' }]); - let out = await findN(c1, 1); - prepareOut(out[0]); - expect(out).toEqual([[{ id: 'd1' }]]); - - try { - const d = await db.drop(); - console.log('out d', d); - } catch (error) { - console.log('error', error); - } - out = await findN(c1, 1); - prepareOut(out[0]); - expect(out).toEqual([[]]); + expect(await findN(c1, 1)).toEqual([[{ id: 'd1' }]]); + await db.drop(); + expect(await findN(c1, 1)).toEqual([[]]); done(); }); }); diff --git a/src/collection.ts b/src/collection.ts index eae236d..ca50dc1 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -125,17 +125,17 @@ export class Collection { // made to documents which match the selector. public watch(selector?: Selector): Observable> { if (!selector) { - return this.changes.asObservable().pipe( map( change => { - change.docs = change.docs.map(doc => omit( doc, '$loki', 'meta' )); - return change; - })); + return this.changes.asObservable().pipe( + map(change => { + change.docs = change.docs.map(doc => omit(doc, '$loki', 'meta')); + return change; + }) + ); } const mq = new mingo.Query(selector); return this.changes.pipe( switchMap(change => { - const docs = change.docs - .filter(doc => mq.test(doc)) - .map(doc => omit( doc, '$loki', 'meta' )); + const docs = change.docs.filter(doc => mq.test(doc)).map(doc => omit(doc, '$loki', 'meta')); change.docs = docs; if (!docs.length) { return empty(); @@ -226,7 +226,7 @@ export class Collection { if (options.limit) { cursor = cursor.limit(options.limit); } - return cursor.all().map(( doc: any ) => omit( doc, '$loki', 'meta' )); + return cursor.all().map((doc: any) => omit(doc, '$loki', 'meta')); } // createFilter @@ -247,7 +247,7 @@ export class Collection { // the cachedDocs and emit the updated docs. public async reload() { return this.loadAll().then(docs => { - this.allDocs.next( docs ); + this.allDocs.next(docs); }); } From d8e3f6568a1cb67a73ee803f40b21e2c6ac9e05d Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Mon, 20 Mar 2023 15:38:38 +0530 Subject: [PATCH 07/13] Updated package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3b99c67..4827828 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@creately/rxdata", - "version": "6.2.0", + "version": "6.2.1", "description": "", "main": "dist/index.js", "typings": "dist/index.d.ts", From 6261cb7844b181d312c3abd4d8bca6b205879a72 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Wed, 22 Mar 2023 16:45:58 +0530 Subject: [PATCH 08/13] Updated watch method --- src/collection.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/collection.ts b/src/collection.ts index ca50dc1..2e52982 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -127,8 +127,8 @@ export class Collection { if (!selector) { return this.changes.asObservable().pipe( map(change => { - change.docs = change.docs.map(doc => omit(doc, '$loki', 'meta')); - return change; + const docs = change.docs.map(doc => omit(doc, '$loki', 'meta')); + return Object.assign({}, change, { docs }); }) ); } @@ -136,7 +136,6 @@ export class Collection { return this.changes.pipe( switchMap(change => { const docs = change.docs.filter(doc => mq.test(doc)).map(doc => omit(doc, '$loki', 'meta')); - change.docs = docs; if (!docs.length) { return empty(); } From 566e060dfeb943f2b4fbf0cde35a424a309caae3 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Wed, 22 Mar 2023 16:46:42 +0530 Subject: [PATCH 09/13] Updted package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4827828..d0eda2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@creately/rxdata", - "version": "6.2.1", + "version": "6.2.2", "description": "", "main": "dist/index.js", "typings": "dist/index.d.ts", From 77a1eeccd69a215c1eee46219f8562ecf06208d8 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Wed, 22 Mar 2023 18:11:13 +0530 Subject: [PATCH 10/13] Added a new test case --- src/__tests__/collection.spec.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/__tests__/collection.spec.ts b/src/__tests__/collection.spec.ts index 08ed8a8..5c278f5 100644 --- a/src/__tests__/collection.spec.ts +++ b/src/__tests__/collection.spec.ts @@ -105,11 +105,16 @@ describe('Collection', () => { it('should emit modified documents if they match the selector', async done => { const { col } = await prepare(); const watchPromise = watchN(col, 1, { z: 3 }); + const watchPromise2 = watchN(col, 1, { z: 2 }); await col.insert(TEST_DOCS); const out = await watchPromise; + const out2 = await watchPromise2; expect(out).toEqual([ { id: (jasmine.any(Number) as any) as number, type: 'insert', docs: TEST_DOCS.filter(doc => doc.z === 3) }, ]); + expect(out2).toEqual([ + { id: (jasmine.any(Number) as any) as number, type: 'insert', docs: TEST_DOCS.filter(doc => doc.z === 2) }, + ]); done(); }); From abcee136a8894d2832c4abcb0c780869aa848ef1 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Thu, 23 Mar 2023 15:29:02 +0530 Subject: [PATCH 11/13] Implemented upsert for rxdata --- package-lock.json | 8 ++++---- package.json | 2 +- src/__tests__/collection.spec.ts | 19 +++++++++++++++++++ src/__tests__/database.spec.ts | 1 + src/collection.ts | 14 +++++++++++++- 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 53a1549..44136ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@creately/rxdata", - "version": "6.0.1", + "version": "6.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4192,9 +4192,9 @@ } }, "rxjs": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", - "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", "requires": { "tslib": "^1.9.0" } diff --git a/package.json b/package.json index d0eda2f..db3afe4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@creately/rxdata", - "version": "6.2.2", + "version": "6.2.3", "description": "", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/src/__tests__/collection.spec.ts b/src/__tests__/collection.spec.ts index 5c278f5..36f0daa 100644 --- a/src/__tests__/collection.spec.ts +++ b/src/__tests__/collection.spec.ts @@ -341,6 +341,25 @@ describe('Collection', () => { done(); }); + it('should update the exsiting query / upsert', async done => { + const { col } = await prepare(); + const promise1 = watchN(col, 1); + await col.insert(TEST_DOCS); + let out = await promise1; + expect(out).toEqual([{ id: (jasmine.any(Number) as any) as number, type: 'insert', docs: [...TEST_DOCS] }]); + + const promise2 = watchN(col, 1); + await col.insert(Object.freeze({ id: 'd111', x: 2, y: 2, z: 2 })); + out = await promise2; + expect(( col as any ).storage.data.length ).toEqual( TEST_DOCS.length ); + expect(( col as any ).storage.data.filter(( doc: any ) => doc.id === 'd111' ).length ).toEqual( 1 ); + const updated = ( col as any ).storage.data.find(( doc: any ) => doc.id === 'd111' ) + expect( updated.x ).toEqual( 2 ); + expect( updated.y ).toEqual( 2 ); + expect( updated.z ).toEqual( 2 ); + done(); + }); + it('should emit the inserted document as a change (remote)'); }); diff --git a/src/__tests__/database.spec.ts b/src/__tests__/database.spec.ts index 5404617..bd32e8e 100644 --- a/src/__tests__/database.spec.ts +++ b/src/__tests__/database.spec.ts @@ -94,6 +94,7 @@ describe('Database', () => { const { db } = prepare(); const c1 = db.collection('test'); await c1.insert([{ id: 'd1' }]); + expect(Collection.loki.getCollection(`rxdata.test-db.test`).data[0].id).toEqual('d1'); expect(await findN(c1, 1)).toEqual([[{ id: 'd1' }]]); await db.drop(); expect(await findN(c1, 1)).toEqual([[]]); diff --git a/src/collection.ts b/src/collection.ts index 2e52982..e0eed6d 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -178,7 +178,19 @@ export class Collection { // with the id already exists in the collection, it will be replaced. public async insert(docOrDocs: T | T[]): Promise { const docs: T[] = cloneDeep(Array.isArray(docOrDocs) ? docOrDocs : [docOrDocs]); - this.storage.insert(docs); + docs.forEach( doc => { + var existingDoc = this.storage.findOne({ id: doc.id }); + if (existingDoc) { + // If a matching document exists, update it + Object.assign( existingDoc, doc ); + this.storage.update(existingDoc); + return existingDoc; + } else { + // If no matching document exists, insert the new document + this.storage.insert( doc ); + } + this.storage.findAndUpdate({ id: doc.id }, d => Object.assign( d, doc )) + }); await this.emitAndApply({ id: this.nextChangeId(), type: 'insert', docs: docs }); } From 49224bb40f014f73b833b3d8467c308e974ac0e1 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Thu, 23 Mar 2023 16:05:10 +0530 Subject: [PATCH 12/13] Updated inser --- package.json | 2 +- src/__tests__/collection.spec.ts | 12 ++++++------ src/collection.ts | 7 +++---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index db3afe4..62c6b6a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@creately/rxdata", - "version": "6.2.3", + "version": "6.2.4", "description": "", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/src/__tests__/collection.spec.ts b/src/__tests__/collection.spec.ts index 36f0daa..d9b9e66 100644 --- a/src/__tests__/collection.spec.ts +++ b/src/__tests__/collection.spec.ts @@ -351,12 +351,12 @@ describe('Collection', () => { const promise2 = watchN(col, 1); await col.insert(Object.freeze({ id: 'd111', x: 2, y: 2, z: 2 })); out = await promise2; - expect(( col as any ).storage.data.length ).toEqual( TEST_DOCS.length ); - expect(( col as any ).storage.data.filter(( doc: any ) => doc.id === 'd111' ).length ).toEqual( 1 ); - const updated = ( col as any ).storage.data.find(( doc: any ) => doc.id === 'd111' ) - expect( updated.x ).toEqual( 2 ); - expect( updated.y ).toEqual( 2 ); - expect( updated.z ).toEqual( 2 ); + expect((col as any).storage.data.length).toEqual(TEST_DOCS.length); + expect((col as any).storage.data.filter((doc: any) => doc.id === 'd111').length).toEqual(1); + const updated = (col as any).storage.data.find((doc: any) => doc.id === 'd111'); + expect(updated.x).toEqual(2); + expect(updated.y).toEqual(2); + expect(updated.z).toEqual(2); done(); }); diff --git a/src/collection.ts b/src/collection.ts index e0eed6d..49a7fa7 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -178,18 +178,17 @@ export class Collection { // with the id already exists in the collection, it will be replaced. public async insert(docOrDocs: T | T[]): Promise { const docs: T[] = cloneDeep(Array.isArray(docOrDocs) ? docOrDocs : [docOrDocs]); - docs.forEach( doc => { + docs.forEach(doc => { var existingDoc = this.storage.findOne({ id: doc.id }); if (existingDoc) { // If a matching document exists, update it - Object.assign( existingDoc, doc ); + Object.assign(existingDoc, doc); this.storage.update(existingDoc); return existingDoc; } else { // If no matching document exists, insert the new document - this.storage.insert( doc ); + this.storage.insert(doc); } - this.storage.findAndUpdate({ id: doc.id }, d => Object.assign( d, doc )) }); await this.emitAndApply({ id: this.nextChangeId(), type: 'insert', docs: docs }); } From ca2aeabde2689f894c3ec759086298179ff0a5d1 Mon Sep 17 00:00:00 2001 From: thisunravisara Date: Thu, 23 Mar 2023 16:07:57 +0530 Subject: [PATCH 13/13] Updated insert method --- src/collection.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/collection.ts b/src/collection.ts index 49a7fa7..756f4d6 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -184,7 +184,6 @@ export class Collection { // If a matching document exists, update it Object.assign(existingDoc, doc); this.storage.update(existingDoc); - return existingDoc; } else { // If no matching document exists, insert the new document this.storage.insert(doc);