Compare commits

..

No commits in common. '68279ccdf09fd3064ce5e02e0f3c30d75d8e2cfa' and 'd4c096b07ade20e89d6c4f965309519a35f76da2' have entirely different histories.

  1. 10
      CHANGELOG.md
  2. 4
      README.md
  3. 3
      benchmarks/commonUtilities.js
  4. 13
      browser-version/lib/storage.browser.js
  5. 13
      browser-version/lib/storage.react-native.js
  6. 12
      index.d.ts
  7. 11
      lib/persistence.js
  8. 20
      lib/storage.js
  9. 4
      package-lock.json
  10. 2
      package.json
  11. 3
      test/cursor.async.test.js
  12. 3
      test/cursor.test.js
  13. 3
      test/db.async.test.js
  14. 3
      test/db.test.js
  15. 3
      test/executor.async.test.js
  16. 3
      test/executor.test.js
  17. 4
      test/persistence.async.test.js
  18. 3
      test/persistence.test.js

@ -6,12 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [4.0.4] - 2024-01-11
## Unreleased
### Fixed
- Explicitly import `buffer` [#34](https://github.com/seald/nedb/pull/34), thanks [maxdaniel98](https://github.com/maxdaniel98).
- Fix `Cursor`'s typings [#45](https://github.com/seald/nedb/issues/45).
- Removes unnecessary uses of the native `path` module for the browser and React-Native version by replacing the internal `Persistance.ensureDirectoryExistsAsync` static method with `Persistance.ensureParentDirectoryExistsAsync` so that any `path` functions are used only in Node.js where it is necessary, as it is not necessary for the browser and React-Native [#51](https://github.com/seald/nedb/pull/51).
- Explicit return/callback type for update based on options [#44](https://github.com/seald/nedb/pull/44), thanks [RobMayer](https://github.com/RobMayer).
- Explicitly import `buffer` [#34](https://github.com/seald/nedb/pull/34).
- Fix `Cursor`'s typings [#45](https://github.com/seald/nedb/issues/45)
## [4.0.3] - 2023-12-13
### Fixed
@ -78,7 +76,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- `Persistence#persistCachedDatabase` replaced with `Persistence#persistCachedDatabaseAsync`;
- `Persistence#persistNewState` replaced with `Persistence#persistNewStateAsync`;
- `Persistence#treatRawStream` replaced with `Persistence#treatRawStreamAsync`;
- `Persistence.ensureDirectoryExists` replaced with `Persistence.ensureDirectoryExistsAsync`;
- `Persistence.ensureDirectoryExists` replaced with `Persistence#ensureDirectoryExistsAsync`;
- Cursor:
- `Cursor#_exec` replaced with `Cursor#_execAsync`;
- `Cursor#project` replaced with `Cursor#_project`;

@ -838,10 +838,6 @@ This is done for:
the repo because it is unmaintained). It isn't used in the browser nor
react-native versions, therefore it is shimmed with an empty object.
However, the `browser` and `react-native` versions rely on node native modules and therefore must be polyfilled:
- `util` with https://github.com/browserify/node-util.
- `events` with https://github.com/browserify/events.
## Performance
### Speed

@ -2,6 +2,7 @@
* Functions that are used in several benchmark tests
*/
const fs = require('fs')
const path = require('path')
const Datastore = require('../lib/datastore')
const Persistence = require('../lib/persistence')
const { callbackify } = require('util')
@ -45,7 +46,7 @@ module.exports.getConfiguration = function (benchDb) {
* Ensure the workspace stat and the db datafile is empty
*/
module.exports.prepareDb = function (filename, cb) {
callbackify((filename) => Persistence.ensureParentDirectoryExistsAsync(filename))(filename, function () {
callbackify((dirname) => Persistence.ensureDirectoryExistsAsync(dirname))(path.dirname(filename), function () {
fs.access(filename, fs.constants.FS_OK, function (err) {
if (!err) {
fs.unlink(filename, cb)

@ -138,17 +138,6 @@ const unlinkAsync = async filename => {
*/
const mkdirAsync = (path, options) => Promise.resolve()
/**
* Shim for {@link module:storage.ensureParentDirectoryExistsAsync}, nothing to do, no directories will be used on the browser.
* @function
* @param {string} file
* @param {number} [mode]
* @return {Promise<void|string>}
* @alias module:storageBrowser.ensureParentDirectoryExistsAsync
* @async
*/
const ensureParentDirectoryExistsAsync = async (file, mode) => Promise.resolve()
/**
* Shim for {@link module:storage.ensureDatafileIntegrityAsync}, nothing to do, no data corruption possible in the browser.
* @param {string} filename
@ -187,5 +176,3 @@ module.exports.unlinkAsync = unlinkAsync
module.exports.mkdirAsync = mkdirAsync
module.exports.ensureDatafileIntegrityAsync = ensureDatafileIntegrityAsync
module.exports.ensureParentDirectoryExistsAsync = ensureParentDirectoryExistsAsync

@ -253,17 +253,6 @@ const crashSafeWriteFileLinesAsync = async (filename, lines) => {
*/
const crashSafeWriteFileLines = callbackify(crashSafeWriteFileLinesAsync)
/**
* Shim for {@link module:storage.ensureParentDirectoryExistsAsync}, nothing to do, no directories will be used on the browser.
* @function
* @param {string} file
* @param {number} [mode]
* @return {Promise<void|string>}
* @alias module:storageBrowser.ensureParentDirectoryExistsAsync
* @async
*/
const ensureParentDirectoryExistsAsync = async (file, mode) => Promise.resolve()
// Interface
module.exports.exists = exists
module.exports.existsAsync = existsAsync
@ -291,5 +280,3 @@ module.exports.mkdirAsync = mkdirAsync
module.exports.ensureDatafileIntegrity = ensureDatafileIntegrity
module.exports.ensureDatafileIntegrityAsync = ensureDatafileIntegrityAsync
module.exports.ensureParentDirectoryExistsAsync = ensureParentDirectoryExistsAsync

12
index.d.ts vendored

@ -105,25 +105,25 @@ declare class Nedb<Schema = Record<string, any>> extends EventEmitter {
projection?: any
): Nedb.Cursor<T>;
update<T extends Schema, O extends Nedb.UpdateOptions>(
update<T extends Schema>(
query: any,
updateQuery: any,
options?: O,
options?: Nedb.UpdateOptions,
callback?: (
err: Error | null,
numberOfUpdated: number,
affectedDocuments: O['returnUpdatedDocs'] extends true ? O['multi'] extends true ? Document<T>[] | null : Document<T> | null : null,
affectedDocuments: Document<T> | Document<T>[] | null,
upsert: boolean | null
) => void
): void;
updateAsync<T extends Schema, O extends Nedb.UpdateOptions>(
updateAsync<T extends Schema>(
query: any,
updateQuery: any,
options?: O
options?: Nedb.UpdateOptions
): Promise<{
numAffected: number;
affectedDocuments: O['returnUpdatedDocs'] extends true ? O['multi'] extends true ? Document<T>[] | null : Document<T> | null : null;
affectedDocuments: Document<T> | Document<T>[] | null;
upsert: boolean;
}>;

@ -1,3 +1,4 @@
const path = require('path')
const { deprecate } = require('util')
const byline = require('./byline')
const customUtils = require('./customUtils.js')
@ -307,7 +308,7 @@ class Persistence {
// In-memory only datastore
if (this.inMemoryOnly) return
await Persistence.ensureParentDirectoryExistsAsync(this.filename, this.modes.dirMode)
await Persistence.ensureDirectoryExistsAsync(path.dirname(this.filename), this.modes.dirMode)
await storage.ensureDatafileIntegrityAsync(this.filename, this.modes.fileMode)
let treatedData
@ -371,8 +372,12 @@ class Persistence {
* @return {Promise<void>}
* @private
*/
static async ensureParentDirectoryExistsAsync (dir, mode = DEFAULT_DIR_MODE) {
return storage.ensureParentDirectoryExistsAsync(dir, mode)
static async ensureDirectoryExistsAsync (dir, mode = DEFAULT_DIR_MODE) {
const parsedDir = path.parse(path.resolve(dir))
// this is because on Windows mkdir throws a permission error when called on the root directory of a volume
if (process.platform !== 'win32' || parsedDir.dir !== parsedDir.root || parsedDir.base !== '') {
await storage.mkdirAsync(dir, { recursive: true, mode })
}
}
}

@ -1,6 +1,6 @@
/**
* Way data is stored for this database.
* This version is the Node.js version.
* This version is the Node.js/Node Webkit version.
* It's essentially fs, mkdirp and crash safe write and read functions.
*
* @see module:storageBrowser
@ -271,22 +271,6 @@ const ensureDatafileIntegrityAsync = async (filename, mode = DEFAULT_FILE_MODE)
else await renameAsync(tempFilename, filename)
}
/**
* Check if a file's parent directory exists and create it on the fly if it is not the case.
* @param {string} filename
* @param {number} mode
* @return {Promise<void>}
* @private
*/
const ensureParentDirectoryExistsAsync = async (filename, mode) => {
const dir = path.dirname(filename)
const parsedDir = path.parse(path.resolve(dir))
// this is because on Windows mkdir throws a permission error when called on the root directory of a volume
if (process.platform !== 'win32' || parsedDir.dir !== parsedDir.root || parsedDir.base !== '') {
await mkdirAsync(dir, { recursive: true, mode })
}
}
// Interface
module.exports.existsAsync = existsAsync
@ -313,5 +297,3 @@ module.exports.flushToStorageAsync = flushToStorageAsync
module.exports.ensureDatafileIntegrityAsync = ensureDatafileIntegrityAsync
module.exports.ensureFileDoesntExistAsync = ensureFileDoesntExistAsync
module.exports.ensureParentDirectoryExistsAsync = ensureParentDirectoryExistsAsync

4
package-lock.json generated

@ -1,12 +1,12 @@
{
"name": "@seald-io/nedb",
"version": "4.0.4",
"version": "4.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@seald-io/nedb",
"version": "4.0.4",
"version": "4.0.3",
"license": "MIT",
"dependencies": {
"@seald-io/binary-search-tree": "^1.0.3",

@ -1,6 +1,6 @@
{
"name": "@seald-io/nedb",
"version": "4.0.4",
"version": "4.0.3",
"files": [
"lib/**/*.js",
"browser-version/**/*.js",

@ -2,6 +2,7 @@
const testDb = 'workspace/test.db'
const { promises: fs } = require('fs')
const assert = require('assert').strict
const path = require('path')
const Datastore = require('../lib/datastore')
const Persistence = require('../lib/persistence')
const Cursor = require('../lib/cursor')
@ -14,7 +15,7 @@ describe('Cursor Async', function () {
d = new Datastore({ filename: testDb })
assert.equal(d.filename, testDb)
assert.equal(d.inMemoryOnly, false)
await Persistence.ensureParentDirectoryExistsAsync(testDb)
await Persistence.ensureDirectoryExistsAsync(path.dirname(testDb))
if (await exists(testDb)) await fs.unlink(testDb)
await d.loadDatabaseAsync()
assert.equal(d.getAllData().length, 0)

@ -2,6 +2,7 @@
const chai = require('chai')
const testDb = 'workspace/test.db'
const fs = require('fs')
const path = require('path')
const { each, waterfall } = require('./utils.test.js')
const Datastore = require('../lib/datastore')
const Persistence = require('../lib/persistence')
@ -21,7 +22,7 @@ describe('Cursor', function () {
waterfall([
function (cb) {
callbackify((filename) => Persistence.ensureParentDirectoryExistsAsync(filename))(testDb, function () {
callbackify((dirname) => Persistence.ensureDirectoryExistsAsync(dirname))(path.dirname(testDb), function () {
fs.access(testDb, fs.constants.F_OK, function (err) {
if (!err) {
fs.unlink(testDb, cb)

@ -1,6 +1,7 @@
/* eslint-env mocha */
const testDb = 'workspace/test.db'
const { promises: fs } = require('fs')
const path = require('path')
const assert = require('assert').strict
const model = require('../lib/model')
const Datastore = require('../lib/datastore')
@ -16,7 +17,7 @@ describe('Database async', function () {
d = new Datastore({ filename: testDb })
assert.equal(d.filename, testDb)
assert.equal(d.inMemoryOnly, false)
await Persistence.ensureParentDirectoryExistsAsync(testDb)
await Persistence.ensureDirectoryExistsAsync(path.dirname(testDb))
if (await exists(testDb)) await fs.unlink(testDb)
await d.loadDatabaseAsync()
assert.equal(d.getAllData().length, 0)

@ -2,6 +2,7 @@
const chai = require('chai')
const testDb = 'workspace/test.db'
const fs = require('fs')
const path = require('path')
const { apply, each, waterfall } = require('./utils.test.js')
const model = require('../lib/model')
const Datastore = require('../lib/datastore')
@ -22,7 +23,7 @@ describe('Database', function () {
waterfall([
function (cb) {
callbackify((filename) => Persistence.ensureParentDirectoryExistsAsync(filename))(testDb, function () {
callbackify((dirname) => Persistence.ensureDirectoryExistsAsync(dirname))(path.dirname(testDb), function () {
fs.access(testDb, fs.constants.FS_OK, function (err) {
if (!err) {
fs.unlink(testDb, cb)

@ -2,6 +2,7 @@
const testDb = 'workspace/test.db'
const { promises: fs } = require('fs')
const assert = require('assert').strict
const path = require('path')
const Datastore = require('../lib/datastore')
const Persistence = require('../lib/persistence')
const { exists } = require('./utils.test.js')
@ -52,7 +53,7 @@ describe('Executor async', function () {
d = new Datastore({ filename: testDb })
assert.equal(d.filename, testDb)
assert.equal(d.inMemoryOnly, false)
await Persistence.ensureParentDirectoryExistsAsync(testDb)
await Persistence.ensureDirectoryExistsAsync(path.dirname(testDb))
if (await exists(testDb)) await fs.unlink(testDb)
await d.loadDatabaseAsync()
assert.equal(d.getAllData().length, 0)

@ -2,6 +2,7 @@
const chai = require('chai')
const testDb = 'workspace/test.db'
const fs = require('fs')
const path = require('path')
const { waterfall } = require('./utils.test.js')
const Datastore = require('../lib/datastore')
const Persistence = require('../lib/persistence')
@ -153,7 +154,7 @@ describe('Executor', function () {
waterfall([
function (cb) {
callbackify((filename) => Persistence.ensureParentDirectoryExistsAsync(filename))(testDb, function () {
callbackify((dirname) => Persistence.ensureDirectoryExistsAsync(dirname))(path.dirname(testDb), function () {
fs.access(testDb, fs.constants.F_OK, function (err) {
if (!err) {
fs.unlink(testDb, cb)

@ -22,7 +22,7 @@ describe('Persistence async', function () {
d = new Datastore({ filename: testDb })
assert.equal(d.filename, testDb)
assert.equal(d.inMemoryOnly, false)
await Persistence.ensureParentDirectoryExistsAsync(testDb)
await Persistence.ensureDirectoryExistsAsync(path.dirname(testDb))
if (await exists(testDb)) await fs.unlink(testDb)
await d.loadDatabaseAsync()
assert.equal(d.getAllData().length, 0)
@ -1062,7 +1062,7 @@ describe('permissions', function () {
})
it('ensureDirectoryExists forwards mode argument', async () => {
await Persistence.ensureParentDirectoryExistsAsync(testDb, 0o700)
await Persistence.ensureDirectoryExistsAsync(path.dirname(testDb), 0o700)
assert.equal(await getMode(path.dirname(testDb)), 0o700)
})

@ -2,6 +2,7 @@
const chai = require('chai')
const testDb = 'workspace/test.db'
const fs = require('fs')
const path = require('path')
const { apply, waterfall } = require('./utils.test.js')
const model = require('../lib/model')
const Datastore = require('../lib/datastore')
@ -26,7 +27,7 @@ describe('Persistence', function () {
waterfall([
function (cb) {
callbackify((filename) => Persistence.ensureParentDirectoryExistsAsync(filename))(testDb, function () {
callbackify((dirname) => Persistence.ensureDirectoryExistsAsync(dirname))(path.dirname(testDb), function () {
fs.access(testDb, fs.constants.FS_OK, function (err) {
if (!err) {
fs.unlink(testDb, cb)

Loading…
Cancel
Save