Skip to content

Commit 6bb0bb6

Browse files
committed
feat: add patch to loki
1 parent a212aaf commit 6bb0bb6

File tree

4 files changed

+77
-0
lines changed

4 files changed

+77
-0
lines changed

package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/loki/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"dependencies": {
3030
"@js-soft/docdb-access-abstractions": "1.1.0",
3131
"@types/lokijs": "1.5.14",
32+
"fast-json-patch": "^3.1.1",
3233
"lokijs": "1.5.12"
3334
},
3435
"publishConfig": {

packages/loki/src/LokiJsCollection.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
DatabaseType,
66
IDatabaseCollection
77
} from "@js-soft/docdb-access-abstractions";
8+
import jsonpatch from "fast-json-patch";
89

910
export class LokiJsCollection implements IDatabaseCollection {
1011
public readonly name: string;
@@ -43,6 +44,30 @@ export class LokiJsCollection implements IDatabaseCollection {
4344
return data;
4445
}
4546

47+
public async patch(oldDocument: any, data: any): Promise<any> {
48+
if (typeof data.toJSON === "function") {
49+
data = data.toJSON();
50+
}
51+
52+
if (!("id" in oldDocument)) {
53+
throw new Error("Patching is not supported for documents with an 'id' field. Use 'update' instead.");
54+
}
55+
56+
data.$loki = oldDocument.$loki;
57+
data.meta = oldDocument.meta;
58+
59+
const patch = jsonpatch.compare(oldDocument, data);
60+
const updated = this.collection
61+
.chain()
62+
.find({ id: oldDocument.id }, true)
63+
.update((doc) => jsonpatch.applyPatch(doc, patch))
64+
.data();
65+
66+
if (updated.length < 1) throw new Error("Document not found for patching");
67+
68+
return updated[0];
69+
}
70+
4671
public async delete(query: any): Promise<boolean> {
4772
if (typeof query === "string") {
4873
query = { id: query };

packages/loki/test/DatabaseCollection.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,40 @@ describe("DatabaseCollection", () => {
224224

225225
await expect(db.create({ id: "uniqueValue" })).rejects.toThrow("Duplicate key for property id: uniqueValue");
226226
});
227+
228+
describe("patch vs update", () => {
229+
test("update is not working properly", async () => {
230+
const db = await getRandomCollection();
231+
232+
const entry = { id: "test", name: "test" };
233+
const createdEntry = await db.create(entry);
234+
235+
// this will completely replaced
236+
await db.update(createdEntry, { id: "test", name: "updated" });
237+
238+
// this will replace the above
239+
await db.update(createdEntry, { id: "test", name: "test", anotherField: "newField" });
240+
241+
const queriedEntry = await db.findOne({ id: "test" });
242+
expect(queriedEntry.name).toBe("test");
243+
expect(queriedEntry.anotherField).toBe("newField");
244+
});
245+
246+
test("patch is better", async () => {
247+
const db = await getRandomCollection();
248+
249+
const entry = { id: "test", name: "test" };
250+
const createdEntry = await db.create(entry);
251+
252+
// this changes name
253+
await db.patch(createdEntry, { id: "test", name: "updated" });
254+
255+
// this only adds another field
256+
await db.patch(createdEntry, { id: "test", name: "test", anotherField: "newField" });
257+
258+
const queriedEntry = await db.findOne({ id: "test" });
259+
expect(queriedEntry.name).toBe("updated");
260+
expect(queriedEntry.anotherField).toBe("newField");
261+
});
262+
});
227263
});

0 commit comments

Comments
 (0)