Comparing version 4.1.4 to 4.2.0
{ | ||
"name": "enmap", | ||
"version": "4.1.4", | ||
"version": "4.2.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -110,2 +110,14 @@ // Lodash should probably be a core lib but hey, it's useful! | ||
configurable: false | ||
}, | ||
pollingInterval: { | ||
value: !_.isNil(options.pollingInterval) ? options.pollingInterval : 1000, | ||
writeable: true, | ||
enumerable: false, | ||
configurable: false | ||
}, | ||
polling: { | ||
value: !_.isNil(options.polling) ? options.polling : false, | ||
writeable: true, | ||
enumerable: false, | ||
configurable: false | ||
} | ||
@@ -170,2 +182,5 @@ }); | ||
this.db.prepare(`INSERT OR REPLACE INTO ${this.name} (key, value) VALUES (?, ?);`).run(key, JSON.stringify(data)); | ||
if (this.polling) { | ||
this.db.prepare(`INSERT INTO 'internal::changes::${this.name}' (type, key, value, timestamp, pid) VALUES (?, ?, ?, ?, ?);`).run('insert', key, JSON.stringify(data), Date.now(), process.pid); | ||
} | ||
} | ||
@@ -219,41 +234,7 @@ return super.set(key, this[_clone](data)); | ||
* Migrates an Enmap from version 3 or lower to a Version 4 enmap, which is locked to sqlite backend only. | ||
* Version 4 uses a different way of storing data, so is not directly compatible with version 3 data. | ||
* Note that this migration also makes the data unuseable with version 3, so it should only be used to migrate once. | ||
* @example | ||
* // This example migrates from enmap-mongo to the new format. | ||
* // Assumes: npm install enmap@3.1.4 enmap-sqlite@latest enmap-mongo@latest | ||
* const Enmap = require("enmap"); | ||
* const Provider = require("enmap-mongo"); | ||
* const SQLite = require("enmap-sqlite"); | ||
* | ||
* let options = { | ||
* name: 'test', | ||
* dbName: 'enmap', | ||
* url: 'mongodb://username:password@localhost:27017/enmap' | ||
* }; | ||
* | ||
* const source = new Provider(options); | ||
* const target = new SQLite({"name": "points"}); | ||
* | ||
* Enmap.migrate(source, target); | ||
* @param {Provider} source A valid Enmap provider. Can be any existing provider. | ||
* @param {Provider} target An SQLite Enmap Provider. Cannot work without enmap-sqlite as the target. | ||
* This migration MUST be executed in version 3.1.4 of Enmap, along with appropriate providers. | ||
* See https://enmap.evie.codes/install/upgrade for more details. | ||
*/ | ||
static async migrate(source, target) { | ||
if (!source || !target) throw `Both source and target are required.`; | ||
if (source.constructor.name !== 'EnmapProvider') throw new Err('Source must be a valid Enmap Provider (not an initialized enmap)', 'EnmapMigrationError'); | ||
if (target.constructor.name !== 'EnmapProvider') throw new Err('Target must be a valid Enmap Provider (not an initialized enmap)', 'EnmapMigrationError'); | ||
const sourceMap = new Enmap({ provider: source }); | ||
const targetMap = new Enmap({ fetchAll: false, provider: target }); | ||
await sourceMap.defer; | ||
await targetMap.defer; | ||
if (!targetMap.db.pool.path.includes('enmap.sqlite')) { | ||
throw new Err('Target enmap is not an sqlite database. The migrate method is only to migrate from a 3.0 enmap to 4.0 sqlite enmap!', 'EnmapMigrationError'); | ||
} | ||
const insertArray = []; | ||
sourceMap.keyArray().forEach(key => { | ||
insertArray.push(targetMap.db.set(key, JSON.stringify(sourceMap.get(key)))); | ||
}); | ||
await Promise.all(insertArray); | ||
return; | ||
static async migrate() { | ||
throw new Err('PLEASE DOWNGRADE TO ENMAP@3.1.4 TO USE THE MIGRATE TOOL', 'EnmapMigrationError'); | ||
} | ||
@@ -630,2 +611,5 @@ | ||
if (this.persistent) { | ||
if (this.polling) { | ||
this.db.prepare(`INSERT INTO 'internal::changes::${this.name}' (type, key, timestamp, pid) VALUES (?, ?, ?, ?);`).run('delete', key.toString(), Date.now(), process.pid); | ||
} | ||
return this.db.prepare(`DELETE FROM ${this.name} WHERE key = '${key}'`).run(); | ||
@@ -660,2 +644,5 @@ } | ||
this.db.prepare(`DELETE FROM ${this.name};`).run(); | ||
if (this.polling) { | ||
this.db.prepare(`INSERT INTO 'internal::changes::${this.name}' (type, timestamp, pid) VALUES (?, ?, ?);`).run('clear', Date.now(), process.pid); | ||
} | ||
} | ||
@@ -769,3 +756,3 @@ super.clear(); | ||
} | ||
const table = this.db.prepare(`SELECT count(*) FROM sqlite_master WHERE type='table' AND name = '${this.name}';`).get(); | ||
const table = this.db.prepare("SELECT count(*) FROM sqlite_master WHERE type='table' AND name = ?;").get(this.name); | ||
if (!table['count(*)']) { | ||
@@ -776,5 +763,37 @@ this.db.prepare(`CREATE TABLE ${this.name} (key text PRIMARY KEY, value text)`).run(); | ||
} | ||
if (this.polling) { | ||
const logs = this.db.prepare(`SELECT count(*) FROM sqlite_master WHERE type='table' AND name = 'internal::changes::${this.name}';`).get(); | ||
if (!logs['count(*)']) { | ||
this.db.prepare(`CREATE TABLE 'internal::changes::${this.name}' (type TEXT, key TEXT, value TEXT, timestamp INTEGER, pid INTEGER);`).run(); | ||
} | ||
} | ||
if (this.fetchAll) { | ||
await this.fetchEverything(); | ||
} | ||
if (this.polling) { | ||
Object.defineProperty(this, 'lastSync', { | ||
value: new Date(), | ||
writable: true, | ||
enumerable: false, | ||
configurable: false | ||
}); | ||
setInterval(() => { | ||
const changes = this.db.prepare(`SELECT type, key, value FROM 'internal::changes::${this.name}' WHERE timestamp >= ? AND pid <> ? ORDER BY timestamp ASC;`).all(this.lastSync.getTime(), process.pid); | ||
for (const row of changes) { | ||
switch (row.type) { | ||
case 'insert': | ||
super.set(row.key, this[_parseData](row.value)); | ||
break; | ||
case 'delete': | ||
super.delete(row.key); | ||
break; | ||
case 'clear': | ||
super.clear(); | ||
break; | ||
} | ||
} | ||
this.lastSync = new Date(); | ||
this.db.prepare(`DELETE FROM 'internal::changes::${this.name}' WHERE ROWID IN (SELECT ROWID FROM 'internal::changes::${this.name}' ORDER BY ROWID DESC LIMIT -1 OFFSET 100);`).run(); | ||
}, this.pollingInterval); | ||
} | ||
this.ready(); | ||
@@ -781,0 +800,0 @@ return this.defer; |
89628
1770