remove deprecated features, remove 'compaction.done' event, add oncompaction callback, include 'callbackify' polyfill for the browser and use it instead of the 'util' module moved to devDependencies

feat/remove-native-modules-imports
Timothée Rebours 11 months ago
parent 68279ccdf0
commit 08c8076ae9
  1. 89
      browser-version/lib/customUtils.js
  2. 2
      browser-version/lib/storage.react-native.js
  3. 2
      lib/cursor.js
  4. 3
      lib/customUtils.js
  5. 85
      lib/datastore.js
  6. 68
      lib/persistence.js
  7. 24
      package-lock.json
  8. 6
      package.json
  9. 14
      test/db.async.test.js
  10. 18
      test/db.test.js
  11. 14
      test/persistence.async.test.js
  12. 6
      test/persistence.test.js
  13. 74
      webpack.config.js

@ -74,3 +74,92 @@ const byteArrayToBase64 = uint8 => {
const uid = len => byteArrayToBase64(randomBytes(Math.ceil(Math.max(8, len * 2)))).replace(/[+/]/g, '').slice(0, len)
module.exports.uid = uid
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
const getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors ||
function getOwnPropertyDescriptors (obj) {
const keys = Object.keys(obj)
const descriptors = {}
for (let i = 0; i < keys.length; i++) {
descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i])
}
return descriptors
}
function callbackifyOnRejected (reason, cb) {
// `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).
// Because `null` is a special error value in callbacks which means "no error
// occurred", we error-wrap so the callback consumer can distinguish between
// "the promise rejected with null" or "the promise fulfilled with undefined".
if (!reason) {
const newReason = new Error('Promise was rejected with a falsy value')
newReason.reason = reason
reason = newReason
}
return cb(reason)
}
/**
* Wraps a function with a callback, converting it into a callback-style function.
*
* Adapted from https://github.com/browserify/node-util, but without its dependency in `process`
*
* @param {function} original - The original function to be callbackified.
* @returns {function} - The callbackified function.
* @throws {TypeError} - If the "original" argument is not a function or if the last argument is not a function.
*/
function callbackify (original) {
if (typeof original !== 'function') {
throw new TypeError('The "original" argument must be of type Function')
}
// We DO NOT return the promise as it gives the user a false sense that
// the promise is actually somehow related to the callback's execution
// and that the callback throwing will reject the promise.
function callbackified () {
const args = []
for (let i = 0; i < arguments.length; i++) {
args.push(arguments[i])
}
const maybeCb = args.pop()
if (typeof maybeCb !== 'function') {
throw new TypeError('The last argument must be of type Function')
}
const self = this
const cb = function () {
return maybeCb.apply(self, arguments)
}
// In true node style we process the callback on `nextTick` with all the
// implications (stack, `uncaughtException`, `async_hooks`), done with setTimeout in browser.
original.apply(this, args)
.then(function (ret) { setTimeout(cb.bind(null, null, ret)) },
function (rej) { setTimeout(callbackifyOnRejected.bind(null, rej, cb)) })
}
Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original))
Object.defineProperties(callbackified,
getOwnPropertyDescriptors(original))
return callbackified
}
module.exports.callbackify = callbackify

@ -9,7 +9,7 @@
*/
const AsyncStorage = require('@react-native-async-storage/async-storage').default
const { callbackify } = require('util')
const { callbackify } = require('./customUtils')
/**
* Async version of {@link module:storageReactNative.exists}.

@ -1,5 +1,5 @@
const model = require('./model.js')
const { callbackify } = require('util')
const { callbackify } = require('./customUtils.js')
/**
* Has a callback

@ -5,6 +5,7 @@
* @private
*/
const crypto = require('crypto')
const { callbackify } = require('util')
/**
* Return a random alphanumerical string of length len
@ -24,3 +25,5 @@ const uid = len => crypto.randomBytes(Math.ceil(Math.max(8, len * 2)))
// Interface
module.exports.uid = uid
module.exports.callbackify = callbackify

@ -1,7 +1,5 @@
const { EventEmitter } = require('events')
const { callbackify, deprecate } = require('util')
const Cursor = require('./cursor.js')
const customUtils = require('./customUtils.js')
const { uid, callbackify } = require('./customUtils.js')
const Executor = require('./executor.js')
const Index = require('./indexes.js')
const model = require('./model.js')
@ -133,19 +131,12 @@ const { isDate, pick, filterIndexNames } = require('./utils.js')
* @return {string}
*/
/**
* @external EventEmitter
* @see http://nodejs.org/api/events.html
*/
/**
* @class
* @classdesc The `Datastore` class is the main class of NeDB.
* @extends external:EventEmitter
* @emits Datastore#event:"compaction.done"
* @typicalname NeDB
*/
class Datastore extends EventEmitter {
class Datastore {
/**
* Create a new collection, either persistent or in-memory.
*
@ -157,9 +148,7 @@ class Datastore extends EventEmitter {
* Also, if loading fails, all commands registered to the {@link Datastore#executor} afterwards will not be executed.
* They will be registered and executed, in sequence, only after a successful loading.
*
* @param {object|string} options Can be an object or a string. If options is a string, the behavior is the same as in
* v0.6: it will be interpreted as `options.filename`. **Giving a string is deprecated, and will be removed in the
* next major version.**
* @param {object} options
* @param {string} [options.filename = null] Path to the file where the data is persisted. If left blank, the datastore is
* automatically considered in-memory only. It cannot end with a `~` which is used in the temporary files NeDB uses to
* perform crash-safe writes. Not used if `options.inMemoryOnly` is `true`.
@ -177,6 +166,9 @@ class Datastore extends EventEmitter {
* @param {NoParamCallback} [options.onload] If you use autoloading, this is the handler called after the `loadDatabase`. It
* takes one `error` argument. If you use autoloading without specifying this handler, and an error happens during
* load, an error will be thrown.
* @param {NoParamCallback} [options.oncompaction] Callback called when a database compaction operation is finished,
* whether it succeeded or failed. If it failed, the first parameter is the Error object that was thrown,
* otherwise it is null.
* @param {serializationHook} [options.beforeDeserialization] Hook you can use to transform data after it was serialized and
* before it is written to disk. Can be used for example to encrypt data before writing database to disk. This
* function takes a string as parameter (one line of an NeDB data file) and outputs the transformed string, **which
@ -197,38 +189,29 @@ class Datastore extends EventEmitter {
* might be CPU-intensive
*/
constructor (options) {
super()
let filename
// Retrocompatibility with v0.6 and before
if (typeof options === 'string') {
deprecate(() => {
filename = options
this.inMemoryOnly = false // Default
}, '@seald-io/nedb: Giving a string to the Datastore constructor is deprecated and will be removed in the next major version. Please use an options object with an argument \'filename\'.')()
} else {
options = options || {}
filename = options.filename
/**
* Determines if the `Datastore` keeps data in-memory, or if it saves it in storage. Is not read after
* instanciation.
* @type {boolean}
* @protected
*/
this.inMemoryOnly = options.inMemoryOnly || false
/**
* Determines if the `Datastore` should autoload the database upon instantiation. Is not read after instanciation.
* @type {boolean}
* @protected
*/
this.autoload = options.autoload || false
/**
* Determines if the `Datastore` should add `createdAt` and `updatedAt` fields automatically if not set by the user.
* @type {boolean}
* @protected
*/
this.timestampData = options.timestampData || false
}
if (options && typeof options !== 'object') throw new Error('\'options\' must be an object')
options = options || {}
const filename = options.filename
/**
* Determines if the `Datastore` keeps data in-memory, or if it saves it in storage. Is not read after
* instanciation.
* @type {boolean}
* @protected
*/
this.inMemoryOnly = options.inMemoryOnly || false
/**
* Determines if the `Datastore` should autoload the database upon instantiation. Is not read after instanciation.
* @type {boolean}
* @protected
*/
this.autoload = options.autoload || false
/**
* Determines if the `Datastore` should add `createdAt` and `updatedAt` fields automatically if not set by the user.
* @type {boolean}
* @protected
*/
this.timestampData = options.timestampData || false
// Determine whether in memory or persistent
if (!filename || typeof filename !== 'string' || filename.length === 0) {
@ -314,6 +297,14 @@ class Datastore extends EventEmitter {
else throw err
})
} else this.autoloadPromise = null
/**
* Callback called when compaction has occurred
* @protected
* @type {NoParamCallback|null}
*/
this.oncompaction = options.oncompaction || null
/**
* Interval if {@link Datastore#setAutocompactionInterval} was called.
* @private
@ -709,7 +700,7 @@ class Datastore extends EventEmitter {
* @private
*/
_createNewId () {
let attemptId = customUtils.uid(16)
let attemptId = uid(16)
// Try as many times as needed to get an unused _id. As explained in customUtils, the probability of this ever happening is extremely small, so this is O(1)
if (this.indexes._id.getMatching(attemptId).length > 0) attemptId = this._createNewId()
return attemptId

@ -1,4 +1,3 @@
const { deprecate } = require('util')
const byline = require('./byline')
const customUtils = require('./customUtils.js')
const Index = require('./indexes.js')
@ -95,53 +94,32 @@ class Persistence {
* @private
*/
async persistCachedDatabaseAsync () {
const lines = []
if (this.inMemoryOnly) return
this.db.getAllData().forEach(doc => {
lines.push(this.afterSerialization(model.serialize(doc)))
})
Object.keys(this.db.indexes).forEach(fieldName => {
if (fieldName !== '_id') { // The special _id index is managed by datastore.js, the others need to be persisted
lines.push(this.afterSerialization(model.serialize({
$$indexCreated: {
fieldName: this.db.indexes[fieldName].fieldName,
unique: this.db.indexes[fieldName].unique,
sparse: this.db.indexes[fieldName].sparse
}
})))
}
})
await storage.crashSafeWriteFileLinesAsync(this.filename, lines, this.modes)
this.db.emit('compaction.done')
}
try {
const lines = []
/**
* @see Datastore#compactDatafile
* @deprecated
* @param {NoParamCallback} [callback = () => {}]
* @see Persistence#compactDatafileAsync
*/
compactDatafile (callback) {
deprecate(_callback => this.db.compactDatafile(_callback), '@seald-io/nedb: calling Datastore#persistence#compactDatafile is deprecated, please use Datastore#compactDatafile, it will be removed in the next major version.')(callback)
}
if (this.inMemoryOnly) return
/**
* @see Datastore#setAutocompactionInterval
* @deprecated
*/
setAutocompactionInterval (interval) {
deprecate(_interval => this.db.setAutocompactionInterval(_interval), '@seald-io/nedb: calling Datastore#persistence#setAutocompactionInterval is deprecated, please use Datastore#setAutocompactionInterval, it will be removed in the next major version.')(interval)
}
this.db.getAllData().forEach(doc => {
lines.push(this.afterSerialization(model.serialize(doc)))
})
Object.keys(this.db.indexes).forEach(fieldName => {
if (fieldName !== '_id') { // The special _id index is managed by datastore.js, the others need to be persisted
lines.push(this.afterSerialization(model.serialize({
$$indexCreated: {
fieldName: this.db.indexes[fieldName].fieldName,
unique: this.db.indexes[fieldName].unique,
sparse: this.db.indexes[fieldName].sparse
}
})))
}
})
/**
* @see Datastore#stopAutocompaction
* @deprecated
*/
stopAutocompaction () {
deprecate(() => this.db.stopAutocompaction(), '@seald-io/nedb: calling Datastore#persistence#stopAutocompaction is deprecated, please use Datastore#stopAutocompaction, it will be removed in the next major version.')()
await storage.crashSafeWriteFileLinesAsync(this.filename, lines, this.modes)
if (typeof this.db.oncompaction === 'function') this.db.oncompaction(null)
} catch (error) {
if (typeof this.db.oncompaction === 'function') this.db.oncompaction(error)
throw error
}
}
/**

24
package-lock.json generated

@ -10,8 +10,7 @@
"license": "MIT",
"dependencies": {
"@seald-io/binary-search-tree": "^1.0.3",
"localforage": "^1.9.0",
"util": "^0.12.4"
"localforage": "^1.9.0"
},
"devDependencies": {
"@react-native-async-storage/async-storage": "^1.17.11",
@ -41,6 +40,7 @@
"timers-browserify": "^2.0.12",
"ts-jest": "^27.1.5",
"typescript": "^4.9.5",
"util": "^0.12.5",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"xvfb-maybe": "^0.2.1"
@ -4700,6 +4700,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -5217,6 +5218,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
@ -7943,6 +7945,7 @@
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"dev": true,
"dependencies": {
"is-callable": "^1.1.3"
}
@ -8037,7 +8040,8 @@
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"node_modules/function.prototype.name": {
"version": "1.1.5",
@ -8097,6 +8101,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
"integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@ -8230,6 +8235,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.1.3"
},
@ -8274,6 +8280,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1"
},
@ -8327,6 +8334,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -8338,6 +8346,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dev": true,
"dependencies": {
"has-symbols": "^1.0.2"
},
@ -8670,7 +8679,8 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/internal-slot": {
"version": "1.0.4",
@ -8726,6 +8736,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@ -8807,6 +8818,7 @@
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -8919,6 +8931,7 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
"dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@ -9096,6 +9109,7 @@
"version": "1.1.10",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
"integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
"dev": true,
"dependencies": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
@ -15707,6 +15721,7 @@
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
"dev": true,
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
@ -16075,6 +16090,7 @@
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
"integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
"dev": true,
"dependencies": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",

@ -46,8 +46,7 @@
},
"dependencies": {
"@seald-io/binary-search-tree": "^1.0.3",
"localforage": "^1.9.0",
"util": "^0.12.4"
"localforage": "^1.9.0"
},
"devDependencies": {
"@react-native-async-storage/async-storage": "^1.17.11",
@ -77,6 +76,7 @@
"timers-browserify": "^2.0.12",
"ts-jest": "^27.1.5",
"typescript": "^4.9.5",
"util": "^0.12.5",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"xvfb-maybe": "^0.2.1"
@ -84,7 +84,7 @@
"scripts": {
"lint": "standard",
"test": "mocha --reporter spec --timeout 10000",
"build:browser": "webpack && webpack --optimization-minimize",
"build:browser": "webpack --config-name Nedb && webpack --config-name Nedb --env minimize && webpack --config-name testUtils --env minimize",
"pretest:browser": "npm run build:browser",
"test:browser": "xvfb-maybe karma start karma.conf.local.js",
"test:react-native": "jest test/react-native",

@ -22,20 +22,6 @@ describe('Database async', function () {
assert.equal(d.getAllData().length, 0)
})
it('Constructor compatibility with v0.6-', () => {
const db1 = new Datastore('somefile')
assert.equal(db1.filename, 'somefile')
assert.equal(db1.inMemoryOnly, false)
const db2 = new Datastore('')
assert.equal(db2.filename, null)
assert.equal(db2.inMemoryOnly, true)
const db3 = new Datastore()
assert.equal(db3.filename, null)
assert.equal(db3.inMemoryOnly, true)
})
describe('Autoloading', () => {
it('Can autoload a database and query it right away', async () => {
const fileStr = model.serialize({

@ -40,20 +40,6 @@ describe('Database', function () {
], done)
})
it('Constructor compatibility with v0.6-', function () {
let dbef = new Datastore('somefile')
dbef.filename.should.equal('somefile')
dbef.inMemoryOnly.should.equal(false)
dbef = new Datastore('')
assert.isNull(dbef.filename)
dbef.inMemoryOnly.should.equal(true)
dbef = new Datastore()
assert.isNull(dbef.filename)
dbef.inMemoryOnly.should.equal(true)
})
describe('Autoloading', function () {
it('Can autoload a database and query it right away', function (done) {
const fileStr = model.serialize({ _id: '1', a: 5, planet: 'Earth' }) + '\n' + model.serialize({
@ -617,7 +603,7 @@ describe('Database', function () {
assert.isNull(err)
assert.isNull(doc)
d.on('compaction.done', function () {
d.oncompaction = function () {
// After compaction, no more mention of the document, correctly removed
const datafileContents = fs.readFileSync(testDb, 'utf8')
datafileContents.split('\n').length.should.equal(2)
@ -631,7 +617,7 @@ describe('Database', function () {
done()
})
})
}
d.compactDatafile()
})

@ -367,12 +367,16 @@ describe('Persistence async', function () {
})
})
it('Can listen to compaction events', async () => {
const compacted = new Promise(resolve => {
d.once('compaction.done', function () {
resolve()
})
it('Can use compaction callback', async () => {
let resolve, reject
const compacted = new Promise((_resolve, _reject) => {
resolve = _resolve
reject = _reject
})
d.oncompaction = err => {
if (err) reject(err)
else resolve(null)
}
await d.compactDatafileAsync()
await compacted // should already be resolved when the function returns, but still awaiting for it
})

@ -453,10 +453,10 @@ describe('Persistence', function () {
})
it('Can listen to compaction events', function (done) {
d.on('compaction.done', function () {
d.removeAllListeners('compaction.done') // Tidy up for next tests
d.oncompaction = function () {
d.oncompaction = null // Tidy up for next tests
done()
})
}
d.compactDatafile()
})

@ -4,42 +4,16 @@ const path = require('path')
const webpack = require('webpack')
module.exports = (env, argv) => {
const minimize = argv.optimizationMinimize || false
return {
const minimize = argv.env.minimize || false
const baseConfig = {
mode: 'production',
cache: false,
watch: false,
target: 'web',
node: {
global: true
},
optimization: {
minimize
},
resolve: {
fallback: {
fs: false,
path: require.resolve('path-browserify'),
events: require.resolve('events/'),
crypto: false
}
},
plugins: [
new webpack.NormalModuleReplacementPlugin(new RegExp(path.resolve(__dirname, 'lib/storage.js')), path.resolve(__dirname, 'browser-version/lib/storage.browser.js')),
new webpack.NormalModuleReplacementPlugin(new RegExp(path.resolve(__dirname, 'lib/customUtils.js')), path.resolve(__dirname, 'browser-version/lib/customUtils.js')),
new webpack.NormalModuleReplacementPlugin(/byline/, path.resolve(__dirname, 'browser-version/lib/byline.js')),
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer'],
setImmediate: ['timers-browserify', 'setImmediate'],
clearImmediate: ['timers-browserify', 'clearImmediate'],
util: 'util'
})
],
entry: {
Nedb: path.join(__dirname, 'lib', 'datastore.js'),
testUtils: path.join(__dirname, 'test', 'utils.test.js')
},
output: {
path: path.join(__dirname, 'browser-version/out'),
filename: pathData => `${pathData.chunk.name.toLowerCase()}${minimize ? '.min' : ''}.js`,
@ -47,4 +21,46 @@ module.exports = (env, argv) => {
library: '[name]'
}
}
const pluginsNedb = [
new webpack.NormalModuleReplacementPlugin(new RegExp(path.resolve(__dirname, 'lib/storage.js')), path.resolve(__dirname, 'browser-version/lib/storage.browser.js')),
new webpack.NormalModuleReplacementPlugin(new RegExp(path.resolve(__dirname, 'lib/customUtils.js')), path.resolve(__dirname, 'browser-version/lib/customUtils.js')),
new webpack.NormalModuleReplacementPlugin(/byline/, path.resolve(__dirname, 'browser-version/lib/byline.js'))
]
const polyfillPlugins = [
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer'],
setImmediate: ['timers-browserify', 'setImmediate'],
clearImmediate: ['timers-browserify', 'clearImmediate']
})
]
return [
{
...baseConfig,
name: 'Nedb',
plugins: pluginsNedb,
entry: {
Nedb: path.join(__dirname, 'lib', 'datastore.js')
}
},
{
...baseConfig,
name: 'testUtils',
plugins: polyfillPlugins,
resolve: {
fallback: {
fs: false,
path: require.resolve('path-browserify'),
util: require.resolve('util/'),
crypto: false
}
},
entry: {
testUtils: path.join(__dirname, 'test', 'utils.test.js')
}
}
]
}

Loading…
Cancel
Save