From 2a121faccc6760cc0ec2085bd51514520870a6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Rebours?= Date: Fri, 2 Sep 2022 14:41:12 +0200 Subject: [PATCH] add testSerializationHooks option --- index.d.ts | 1 + lib/datastore.js | 5 ++++- lib/persistence.js | 13 ++++++++----- test/persistence.async.test.js | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/index.d.ts b/index.d.ts index bbbd4af..b3059ab 100644 --- a/index.d.ts +++ b/index.d.ts @@ -114,6 +114,7 @@ declare namespace Nedb { corruptAlertThreshold?: number; compareStrings?(a: string, b: string): number; modes?: {fileMode: number, dirMode: number}; + testSerializationHooks?: boolean; } interface UpdateOptions { diff --git a/lib/datastore.js b/lib/datastore.js index 140cccf..1eabc88 100755 --- a/lib/datastore.js +++ b/lib/datastore.js @@ -193,6 +193,8 @@ class Datastore extends EventEmitter { * @param {compareStrings} [options.compareStrings] If specified, it overrides default string comparison which is not * well adapted to non-US characters in particular accented letters. Native `localCompare` will most of the time be * the right choice. + * @param {boolean} [options.testSerializationHooks=true] Whether to test the serialization hooks or not, + * might be CPU-intensive */ constructor (options) { super() @@ -262,7 +264,8 @@ class Datastore extends EventEmitter { afterSerialization: options.afterSerialization, beforeDeserialization: options.beforeDeserialization, corruptAlertThreshold: options.corruptAlertThreshold, - modes: options.modes + modes: options.modes, + testSerializationHooks: options.testSerializationHooks }) // This new executor is ready if we don't use persistence diff --git a/lib/persistence.js b/lib/persistence.js index 2d21aaa..5f96d0a 100755 --- a/lib/persistence.js +++ b/lib/persistence.js @@ -49,6 +49,7 @@ class Persistence { * @param {object} [options.modes] Modes to use for FS permissions. Will not work on Windows. * @param {number} [options.modes.fileMode=0o644] Mode to use for files. * @param {number} [options.modes.dirMode=0o755] Mode to use for directories. + * @param {boolean} [options.testSerializationHooks=true] Whether to test the serialization hooks or not, might be CPU-intensive */ constructor (options) { this.db = options.db @@ -77,11 +78,13 @@ class Persistence { this.afterSerialization = options.afterSerialization || (s => s) this.beforeDeserialization = options.beforeDeserialization || (s => s) - for (let i = 1; i < 30; i += 1) { - for (let j = 0; j < 10; j += 1) { - const randomString = customUtils.uid(i) - if (this.beforeDeserialization(this.afterSerialization(randomString)) !== randomString) { - throw new Error('beforeDeserialization is not the reverse of afterSerialization, cautiously refusing to start NeDB to prevent dataloss') + if (options.testSerializationHooks === undefined || options.testSerializationHooks) { + for (let i = 1; i < 30; i += 1) { + for (let j = 0; j < 10; j += 1) { + const randomString = customUtils.uid(i) + if (this.beforeDeserialization(this.afterSerialization(randomString)) !== randomString) { + throw new Error('beforeDeserialization is not the reverse of afterSerialization, cautiously refusing to start NeDB to prevent dataloss') + } } } } diff --git a/test/persistence.async.test.js b/test/persistence.async.test.js index 7473a7c..241147b 100755 --- a/test/persistence.async.test.js +++ b/test/persistence.async.test.js @@ -461,6 +461,20 @@ describe('Persistence async', function () { assert.equal(await fs.readFile(hookTestFilename, 'utf8'), 'Some content') }) + it('Declaring two hooks that are not reverse of one another will not cause exception if options.testSerializationHooks === false', async () => { + const hookTestFilename = 'workspace/hookTest.db' + await storage.ensureFileDoesntExistAsync(hookTestFilename) + await fs.writeFile(hookTestFilename, 'Some content', 'utf8') + const db = new Datastore({ + filename: hookTestFilename, + autoload: true, + afterSerialization: as, + beforeDeserialization: function (s) { return s }, + testSerializationHooks: false + }) + await assert.rejects(() => db.autoloadPromise) + }) + it('A serialization hook can be used to transform data before writing new state to disk', async () => { const hookTestFilename = 'workspace/hookTest.db' await storage.ensureFileDoesntExistAsync(hookTestFilename)