react-native-local-mongodb
Advanced tools
Comparing version
@@ -10,5 +10,3 @@ var customUtils = require('./customUtils'), | ||
Cursor = require('./cursor'), | ||
promisefy = require('./promisefy').promisefy | ||
; | ||
promisefy = require('./promisefy').promisefy; | ||
/** | ||
@@ -43,3 +41,22 @@ * Create a new collection | ||
this.timestampData = options.timestampData || false; | ||
this.storage = options.storage || getAsyncStorage(); | ||
this.storage = options.storage; | ||
if ( | ||
!( | ||
this.storage && | ||
this.storage.getItem && | ||
this.storage.setItem && | ||
this.storage.removeItem | ||
) | ||
) { | ||
throw new Error( | ||
`expected options.storage to be defined. \n--> received ${ | ||
this.storage | ||
? `object with keys: [${Object.getOwnPropertyNames( | ||
this.storage | ||
).join(', ')}]` | ||
: this.storage | ||
}` | ||
); | ||
} | ||
} | ||
@@ -86,7 +103,7 @@ | ||
options.onload || | ||
function(err) { | ||
function (err) { | ||
if (err) { | ||
throw err; | ||
} | ||
}, | ||
} | ||
); | ||
@@ -101,6 +118,10 @@ } | ||
*/ | ||
Datastore.prototype.loadDatabase = function() { | ||
Datastore.prototype.loadDatabase = function () { | ||
this.executor.push( | ||
{ this: this.persistence, fn: this.persistence.loadDatabase, arguments: arguments }, | ||
true, | ||
{ | ||
this: this.persistence, | ||
fn: this.persistence.loadDatabase, | ||
arguments: arguments, | ||
}, | ||
true | ||
); | ||
@@ -112,3 +133,3 @@ }; | ||
*/ | ||
Datastore.prototype.getAllData = function() { | ||
Datastore.prototype.getAllData = function () { | ||
return this.indexes._id.getAll(); | ||
@@ -120,6 +141,6 @@ }; | ||
*/ | ||
Datastore.prototype.resetIndexes = function(newData) { | ||
Datastore.prototype.resetIndexes = function (newData) { | ||
var self = this; | ||
Object.keys(this.indexes).forEach(function(i) { | ||
Object.keys(this.indexes).forEach(function (i) { | ||
self.indexes[i].reset(newData); | ||
@@ -139,5 +160,5 @@ }); | ||
*/ | ||
Datastore.prototype.ensureIndex = function(options, cb) { | ||
Datastore.prototype.ensureIndex = function (options, cb) { | ||
var err, | ||
callback = cb || function() {}; | ||
callback = cb || function () {}; | ||
@@ -168,8 +189,11 @@ options = options || {}; | ||
// We may want to force all options to be persisted including defaults, not just the ones passed the index creation function | ||
this.persistence.persistNewState([{ $$indexCreated: options }], function(err) { | ||
if (err) { | ||
return callback(err); | ||
this.persistence.persistNewState( | ||
[{ $$indexCreated: options }], | ||
function (err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
return callback(null); | ||
} | ||
return callback(null); | ||
}); | ||
); | ||
}; | ||
@@ -182,13 +206,16 @@ | ||
*/ | ||
Datastore.prototype.removeIndex = function(fieldName, cb) { | ||
var callback = cb || function() {}; | ||
Datastore.prototype.removeIndex = function (fieldName, cb) { | ||
var callback = cb || function () {}; | ||
delete this.indexes[fieldName]; | ||
this.persistence.persistNewState([{ $$indexRemoved: fieldName }], function(err) { | ||
if (err) { | ||
return callback(err); | ||
this.persistence.persistNewState( | ||
[{ $$indexRemoved: fieldName }], | ||
function (err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
return callback(null); | ||
} | ||
return callback(null); | ||
}); | ||
); | ||
}; | ||
@@ -199,3 +226,3 @@ | ||
*/ | ||
Datastore.prototype.addToIndexes = function(doc) { | ||
Datastore.prototype.addToIndexes = function (doc) { | ||
var i, | ||
@@ -229,6 +256,6 @@ failingIndex, | ||
*/ | ||
Datastore.prototype.removeFromIndexes = function(doc) { | ||
Datastore.prototype.removeFromIndexes = function (doc) { | ||
var self = this; | ||
Object.keys(this.indexes).forEach(function(i) { | ||
Object.keys(this.indexes).forEach(function (i) { | ||
self.indexes[i].remove(doc); | ||
@@ -243,3 +270,3 @@ }); | ||
*/ | ||
Datastore.prototype.updateIndexes = function(oldDoc, newDoc) { | ||
Datastore.prototype.updateIndexes = function (oldDoc, newDoc) { | ||
var i, | ||
@@ -283,3 +310,7 @@ failingIndex, | ||
*/ | ||
Datastore.prototype.getCandidates = function(query, dontExpireStaleDocs, callback) { | ||
Datastore.prototype.getCandidates = function ( | ||
query, | ||
dontExpireStaleDocs, | ||
callback | ||
) { | ||
var indexNames = Object.keys(this.indexes), | ||
@@ -296,6 +327,6 @@ self = this, | ||
// STEP 1: get candidates list by checking indexes from most to least frequent usecase | ||
function(cb) { | ||
function (cb) { | ||
// For a basic match | ||
usableQueryKeys = []; | ||
Object.keys(query).forEach(function(k) { | ||
Object.keys(query).forEach(function (k) { | ||
if ( | ||
@@ -313,3 +344,8 @@ typeof query[k] === 'string' || | ||
if (usableQueryKeys.length > 0) { | ||
return cb(null, self.indexes[usableQueryKeys[0]].getMatching(query[usableQueryKeys[0]])); | ||
return cb( | ||
null, | ||
self.indexes[usableQueryKeys[0]].getMatching( | ||
query[usableQueryKeys[0]] | ||
) | ||
); | ||
} | ||
@@ -319,3 +355,3 @@ | ||
usableQueryKeys = []; | ||
Object.keys(query).forEach(function(k) { | ||
Object.keys(query).forEach(function (k) { | ||
if (query[k] && query[k].hasOwnProperty('$in')) { | ||
@@ -329,3 +365,5 @@ usableQueryKeys.push(k); | ||
null, | ||
self.indexes[usableQueryKeys[0]].getMatching(query[usableQueryKeys[0]].$in), | ||
self.indexes[usableQueryKeys[0]].getMatching( | ||
query[usableQueryKeys[0]].$in | ||
) | ||
); | ||
@@ -336,3 +374,3 @@ } | ||
usableQueryKeys = []; | ||
Object.keys(query).forEach(function(k) { | ||
Object.keys(query).forEach(function (k) { | ||
if ( | ||
@@ -352,3 +390,5 @@ query[k] && | ||
null, | ||
self.indexes[usableQueryKeys[0]].getBetweenBounds(query[usableQueryKeys[0]]), | ||
self.indexes[usableQueryKeys[0]].getBetweenBounds( | ||
query[usableQueryKeys[0]] | ||
) | ||
); | ||
@@ -361,3 +401,3 @@ } | ||
// STEP 2: remove all expired documents | ||
function(docs) { | ||
function (docs) { | ||
if (dontExpireStaleDocs) { | ||
@@ -371,5 +411,5 @@ return callback(null, docs); | ||
docs.forEach(function(doc) { | ||
docs.forEach(function (doc) { | ||
var valid = true; | ||
ttlIndexesFieldNames.forEach(function(i) { | ||
ttlIndexesFieldNames.forEach(function (i) { | ||
if ( | ||
@@ -392,4 +432,4 @@ doc[i] !== undefined && | ||
expiredDocsIds, | ||
function(_id, cb) { | ||
self._remove({ _id: _id }, {}, function(err) { | ||
function (_id, cb) { | ||
self._remove({ _id: _id }, {}, function (err) { | ||
if (err) { | ||
@@ -401,5 +441,5 @@ return callback(err); | ||
}, | ||
function(err) { | ||
function (err) { | ||
return callback(null, validDocs); | ||
}, | ||
} | ||
); | ||
@@ -416,4 +456,4 @@ }, | ||
*/ | ||
Datastore.prototype._insert = function(newDoc, cb) { | ||
var callback = cb || function() {}, | ||
Datastore.prototype._insert = function (newDoc, cb) { | ||
var callback = cb || function () {}, | ||
preparedDoc; | ||
@@ -430,3 +470,3 @@ | ||
util.isArray(preparedDoc) ? preparedDoc : [preparedDoc], | ||
function(err) { | ||
function (err) { | ||
if (err) { | ||
@@ -436,3 +476,3 @@ return callback(err); | ||
return callback(null, model.deepCopy(preparedDoc)); | ||
}, | ||
} | ||
); | ||
@@ -444,3 +484,3 @@ }; | ||
*/ | ||
Datastore.prototype.createNewId = function() { | ||
Datastore.prototype.createNewId = function () { | ||
var tentativeId = customUtils.uid(16); | ||
@@ -459,3 +499,3 @@ // 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) | ||
*/ | ||
Datastore.prototype.prepareDocumentForInsertion = function(newDoc) { | ||
Datastore.prototype.prepareDocumentForInsertion = function (newDoc) { | ||
var preparedDoc, | ||
@@ -466,3 +506,3 @@ self = this; | ||
preparedDoc = []; | ||
newDoc.forEach(function(doc) { | ||
newDoc.forEach(function (doc) { | ||
preparedDoc.push(self.prepareDocumentForInsertion(doc)); | ||
@@ -492,3 +532,3 @@ }); | ||
*/ | ||
Datastore.prototype._insertInCache = function(preparedDoc) { | ||
Datastore.prototype._insertInCache = function (preparedDoc) { | ||
if (util.isArray(preparedDoc)) { | ||
@@ -506,3 +546,3 @@ this._insertMultipleDocsInCache(preparedDoc); | ||
*/ | ||
Datastore.prototype._insertMultipleDocsInCache = function(preparedDocs) { | ||
Datastore.prototype._insertMultipleDocsInCache = function (preparedDocs) { | ||
var i, failingI, error; | ||
@@ -529,3 +569,3 @@ | ||
Datastore.prototype.insert = function() { | ||
Datastore.prototype.insert = function () { | ||
this.executor.push({ this: this, fn: this._insert, arguments: arguments }); | ||
@@ -538,4 +578,4 @@ }; | ||
*/ | ||
Datastore.prototype.count = function(query, callback) { | ||
var cursor = new Cursor(this, query, function(err, docs, callback) { | ||
Datastore.prototype.count = function (query, callback) { | ||
var cursor = new Cursor(this, query, function (err, docs, callback) { | ||
if (err) { | ||
@@ -560,3 +600,3 @@ return callback(err); | ||
*/ | ||
Datastore.prototype.find = function(query, projection, callback) { | ||
Datastore.prototype.find = function (query, projection, callback) { | ||
switch (arguments.length) { | ||
@@ -575,3 +615,3 @@ case 1: | ||
var cursor = new Cursor(this, query, function(err, docs, callback) { | ||
var cursor = new Cursor(this, query, function (err, docs, callback) { | ||
var res = [], | ||
@@ -603,3 +643,3 @@ i; | ||
*/ | ||
Datastore.prototype.findOne = function(query, projection, callback) { | ||
Datastore.prototype.findOne = function (query, projection, callback) { | ||
switch (arguments.length) { | ||
@@ -618,3 +658,3 @@ case 1: | ||
var cursor = new Cursor(this, query, function(err, docs, callback) { | ||
var cursor = new Cursor(this, query, function (err, docs, callback) { | ||
if (err) { | ||
@@ -663,3 +703,3 @@ return callback(err); | ||
*/ | ||
Datastore.prototype._update = function(query, updateQuery, options, cb) { | ||
Datastore.prototype._update = function (query, updateQuery, options, cb) { | ||
var callback, | ||
@@ -676,3 +716,3 @@ self = this, | ||
} | ||
callback = cb || function() {}; | ||
callback = cb || function () {}; | ||
multi = options.multi !== undefined ? options.multi : false; | ||
@@ -682,3 +722,3 @@ upsert = options.upsert !== undefined ? options.upsert : false; | ||
async.waterfall([ | ||
function(cb) { | ||
function (cb) { | ||
// If upsert option is set, check whether we need to insert the doc | ||
@@ -691,3 +731,3 @@ if (!upsert) { | ||
var cursor = new Cursor(self, query); | ||
cursor.limit(1)._exec(function(err, docs) { | ||
cursor.limit(1)._exec(function (err, docs) { | ||
if (err) { | ||
@@ -709,3 +749,6 @@ return callback(err); | ||
try { | ||
toBeInserted = model.modify(model.deepCopy(query, true), updateQuery); | ||
toBeInserted = model.modify( | ||
model.deepCopy(query, true), | ||
updateQuery | ||
); | ||
} catch (err) { | ||
@@ -716,3 +759,3 @@ return callback(err); | ||
return self._insert(toBeInserted, function(err, newDoc) { | ||
return self._insert(toBeInserted, function (err, newDoc) { | ||
if (err) { | ||
@@ -726,3 +769,3 @@ return callback(err); | ||
}, | ||
function() { | ||
function () { | ||
// Perform the update | ||
@@ -733,3 +776,3 @@ var modifiedDoc, | ||
self.getCandidates(query, function(err, candidates) { | ||
self.getCandidates(query, function (err, candidates) { | ||
if (err) { | ||
@@ -743,3 +786,6 @@ return callback(err); | ||
for (i = 0; i < candidates.length; i += 1) { | ||
if (model.match(candidates[i], query) && (multi || numReplaced === 0)) { | ||
if ( | ||
model.match(candidates[i], query) && | ||
(multi || numReplaced === 0) | ||
) { | ||
numReplaced += 1; | ||
@@ -754,3 +800,6 @@ if (self.timestampData) { | ||
} | ||
modifications.push({ oldDoc: candidates[i], newDoc: modifiedDoc }); | ||
modifications.push({ | ||
oldDoc: candidates[i], | ||
newDoc: modifiedDoc, | ||
}); | ||
} | ||
@@ -771,3 +820,3 @@ } | ||
var updatedDocs = _.pluck(modifications, 'newDoc'); | ||
self.persistence.persistNewState(updatedDocs, function(err) { | ||
self.persistence.persistNewState(updatedDocs, function (err) { | ||
if (err) { | ||
@@ -780,3 +829,3 @@ return callback(err); | ||
var updatedDocsDC = []; | ||
updatedDocs.forEach(function(doc) { | ||
updatedDocs.forEach(function (doc) { | ||
updatedDocsDC.push(model.deepCopy(doc)); | ||
@@ -795,3 +844,3 @@ }); | ||
Datastore.prototype.update = function() { | ||
Datastore.prototype.update = function () { | ||
this.executor.push({ this: this, fn: this._update, arguments: arguments }); | ||
@@ -810,3 +859,3 @@ }; | ||
*/ | ||
Datastore.prototype._remove = function(query, options, cb) { | ||
Datastore.prototype._remove = function (query, options, cb) { | ||
var callback, | ||
@@ -822,6 +871,6 @@ self = this, | ||
} | ||
callback = cb || function() {}; | ||
callback = cb || function () {}; | ||
multi = options.multi !== undefined ? options.multi : false; | ||
this.getCandidates(query, true, function(err, candidates) { | ||
this.getCandidates(query, true, function (err, candidates) { | ||
if (err) { | ||
@@ -832,3 +881,3 @@ return callback(err); | ||
try { | ||
candidates.forEach(function(d) { | ||
candidates.forEach(function (d) { | ||
if (model.match(d, query) && (multi || numRemoved === 0)) { | ||
@@ -844,3 +893,3 @@ numRemoved += 1; | ||
self.persistence.persistNewState(removedDocs, function(err) { | ||
self.persistence.persistNewState(removedDocs, function (err) { | ||
if (err) { | ||
@@ -854,34 +903,3 @@ return callback(err); | ||
function getAsyncStorage(){ | ||
var asyncStorage; | ||
try { | ||
asyncStorage = require("@react-native-community/async-storage"); | ||
if (asyncStorage.default) { | ||
asyncStorage = asyncStorage.default; | ||
} | ||
} catch (e) { | ||
// | ||
} | ||
if (!asyncStorage) { | ||
try { | ||
asyncStorage = require('react-native').AsyncStorage; | ||
} catch (e) { | ||
// | ||
} | ||
} | ||
if (!asyncStorage) { | ||
throw new Error("'@react-native-community/async-storage' is not installed"); | ||
} | ||
if (asyncStorage.AsyncStorage) { | ||
asyncStorage = asyncStorage.AsyncStorage | ||
} | ||
return asyncStorage | ||
} | ||
Datastore.prototype.remove = function() { | ||
Datastore.prototype.remove = function () { | ||
this.executor.push({ this: this, fn: this._remove, arguments: arguments }); | ||
@@ -888,0 +906,0 @@ }; |
{ | ||
"name": "react-native-local-mongodb", | ||
"version": "3.0.2", | ||
"version": "4.0.0", | ||
"author": "Antonio Presto <antoniopresto@gmail.com>", | ||
@@ -8,2 +8,12 @@ "contributors": [ | ||
], | ||
"scripts": { | ||
"test": "NODE_ENV=test ./node_modules/.bin/jest --verbose && npm run test-db", | ||
"test-db": "./node_modules/.bin/mocha test/dbTest.test.js --reporter spec --timeout 10000" | ||
}, | ||
"main": "index", | ||
"typings": "index.d.ts", | ||
"license": "SEE LICENSE IN LICENSE", | ||
"bugs": { | ||
"url": "https://github.com/antoniopresto/react-native-local-mongodb/issues" | ||
}, | ||
"description": "react-native local mongodb storage. Embedded persistent or in memory database for react-native. API is a subset of MongoDB's and it's plenty fast.", | ||
@@ -17,3 +27,2 @@ "keywords": [ | ||
], | ||
"typings": "./lib/typings.d.ts", | ||
"homepage": "https://github.com/antoniopresto/react-native-local-mongodb", | ||
@@ -26,34 +35,25 @@ "repository": { | ||
"async": "2.6.2", | ||
"babel-preset-env": "1.6.1", | ||
"binary-search-tree": "0.2.5", | ||
"events": "1.1.0", | ||
"underscore": "1.9.1", | ||
"underscore": "^1.13.2", | ||
"util": "0.10.3" | ||
}, | ||
"peerDependencies": { | ||
"react-native": "*", | ||
"@react-native-community/async-storage": "^1.2.1" | ||
"react-native": "*" | ||
}, | ||
"devDependencies": { | ||
"@react-native-async-storage/async-storage": "1.15.13", | ||
"@types/react-native": "^0.66.9", | ||
"babel-preset-env": "1.6.1", | ||
"@types/jest": "27.0.3", | ||
"@types/node": "16.11.12", | ||
"jest": "27.4.5", | ||
"ts-jest": "27.1.1", | ||
"typescript": "4.5.4", | ||
"chai": "3.2.0", | ||
"jest": "22.3.0", | ||
"mocha": "^5.2.0", | ||
"sinon": "1.3.x" | ||
"react-native": "latest", | ||
"sinon": "1.3.x", | ||
"prettier": "2.5.1" | ||
}, | ||
"scripts": { | ||
"test": "NODE_ENV=test ./node_modules/.bin/jest --verbose && npm run test-db", | ||
"test-db": "./node_modules/.bin/mocha test/dbTest.js --reporter spec --timeout 10000" | ||
}, | ||
"jest": { | ||
"moduleNameMapper": { | ||
"react-native": "<rootDir>/config/jest/reactNativeMock.js", | ||
".*async-storage": "<rootDir>/config/jest/@react-native-community/async-storage.js" | ||
}, | ||
"testEnvironment": "node" | ||
}, | ||
"main": "index", | ||
"license": "SEE LICENSE IN LICENSE", | ||
"bugs": { | ||
"url": "https://github.com/antoniopresto/react-native-local-mongodb/issues" | ||
}, | ||
"directories": { | ||
@@ -60,0 +60,0 @@ "test": "test" |
@@ -1,2 +0,1 @@ | ||
**Embedded persistent or in memory database for react-native**. API is a subset of MongoDB's (NeDB). | ||
@@ -8,3 +7,2 @@ | ||
# | ||
> Starting with version 3.0.0 we use `@react-native-community/async-storage` as a peer pependence | ||
> Starting with version 2.0.0, the `insert`,` update`, `remove`,` find`, and `findOne` methods no longer return promises - now they have a corresponding `Async` method (insertAsync, updateAsync, etc ) | ||
@@ -23,2 +21,3 @@ # | ||
* <a href="#persistence">Persistence</a> | ||
* <a href="#using-a-custom-storage">Using a custom storage </a> | ||
* <a href="#inserting-documents">Inserting documents</a> | ||
@@ -69,4 +68,5 @@ * <a href="#finding-documents">Finding documents</a> | ||
// Type 2: Persistent datastore with manual loading | ||
var Datastore = require('react-native-local-mongodb') | ||
, db = new Datastore({ filename: 'asyncStorageKey' }); | ||
const Datastore = require('react-native-local-mongodb') | ||
, db = new Datastore({ filename: 'asyncStorageKey', storage: AsyncStorage }); | ||
db.loadDatabase(function (err) { // Callback is optional | ||
@@ -79,3 +79,3 @@ // Now commands will be executed | ||
var Datastore = require('react-native-local-mongodb') | ||
, db = new Datastore({ filename: 'asyncStorageKey', autoload: true }); | ||
, db = new Datastore({ filename: 'asyncStorageKey', storage: AsyncStorage, autoload: true }); | ||
// You can issue commands right away | ||
@@ -97,2 +97,43 @@ ``` | ||
### Using a custom Storage | ||
You can pass a custom storage in the Datastore configuration object. Your storage must be an object that matches [this interface](https://github.com/react-native-community/react-native-async-storage/blob/67ae214ad5caebc83bb21e659e898924cb27fe6e/types/index.d.ts#L19). | ||
```javascript | ||
import Datastore from 'react-native-local-mongodb'; | ||
import AsyncStorage from '@react-native-community/async-storage'; | ||
const db = new Datastore({ | ||
filename: 'asyncStorageKey', | ||
storage: AsyncStorage | ||
}); | ||
// === or === | ||
const items = {}; | ||
const db2 = new Datastore({ | ||
filename: 'asyncStorageKey', | ||
// custom storage | ||
storage: { | ||
setItem: (key, value, cb) => { | ||
items[key] = value; | ||
cb(null, value); | ||
}, | ||
getItem: (key, cb) => { | ||
const res = items[key]; | ||
cb(null, res); | ||
}, | ||
removeItem: (key, cb) => { | ||
const res = delete items[key]; | ||
cb(null, res); | ||
}, | ||
// ... | ||
}, | ||
}); | ||
``` | ||
### Inserting documents | ||
@@ -99,0 +140,0 @@ The native types are `String`, `Number`, `Boolean`, `Date` and `null`. You can also use |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
236346
2.38%6
-25%24
14.29%5655
2.46%0
-100%666
6.56%13
225%1
Infinity%+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated