diff --git a/changelog.md b/changelog.md index 60f8339..0d4bfd6 100644 --- a/changelog.md +++ b/changelog.md @@ -1,11 +1,21 @@ ## 0.0.1.beta-0 -* First release named dat-db +- First release named dat-db ## 0.0.2.beta-0 -* Renamed from dat-db to quipodb -* Added a readme -* Added document -* Added changelogs -* Added a nice logo (stole it from flaticon) +- Renamed from dat-db to quipodb +- Added a readme +- Added document +- Added changelogs +- Added a nice logo (stole it from flaticon) + +## 1.0.0 + +- Changed `setDoc` to `createDoc` +- Added `hasDoc` +- Moved DB function into a new class + +## 1.0.1 + +- Added atomic setters for `updateDoc` diff --git a/dist/index.js b/dist/index.js index bb38aac..42068cb 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,6 +1,7 @@ import BSQLite from "better-sqlite3"; import fs from "fs-extra"; import _ from "lodash"; +import { mergeAndConcat } from "merge-anything"; class QuipoDB { options; storage; @@ -13,11 +14,11 @@ class QuipoDB { inMemory: true, }); this.options = options; + fs.ensureFileSync(`${this.options.path}`); this.storage = {}; this.sqlite = new SQLite({ fileName: `${this.options.path}` }); this.ready = false; // Set-up - fs.ensureFileSync(`${this.options.path}`); if (this.options.inMemory) { this.sqlite.provider .prepare(`SELECT name FROM sqlite_master WHERE type='table'`) @@ -79,7 +80,7 @@ class QuipoDB { return this.storage[collectionName]; } } -// +// Document class Doc { storage; collectionName; @@ -162,21 +163,110 @@ class Doc { return this; } if (typeof value === "function") { + let newValue = _.defaultsDeep(value(oldVal), oldVal); const index = this.storage[this.collectionName].findIndex((doc) => value(doc)); - this.storage[this.collectionName][index] = _.defaultsDeep(value(oldVal), oldVal); + Object.keys(value(oldVal)) + .filter((v) => v.startsWith("$")) + .forEach((atomic) => { + newValue = _.defaultsDeep(new Query()[atomic](oldVal, value(oldVal)[atomic]), oldVal); + }); + this.storage[this.collectionName][index] = _.defaultsDeep(newValue, oldVal); if (this.options.inMemory) - this.sqlite.updateRow(this.collectionName, this.primaryKey, _.defaultsDeep(value(oldVal), oldVal)); + this.sqlite.updateRow(this.collectionName, this.primaryKey, _.defaultsDeep(newValue, oldVal)); } else if (typeof value === "object") { + let newValue = _.defaultsDeep(value, oldVal); + Object.keys(value) + .filter((v) => v.startsWith("$")) + .forEach((atomic) => { + newValue = _.defaultsDeep(new Query()[atomic](oldVal, value[atomic]), oldVal); + }); const index = this.storage[this.collectionName].findIndex((doc) => doc[this.primaryKey] === data[this.primaryKey]); - this.storage[this.collectionName][index] = _.defaultsDeep(value, oldVal); + this.storage[this.collectionName][index] = _.defaultsDeep(newValue, oldVal); if (this.options.inMemory) - this.sqlite.updateRow(this.collectionName, this.primaryKey, value); + this.sqlite.updateRow(this.collectionName, this.primaryKey, _.defaultsDeep(newValue, oldVal)); } cb(this); return this; } } +class Query { + constructor() { } + where(query) { + _.get; + } + $add(...data) { + const deepMerge = (oldData, newData) => { + return Object.keys(oldData).reduce((acc, key) => { + if (typeof newData[key] === "object") { + acc[key] = deepMerge(oldData[key], newData[key]); + } + else if (newData.hasOwnProperty(key) && !isNaN(parseFloat(newData[key]))) { + if (!acc[key]) + acc[key] = oldData[key] + newData[key]; + acc[key] = oldData[key] + newData[key]; + } + return acc; + }, {}); + }; + const result = data.reduce((acc, obj) => (acc = deepMerge(acc, obj))); + return result; + } + $subtract(...data) { + const deepMerge = (oldData, newData) => { + return Object.keys(oldData).reduce((acc, key) => { + if (typeof newData[key] === "object") { + acc[key] = deepMerge(oldData[key], newData[key]); + } + else if (newData.hasOwnProperty(key) && !isNaN(parseFloat(newData[key]))) { + if (!acc[key]) + acc[key] = oldData[key] - newData[key]; + acc[key] = oldData[key] - newData[key]; + } + return acc; + }, {}); + }; + const result = data.reduce((acc, obj) => (acc = deepMerge(acc, obj))); + return result; + } + $multiply(...data) { + const deepMerge = (oldData, newData) => { + return Object.keys(oldData).reduce((acc, key) => { + if (typeof newData[key] === "object") { + acc[key] = deepMerge(oldData[key], newData[key]); + } + else if (newData.hasOwnProperty(key) && !isNaN(parseFloat(newData[key]))) { + if (!acc[key]) + acc[key] = oldData[key] * newData[key]; + acc[key] = oldData[key] * newData[key]; + } + return acc; + }, {}); + }; + const result = data.reduce((acc, obj) => (acc = deepMerge(acc, obj))); + return result; + } + $divide(...data) { + const deepMerge = (oldData, newData) => { + return Object.keys(oldData).reduce((acc, key) => { + if (typeof newData[key] === "object") { + acc[key] = deepMerge(oldData[key], newData[key]); + } + else if (newData.hasOwnProperty(key) && !isNaN(parseFloat(newData[key]))) { + if (!acc[key]) + acc[key] = oldData[key] / newData[key]; + acc[key] = oldData[key] / newData[key]; + } + return acc; + }, {}); + }; + const result = data.reduce((acc, obj) => (acc = deepMerge(acc, obj))); + return result; + } + $push(oldval, newVal) { + return mergeAndConcat(oldval, newVal); + } +} // SQLite Provider class SQLite { options; diff --git a/index.ts b/index.ts index 8294600..f90a6e8 100644 --- a/index.ts +++ b/index.ts @@ -1,6 +1,7 @@ import BSQLite from "better-sqlite3"; import fs from "fs-extra"; import _ from "lodash"; +import { mergeAndConcat } from "merge-anything"; interface constructorOptions { path?: string; @@ -25,12 +26,12 @@ class QuipoDB { inMemory: true, }); this.options = options; + fs.ensureFileSync(`${this.options.path}`); this.storage = {}; this.sqlite = new SQLite({ fileName: `${this.options.path}` }); this.ready = false; // Set-up - fs.ensureFileSync(`${this.options.path}`); if (this.options.inMemory) { this.sqlite.provider .prepare(`SELECT name FROM sqlite_master WHERE type='table'`) @@ -88,7 +89,7 @@ class QuipoDB { return this.storage[collectionName]; } } -// +// Document class Doc { public storage: storage; private collectionName: string; @@ -165,18 +166,107 @@ class Doc { return this; } if (typeof value === "function") { + let newValue = _.defaultsDeep(value(oldVal), oldVal); const index = this.storage[this.collectionName].findIndex((doc) => value(doc)); - this.storage[this.collectionName][index] = _.defaultsDeep(value(oldVal), oldVal); - if (this.options.inMemory) this.sqlite.updateRow(this.collectionName, this.primaryKey, _.defaultsDeep(value(oldVal), oldVal)); + Object.keys(value(oldVal)) + .filter((v) => v.startsWith("$")) + .forEach((atomic) => { + newValue = _.defaultsDeep(new Query()[atomic](oldVal, value(oldVal)[atomic]), oldVal); + }); + this.storage[this.collectionName][index] = _.defaultsDeep(newValue, oldVal); + if (this.options.inMemory) this.sqlite.updateRow(this.collectionName, this.primaryKey, _.defaultsDeep(newValue, oldVal)); } else if (typeof value === "object") { + let newValue = _.defaultsDeep(value, oldVal); + Object.keys(value) + .filter((v) => v.startsWith("$")) + .forEach((atomic) => { + newValue = _.defaultsDeep(new Query()[atomic](oldVal, value[atomic]), oldVal); + }); const index = this.storage[this.collectionName].findIndex((doc) => doc[this.primaryKey] === data[this.primaryKey]); - this.storage[this.collectionName][index] = _.defaultsDeep(value, oldVal); - if (this.options.inMemory) this.sqlite.updateRow(this.collectionName, this.primaryKey, value); + this.storage[this.collectionName][index] = _.defaultsDeep(newValue, oldVal); + if (this.options.inMemory) this.sqlite.updateRow(this.collectionName, this.primaryKey, _.defaultsDeep(newValue, oldVal)); } cb(this); return this; } } +class Query { + constructor() {} + public where(query: string) { + _.get; + } + public $add(...data: Object[]) { + const deepMerge = (oldData: any, newData: any) => { + return Object.keys(oldData).reduce((acc, key) => { + if (typeof newData[key] === "object") { + acc[key] = deepMerge(oldData[key], newData[key]); + } else if (newData.hasOwnProperty(key) && !isNaN(parseFloat(newData[key]))) { + if (!acc[key]) acc[key] = oldData[key] + newData[key]; + acc[key] = oldData[key] + newData[key]; + } + return acc; + }, {}); + }; + + const result = data.reduce((acc, obj) => (acc = deepMerge(acc, obj))); + + return result; + } + public $subtract(...data: Object[]) { + const deepMerge = (oldData: any, newData: any) => { + return Object.keys(oldData).reduce((acc, key) => { + if (typeof newData[key] === "object") { + acc[key] = deepMerge(oldData[key], newData[key]); + } else if (newData.hasOwnProperty(key) && !isNaN(parseFloat(newData[key]))) { + if (!acc[key]) acc[key] = oldData[key] - newData[key]; + acc[key] = oldData[key] - newData[key]; + } + return acc; + }, {}); + }; + + const result = data.reduce((acc, obj) => (acc = deepMerge(acc, obj))); + + return result; + } + public $multiply(...data: Object[]) { + const deepMerge = (oldData: any, newData: any) => { + return Object.keys(oldData).reduce((acc, key) => { + if (typeof newData[key] === "object") { + acc[key] = deepMerge(oldData[key], newData[key]); + } else if (newData.hasOwnProperty(key) && !isNaN(parseFloat(newData[key]))) { + if (!acc[key]) acc[key] = oldData[key] * newData[key]; + acc[key] = oldData[key] * newData[key]; + } + return acc; + }, {}); + }; + + const result = data.reduce((acc, obj) => (acc = deepMerge(acc, obj))); + + return result; + } + public $divide(...data: Object[]) { + const deepMerge = (oldData: any, newData: any) => { + return Object.keys(oldData).reduce((acc, key) => { + if (typeof newData[key] === "object") { + acc[key] = deepMerge(oldData[key], newData[key]); + } else if (newData.hasOwnProperty(key) && !isNaN(parseFloat(newData[key]))) { + if (!acc[key]) acc[key] = oldData[key] / newData[key]; + acc[key] = oldData[key] / newData[key]; + } + return acc; + }, {}); + }; + + const result = data.reduce((acc, obj) => (acc = deepMerge(acc, obj))); + + return result; + } + public $push(oldval: any, newVal: any) { + return mergeAndConcat(oldval, newVal); + } +} // SQLite Provider class SQLite { diff --git a/package.json b/package.json index 7b2d4b8..d8c30f8 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,9 @@ "dependencies": { "better-sqlite3": "^7.6.2", "fs-extra": "^10.1.0", - "lodash": "^4.17.21" + "is-what": "^4.1.7", + "lodash": "^4.17.21", + "merge-anything": "^5.0.4" }, "devDependencies": { "@types/fs-extra": "^9.0.13",