Merge pull request #17 from seald/react-native

react-native version
pull/19/head
tex0l 3 years ago committed by GitHub
commit bd4ea63116
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      .github/workflows/github-actions-demo.yml
  2. 4
      CHANGELOG.md
  3. 1
      __mocks__/@react-native-async-storage/async-storage.js
  4. 1
      browser-version/lib/storage.browser.js
  5. 86
      browser-version/lib/storage.react-native.js
  6. 30807
      package-lock.json
  7. 20
      package.json
  8. 108
      test/react-native/persistence.test.js
  9. 3
      test/react-native/resolver.js
  10. 2
      webpack.config.js

@ -45,3 +45,16 @@ jobs:
uses: browser-actions/setup-chrome@latest uses: browser-actions/setup-chrome@latest
- run: npm ci - run: npm ci
- run: npm run test:browser - run: npm run test:browser
react-native-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Node.js 14
uses: actions/setup-node@v2
with:
node-version: 14.x
cache: 'npm'
- run: npm ci
- run: npm run test:react-native

@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres and this project adheres
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Added
- Include a `"react-native"` version (heavily inspired from [react-native-local-mongdb](https://github.com/antoniopresto/react-native-local-mongodb)).
## [2.1.0] - 2021-10-21 ## [2.1.0] - 2021-10-21
Thanks to [@eliot-akira](https://github.com/eliot-akira) for the amazing work on file streaming. Thanks to [@eliot-akira](https://github.com/eliot-akira) for the amazing work on file streaming.
### Changed ### Changed

@ -0,0 +1 @@
module.exports.default = require('@react-native-async-storage/async-storage/jest/async-storage-mock')

@ -2,6 +2,7 @@
* Way data is stored for this database * Way data is stored for this database
* For a Node.js/Node Webkit database it's the file system * For a Node.js/Node Webkit database it's the file system
* For a browser-side database it's localforage, which uses the best backend available (IndexedDB then WebSQL then localStorage) * For a browser-side database it's localforage, which uses the best backend available (IndexedDB then WebSQL then localStorage)
* For a react-native database, we use @react-native-async-storage/async-storage
* *
* This version is the browser version * This version is the browser version
*/ */

@ -0,0 +1,86 @@
/**
* Way data is stored for this database
* For a Node.js/Node Webkit database it's the file system
* For a browser-side database it's localforage, which uses the best backend available (IndexedDB then WebSQL then localStorage)
* For a react-native database, we use @react-native-async-storage/async-storage
*
* This version is the react-native version
*/
const AsyncStorage = require('@react-native-async-storage/async-storage').default
const exists = (filename, cback) => {
// eslint-disable-next-line node/handle-callback-err
AsyncStorage.getItem(filename, (err, value) => {
if (value !== null) {
return cback(true)
} else {
return cback(false)
}
})
}
const rename = (filename, newFilename, callback) => {
// eslint-disable-next-line node/handle-callback-err
AsyncStorage.getItem(filename, (err, value) => {
if (value === null) {
this.storage.removeItem(newFilename, callback)
} else {
this.storage.setItem(newFilename, value, () => {
this.storage.removeItem(filename, callback)
})
}
})
}
const writeFile = (filename, contents, options, callback) => {
// Options do not matter in a react-native setup
if (typeof options === 'function') { callback = options }
AsyncStorage.setItem(filename, contents, callback)
}
const appendFile = (filename, toAppend, options, callback) => {
// Options do not matter in a react-native setup
if (typeof options === 'function') { callback = options }
// eslint-disable-next-line node/handle-callback-err
AsyncStorage.getItem(filename, (err, contents) => {
contents = contents || ''
contents += toAppend
AsyncStorage.setItem(filename, contents, callback)
})
}
const readFile = (filename, options, callback) => {
// Options do not matter in a react-native setup
if (typeof options === 'function') { callback = options }
// eslint-disable-next-line node/handle-callback-err
AsyncStorage.getItem(filename, (err, contents) => {
return callback(null, contents || '')
})
}
const unlink = (filename, callback) => {
AsyncStorage.removeItem(filename, callback)
}
// Nothing to do, no directories will be used on react-native
const mkdir = (dir, options, callback) => callback()
// Nothing to do, no data corruption possible on react-native
const ensureDatafileIntegrity = (filename, callback) => callback(null)
const crashSafeWriteFileLines = (filename, lines, callback) => {
lines.push('') // Add final new line
writeFile(filename, lines.join('\n'), callback)
}
// Interface
module.exports.exists = exists
module.exports.rename = rename
module.exports.writeFile = writeFile
module.exports.crashSafeWriteFileLines = crashSafeWriteFileLines
module.exports.appendFile = appendFile
module.exports.readFile = readFile
module.exports.unlink = unlink
module.exports.mkdir = mkdir
module.exports.ensureDatafileIntegrity = ensureDatafileIntegrity

30807
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{ {
"name": "@seald-io/nedb", "name": "@seald-io/nedb",
"version": "2.1.0", "version": "2.2.0-1",
"files": [ "files": [
"lib/**/*.js", "lib/**/*.js",
"browser-version/**/*.js", "browser-version/**/*.js",
@ -46,9 +46,13 @@
"localforage": "^1.9.0" "localforage": "^1.9.0"
}, },
"devDependencies": { "devDependencies": {
"@react-native-async-storage/async-storage": "^1.15.9",
"@types/jest": "^27.0.2",
"browser-resolve": "^2.0.0",
"chai": "^4.3.4", "chai": "^4.3.4",
"commander": "^7.2.0", "commander": "^7.2.0",
"events": "^3.3.0", "events": "^3.3.0",
"jest": "^27.3.1",
"jquery": "^3.6.0", "jquery": "^3.6.0",
"karma": "^6.3.2", "karma": "^6.3.2",
"karma-chai": "^0.1.0", "karma-chai": "^0.1.0",
@ -65,6 +69,7 @@
"standard": "^16.0.3", "standard": "^16.0.3",
"terser-webpack-plugin": "^5.1.2", "terser-webpack-plugin": "^5.1.2",
"timers-browserify": "^2.0.12", "timers-browserify": "^2.0.12",
"ts-jest": "^27.0.7",
"ts-node": "^10.3.0", "ts-node": "^10.3.0",
"typescript": "^4.4.4", "typescript": "^4.4.4",
"webpack": "^5.37.0", "webpack": "^5.37.0",
@ -77,13 +82,19 @@
"build:browser": "webpack && webpack --optimization-minimize", "build:browser": "webpack && webpack --optimization-minimize",
"pretest:browser": "npm run build:browser", "pretest:browser": "npm run build:browser",
"test:browser": "xvfb-maybe karma start karma.conf.local.js", "test:browser": "xvfb-maybe karma start karma.conf.local.js",
"test:react-native": "jest test/react-native",
"test:typings": "ts-node ./typings-tests.ts", "test:typings": "ts-node ./typings-tests.ts",
"prepublishOnly": "npm run build:browser" "prepublishOnly": "npm run build:browser"
}, },
"main": "index.js", "main": "index.js",
"browser": { "browser": {
"./lib/customUtils.js": "./browser-version/lib/customUtils.js", "./lib/customUtils.js": "./browser-version/lib/customUtils.js",
"./lib/storage.js": "./browser-version/lib/storage.js", "./lib/storage.js": "./browser-version/lib/storage.browser.js",
"./lib/byline.js": "./browser-version/lib/byline.js"
},
"react-native": {
"./lib/customUtils.js": "./browser-version/lib/customUtils.js",
"./lib/storage.js": "./browser-version/lib/storage.react-native.js",
"./lib/byline.js": "./browser-version/lib/byline.js" "./lib/byline.js": "./browser-version/lib/byline.js"
}, },
"license": "MIT", "license": "MIT",
@ -95,5 +106,10 @@
"browser-version/out", "browser-version/out",
"**/*.ts" "**/*.ts"
] ]
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
"resolver": "<rootDir>/test/react-native/resolver.js"
} }
} }

@ -0,0 +1,108 @@
/* eslint-env jest */
// Forked from https://github.com/antoniopresto/react-native-local-mongodb/blob/93acbc8a9aaca86aed1d632855cd8b984501147b/test/persistence.test.js
const { promisify } = require('util')
const AsyncStorage = require('@react-native-async-storage/async-storage').default
const DataStore = require('../../')
const getDb = async () => {
await AsyncStorage.clear()
const db = new DataStore({ filename: 'foo' })
await promisify(db.loadDatabase.bind(db))()
return db
}
it('update', async () => {
const db = await getDb()
const items0 = await promisify(db.find.bind(db))({})
expect(AsyncStorage.getItem).toHaveBeenCalled()
await promisify(db.insert.bind(db))({ name: 'Maggie' })
await promisify(db.insert.bind(db))({ name: 'Bob' })
expect(AsyncStorage.setItem).toHaveBeenCalled()
const items = await promisify(db.find.bind(db))({})
const maggie1 = await promisify(db.findOne.bind(db))({ name: 'Maggie' })
const bob1 = await promisify(db.findOne.bind(db))({ name: 'Bob' })
const res = await promisify(db.update.bind(db))({ name: { $in: ['Maggie', 'Bob'] } }, { $set: { age: 1 } }, { multi: true })
const maggie2 = await promisify(db.findOne.bind(db))({ name: 'Maggie' })
const bob2 = await promisify(db.findOne.bind(db))({ name: 'Bob' })
expect(res).toEqual(2)
expect(items0).toHaveLength(0)
expect(items).toHaveLength(2)
expect(maggie1.age).toBeUndefined()
expect(bob1.age).toBeUndefined()
expect(bob2.age).toEqual(1)
expect(maggie2.age).toEqual(1)
})
it('remove', async () => {
const db = await getDb()
const items0 = await promisify(db.find.bind(db))({})
expect(AsyncStorage.getItem).toHaveBeenCalled()
await promisify(db.insert.bind(db))({ name: 'Maggie' })
await promisify(db.insert.bind(db))({ name: 'Bob' })
expect(AsyncStorage.setItem).toHaveBeenCalled()
const items = await promisify(db.find.bind(db))({})
const res = await promisify(db.remove.bind(db))({ name: { $in: ['Bob'] } }, { multi: true })
const bob2 = await promisify(db.findOne.bind(db))({ name: 'Bob' })
expect(res).toEqual(1)
expect(items0).toHaveLength(0)
expect(items).toHaveLength(2)
expect(bob2).toBeNull()
})
it('resolve remove nonexistent', async () => {
const db = await getDb()
const items0 = await promisify(db.find.bind(db))({})
expect(AsyncStorage.getItem).toHaveBeenCalled()
await promisify(db.insert.bind(db))({ name: 'Maggie' })
await promisify(db.insert.bind(db))({ name: 'Bob' })
expect(AsyncStorage.setItem).toHaveBeenCalled()
const items = await promisify(db.find.bind(db))({})
const res = await promisify(db.remove.bind(db))({ name: 'nonexistent' }, { multi: true })
const nonexistent = await promisify(db.findOne.bind(db))({ name: 'nonexistent' })
expect(res).toEqual(0)
expect(items0).toHaveLength(0)
expect(items).toHaveLength(2)
expect(nonexistent).toBeNull()
})
it('resolve findOne nonexistent', async () => {
const db = await getDb()
await promisify(db.insert.bind(db))({ name: 'Maggie' })
await promisify(db.insert.bind(db))({ name: 'Bob' })
expect(AsyncStorage.setItem).toHaveBeenCalled()
const items = await promisify(db.find.bind(db))({ name: 'nonexistent' })
const item = await promisify(db.findOne.bind(db))({ name: 'nonexistent' })
expect(item).toBeNull()
expect(items.length).toEqual(0)
})
it('should limit', async () => {
const db = await getDb()
await promisify(db.insert.bind(db))({ name: 'A' })
await promisify(db.insert.bind(db))({ name: 'B' })
await promisify(db.insert.bind(db))({ name: 'C' })
await promisify(db.insert.bind(db))({ name: 'D' })
expect(AsyncStorage.setItem).toHaveBeenCalled()
const cursor = db.find({}).sort({ name: 1 }).skip(1).limit(2)
const docs = await promisify(cursor.exec.bind(cursor))()
expect(docs.length).toEqual(2)
expect(docs[1].name).toEqual('C')
})

@ -0,0 +1,3 @@
const browserResolve = require('browser-resolve')
module.exports = (id, opts) => browserResolve.sync(id, { ...opts, browser: 'react-native' })

@ -25,7 +25,7 @@ module.exports = (env, argv) => {
} }
}, },
plugins: [ plugins: [
new webpack.NormalModuleReplacementPlugin(new RegExp(path.resolve(__dirname, 'lib/storage.js')), path.resolve(__dirname, 'browser-version/lib/storage.js')), 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(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.NormalModuleReplacementPlugin(/byline/, path.resolve(__dirname, 'browser-version/lib/byline.js')),
new webpack.ProvidePlugin({ new webpack.ProvidePlugin({

Loading…
Cancel
Save