pouchdb-adapter-indexeddb
Advanced tools
Comparing version 7.2.2 to 7.3.0
@@ -5,4 +5,4 @@ import { btoa, readAsBinaryString, binaryStringToBlobOrBuffer } from 'pouchdb-binary-utils'; | ||
import { uuid, filterChange, changesHandler } from 'pouchdb-utils'; | ||
import { createError, IDB_ERROR, MISSING_DOC, REV_CONFLICT, MISSING_STUB, BAD_ARG } from 'pouchdb-errors'; | ||
import { latest, winningRev, merge, collectConflicts, traverseRevTree } from 'pouchdb-merge'; | ||
import { createError, IDB_ERROR, MISSING_DOC, REV_CONFLICT, MISSING_STUB, BAD_ARG, UNKNOWN_ERROR } from 'pouchdb-errors'; | ||
import { latest, winningRev, merge, compactTree, collectConflicts, traverseRevTree } from 'pouchdb-merge'; | ||
@@ -13,2 +13,15 @@ var IDB_NULL = Number.MIN_SAFE_INTEGER; | ||
// These are the same as bellow but without the global flag | ||
// we want to use RegExp.test because it's really fast, but the global flag | ||
// makes the regex const stateful (seriously) as it walked through all instances | ||
var TEST_KEY_INVALID = /^[^a-zA-Z_$]|[^a-zA-Z0-9_$]+/; | ||
var TEST_PATH_INVALID = /\\.|(^|\.)[^a-zA-Z_$]|[^a-zA-Z0-9_$.]+/; | ||
function needsSanitise(name, isPath) { | ||
if (isPath) { | ||
return TEST_PATH_INVALID.test(name); | ||
} else { | ||
return TEST_KEY_INVALID.test(name); | ||
} | ||
} | ||
// | ||
@@ -30,19 +43,7 @@ // IndexedDB only allows valid JS names in its index paths, whereas JSON allows | ||
// | ||
var KEY_INVALID = /[^a-zA-Z0-9_$]+|(^[^a-zA-Z_$])/g; | ||
var PATH_INVALID = /(\\.)|[^a-zA-Z0-9_$.]+|(^[^a-zA-Z_$])/g; | ||
var KEY_INVALID = new RegExp(TEST_KEY_INVALID.source, 'g'); | ||
var PATH_INVALID = new RegExp(TEST_PATH_INVALID.source, 'g'); | ||
var SLASH = '\\'.charCodeAt(0); | ||
const IS_DOT = '.'.charCodeAt(0); | ||
// These are the same as above but without the global flag | ||
// we want to use RegExp.test because it's really fast, but the global flag | ||
// makes the regex const stateful (seriously) as it walked through all instances | ||
var TEST_KEY_INVALID = /[^a-zA-Z0-9_$]+|(^[^a-zA-Z_$])/; | ||
var TEST_PATH_INVALID = /(\\.)|[^a-zA-Z0-9_$.]+|(^[^a-zA-Z_$])/; | ||
function needsSanitise(name, isPath) { | ||
if (isPath) { | ||
return TEST_PATH_INVALID.test(name); | ||
} else { | ||
return TEST_KEY_INVALID.test(name); | ||
} | ||
} | ||
function sanitise(name, isPath) { | ||
@@ -59,7 +60,10 @@ var correctCharacters = function (match) { | ||
// Your index path would be "foo.bar\.baz". | ||
if (code === SLASH && isPath) { | ||
if (code === IS_DOT && isPath && i === 0) { | ||
good += '.'; | ||
} else if (code === SLASH && isPath) { | ||
continue; | ||
} else { | ||
good += '_c' + code + '_'; | ||
} | ||
good += '_c' + code + '_'; | ||
} | ||
@@ -304,2 +308,7 @@ return good; | ||
throw new Error('Incorrect adapter: you should specify the "idb" adapter to open this DB'); | ||
} else if (e.oldVersion === 0 && e.newVersion < versionMultiplier) { | ||
// Firefox still creates the database with version=1 even if we throw, | ||
// so we need to be sure to destroy the empty database before throwing | ||
indexedDB.deleteDatabase(opts.name); | ||
throw new Error('Database was deleted while open'); | ||
} | ||
@@ -338,2 +347,9 @@ | ||
idb.onclose = function () { | ||
console.log('Database was made stale, closing handle'); | ||
if (opts.name in openDatabases) { | ||
openDatabases[opts.name].versionchanged = true; | ||
} | ||
}; | ||
var metadata = {id: META_STORE}; | ||
@@ -474,2 +490,3 @@ var txn = idb.transaction([META_STORE], 'readwrite'); | ||
var rewriteEnabled = dbOpts.name.indexOf("-mrview-") === -1; | ||
const autoCompaction = dbOpts.auto_compaction; | ||
@@ -515,2 +532,10 @@ // We only need to track 1 revision for local documents | ||
function revHasAttachment(doc, rev, digest) { | ||
return doc.revs[rev] && | ||
doc.revs[rev].data._attachments && | ||
Object.values(doc.revs[rev].data._attachments).find(function (att) { | ||
return att.digest === digest; | ||
}); | ||
} | ||
function processDocs(txn, docs, oldDocs) { | ||
@@ -522,3 +547,3 @@ | ||
// The first document write cannot be a deletion | ||
if ('was_delete' in opts && !(oldDocs.hasOwnProperty(doc.id))) { | ||
if ('was_delete' in opts && !(Object.prototype.hasOwnProperty.call(oldDocs, doc.id))) { | ||
newDoc = createError(MISSING_DOC, 'deleted'); | ||
@@ -528,3 +553,3 @@ | ||
} else if (opts.new_edits && | ||
!oldDocs.hasOwnProperty(doc.id) && | ||
!Object.prototype.hasOwnProperty.call(oldDocs, doc.id) && | ||
rootIsMissing(doc)) { | ||
@@ -534,3 +559,3 @@ newDoc = createError(REV_CONFLICT); | ||
// Update the existing document | ||
} else if (oldDocs.hasOwnProperty(doc.id)) { | ||
} else if (Object.prototype.hasOwnProperty.call(oldDocs, doc.id)) { | ||
newDoc = update(txn, doc, oldDocs[doc.id]); | ||
@@ -636,2 +661,4 @@ // The update can be rejected if it is an update to an existing | ||
const isNewDoc = doc.isNewDoc; | ||
if (rewriteEnabled) { | ||
@@ -675,5 +702,15 @@ // doc.data is what we index, so we need to clone and rewrite it, and clean | ||
// delete their data | ||
if (doc.stemmedRevs) { | ||
doc.stemmedRevs.forEach(function (rev) { delete doc.revs[rev]; }); | ||
let revsToDelete = doc.stemmedRevs || []; | ||
if (autoCompaction && !isNewDoc) { | ||
const result = compactTree(doc); | ||
if (result.length) { | ||
revsToDelete = revsToDelete.concat(result); | ||
} | ||
} | ||
if (revsToDelete.length) { | ||
revsToDelete.forEach(function (rev) { delete doc.revs[rev]; }); | ||
} | ||
delete doc.stemmedRevs; | ||
@@ -697,3 +734,5 @@ | ||
doc.attachments[attachment.digest].revs[writtenRev] = true; | ||
if (revHasAttachment(doc, writtenRev, attachment.digest)) { | ||
doc.attachments[attachment.digest].revs[writtenRev] = true; | ||
} | ||
@@ -822,3 +861,3 @@ } else { | ||
txn.onabort = function () { | ||
callback(error); | ||
callback(error || createError(UNKNOWN_ERROR, 'transaction was aborted')); | ||
}; | ||
@@ -1315,3 +1354,3 @@ txn.ontimeout = idbError(callback); | ||
return IDB_COLLATE_LO; | ||
} else if (k.hasOwnProperty(COUCH_COLLATE_HI)) { | ||
} else if (Object.prototype.hasOwnProperty.call(k, COUCH_COLLATE_HI)) { | ||
return IDB_COLLATE_HI; | ||
@@ -1501,2 +1540,6 @@ } | ||
if (dbOpts.view_adapter) { | ||
console.log('Please note that the indexeddb adapter manages _find indexes itself, therefore it is not using your specified view_adapter'); | ||
} | ||
var api = this; | ||
@@ -1514,3 +1557,3 @@ var metadata = {}; | ||
}).catch(function (err) { | ||
var last = args.unshift(); | ||
var last = args.pop(); | ||
if (typeof last === 'function') { | ||
@@ -1529,10 +1572,7 @@ last(err); | ||
return new Promise(function (resolve, reject) { | ||
setup(openDatabases, api, dbOpts).then(function (res) { | ||
metadata = res.metadata; | ||
args.unshift(res.idb); | ||
return setup(openDatabases, api, dbOpts).then(function (res) { | ||
metadata = res.metadata; | ||
args.unshift(res.idb); | ||
return fun.apply(api, args); | ||
}).then(resolve) | ||
.catch(reject); | ||
return fun.apply(api, args); | ||
}); | ||
@@ -1555,4 +1595,2 @@ }; | ||
txn.txn = res.idb.transaction(stores, mode); | ||
args.unshift(txn); | ||
fun.apply(api, args); | ||
}).catch(function (err) { | ||
@@ -1562,2 +1600,5 @@ console.error('Failed to establish transaction safely'); | ||
txn.error = err; | ||
}).then(function () { | ||
args.unshift(txn); | ||
fun.apply(api, args); | ||
}); | ||
@@ -1564,0 +1605,0 @@ }; |
113
lib/index.js
@@ -14,2 +14,15 @@ 'use strict'; | ||
// These are the same as bellow but without the global flag | ||
// we want to use RegExp.test because it's really fast, but the global flag | ||
// makes the regex const stateful (seriously) as it walked through all instances | ||
var TEST_KEY_INVALID = /^[^a-zA-Z_$]|[^a-zA-Z0-9_$]+/; | ||
var TEST_PATH_INVALID = /\\.|(^|\.)[^a-zA-Z_$]|[^a-zA-Z0-9_$.]+/; | ||
function needsSanitise(name, isPath) { | ||
if (isPath) { | ||
return TEST_PATH_INVALID.test(name); | ||
} else { | ||
return TEST_KEY_INVALID.test(name); | ||
} | ||
} | ||
// | ||
@@ -31,19 +44,7 @@ // IndexedDB only allows valid JS names in its index paths, whereas JSON allows | ||
// | ||
var KEY_INVALID = /[^a-zA-Z0-9_$]+|(^[^a-zA-Z_$])/g; | ||
var PATH_INVALID = /(\\.)|[^a-zA-Z0-9_$.]+|(^[^a-zA-Z_$])/g; | ||
var KEY_INVALID = new RegExp(TEST_KEY_INVALID.source, 'g'); | ||
var PATH_INVALID = new RegExp(TEST_PATH_INVALID.source, 'g'); | ||
var SLASH = '\\'.charCodeAt(0); | ||
const IS_DOT = '.'.charCodeAt(0); | ||
// These are the same as above but without the global flag | ||
// we want to use RegExp.test because it's really fast, but the global flag | ||
// makes the regex const stateful (seriously) as it walked through all instances | ||
var TEST_KEY_INVALID = /[^a-zA-Z0-9_$]+|(^[^a-zA-Z_$])/; | ||
var TEST_PATH_INVALID = /(\\.)|[^a-zA-Z0-9_$.]+|(^[^a-zA-Z_$])/; | ||
function needsSanitise(name, isPath) { | ||
if (isPath) { | ||
return TEST_PATH_INVALID.test(name); | ||
} else { | ||
return TEST_KEY_INVALID.test(name); | ||
} | ||
} | ||
function sanitise(name, isPath) { | ||
@@ -60,7 +61,10 @@ var correctCharacters = function (match) { | ||
// Your index path would be "foo.bar\.baz". | ||
if (code === SLASH && isPath) { | ||
if (code === IS_DOT && isPath && i === 0) { | ||
good += '.'; | ||
} else if (code === SLASH && isPath) { | ||
continue; | ||
} else { | ||
good += '_c' + code + '_'; | ||
} | ||
good += '_c' + code + '_'; | ||
} | ||
@@ -305,2 +309,7 @@ return good; | ||
throw new Error('Incorrect adapter: you should specify the "idb" adapter to open this DB'); | ||
} else if (e.oldVersion === 0 && e.newVersion < versionMultiplier) { | ||
// Firefox still creates the database with version=1 even if we throw, | ||
// so we need to be sure to destroy the empty database before throwing | ||
indexedDB.deleteDatabase(opts.name); | ||
throw new Error('Database was deleted while open'); | ||
} | ||
@@ -339,2 +348,9 @@ | ||
idb.onclose = function () { | ||
console.log('Database was made stale, closing handle'); | ||
if (opts.name in openDatabases) { | ||
openDatabases[opts.name].versionchanged = true; | ||
} | ||
}; | ||
var metadata = {id: META_STORE}; | ||
@@ -475,2 +491,3 @@ var txn = idb.transaction([META_STORE], 'readwrite'); | ||
var rewriteEnabled = dbOpts.name.indexOf("-mrview-") === -1; | ||
const autoCompaction = dbOpts.auto_compaction; | ||
@@ -516,2 +533,10 @@ // We only need to track 1 revision for local documents | ||
function revHasAttachment(doc, rev, digest) { | ||
return doc.revs[rev] && | ||
doc.revs[rev].data._attachments && | ||
Object.values(doc.revs[rev].data._attachments).find(function (att) { | ||
return att.digest === digest; | ||
}); | ||
} | ||
function processDocs(txn, docs, oldDocs) { | ||
@@ -523,3 +548,3 @@ | ||
// The first document write cannot be a deletion | ||
if ('was_delete' in opts && !(oldDocs.hasOwnProperty(doc.id))) { | ||
if ('was_delete' in opts && !(Object.prototype.hasOwnProperty.call(oldDocs, doc.id))) { | ||
newDoc = pouchdbErrors.createError(pouchdbErrors.MISSING_DOC, 'deleted'); | ||
@@ -529,3 +554,3 @@ | ||
} else if (opts.new_edits && | ||
!oldDocs.hasOwnProperty(doc.id) && | ||
!Object.prototype.hasOwnProperty.call(oldDocs, doc.id) && | ||
rootIsMissing(doc)) { | ||
@@ -535,3 +560,3 @@ newDoc = pouchdbErrors.createError(pouchdbErrors.REV_CONFLICT); | ||
// Update the existing document | ||
} else if (oldDocs.hasOwnProperty(doc.id)) { | ||
} else if (Object.prototype.hasOwnProperty.call(oldDocs, doc.id)) { | ||
newDoc = update(txn, doc, oldDocs[doc.id]); | ||
@@ -637,2 +662,4 @@ // The update can be rejected if it is an update to an existing | ||
const isNewDoc = doc.isNewDoc; | ||
if (rewriteEnabled) { | ||
@@ -676,5 +703,15 @@ // doc.data is what we index, so we need to clone and rewrite it, and clean | ||
// delete their data | ||
if (doc.stemmedRevs) { | ||
doc.stemmedRevs.forEach(function (rev) { delete doc.revs[rev]; }); | ||
let revsToDelete = doc.stemmedRevs || []; | ||
if (autoCompaction && !isNewDoc) { | ||
const result = pouchdbMerge.compactTree(doc); | ||
if (result.length) { | ||
revsToDelete = revsToDelete.concat(result); | ||
} | ||
} | ||
if (revsToDelete.length) { | ||
revsToDelete.forEach(function (rev) { delete doc.revs[rev]; }); | ||
} | ||
delete doc.stemmedRevs; | ||
@@ -698,3 +735,5 @@ | ||
doc.attachments[attachment.digest].revs[writtenRev] = true; | ||
if (revHasAttachment(doc, writtenRev, attachment.digest)) { | ||
doc.attachments[attachment.digest].revs[writtenRev] = true; | ||
} | ||
@@ -823,3 +862,3 @@ } else { | ||
txn.onabort = function () { | ||
callback(error); | ||
callback(error || pouchdbErrors.createError(pouchdbErrors.UNKNOWN_ERROR, 'transaction was aborted')); | ||
}; | ||
@@ -1316,3 +1355,3 @@ txn.ontimeout = idbError(callback); | ||
return IDB_COLLATE_LO; | ||
} else if (k.hasOwnProperty(COUCH_COLLATE_HI)) { | ||
} else if (Object.prototype.hasOwnProperty.call(k, COUCH_COLLATE_HI)) { | ||
return IDB_COLLATE_HI; | ||
@@ -1502,2 +1541,6 @@ } | ||
if (dbOpts.view_adapter) { | ||
console.log('Please note that the indexeddb adapter manages _find indexes itself, therefore it is not using your specified view_adapter'); | ||
} | ||
var api = this; | ||
@@ -1515,3 +1558,3 @@ var metadata = {}; | ||
}).catch(function (err) { | ||
var last = args.unshift(); | ||
var last = args.pop(); | ||
if (typeof last === 'function') { | ||
@@ -1530,10 +1573,7 @@ last(err); | ||
return new Promise(function (resolve, reject) { | ||
setup(openDatabases, api, dbOpts).then(function (res) { | ||
metadata = res.metadata; | ||
args.unshift(res.idb); | ||
return setup(openDatabases, api, dbOpts).then(function (res) { | ||
metadata = res.metadata; | ||
args.unshift(res.idb); | ||
return fun.apply(api, args); | ||
}).then(resolve) | ||
.catch(reject); | ||
return fun.apply(api, args); | ||
}); | ||
@@ -1556,4 +1596,2 @@ }; | ||
txn.txn = res.idb.transaction(stores, mode); | ||
args.unshift(txn); | ||
fun.apply(api, args); | ||
}).catch(function (err) { | ||
@@ -1563,2 +1601,5 @@ console.error('Failed to establish transaction safely'); | ||
txn.error = err; | ||
}).then(function () { | ||
args.unshift(txn); | ||
fun.apply(api, args); | ||
}); | ||
@@ -1565,0 +1606,0 @@ }; |
{ | ||
"name": "pouchdb-adapter-indexeddb", | ||
"version": "7.2.2", | ||
"version": "7.3.0", | ||
"description": "PouchDB adapter using IndexedDB as its data store.", | ||
@@ -9,11 +9,15 @@ "main": "./lib/index.js", | ||
"license": "Apache-2.0", | ||
"repository": "https://github.com/pouchdb/pouchdb", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/pouchdb/pouchdb.git", | ||
"directory": "packages/node_modules/pouchdb-adapter-indexeddb" | ||
}, | ||
"jsnext:main": "./lib/index.es.js", | ||
"dependencies": { | ||
"pouchdb-adapter-utils": "7.2.2", | ||
"pouchdb-binary-utils": "7.2.2", | ||
"pouchdb-errors": "7.2.2", | ||
"pouchdb-md5": "7.2.2", | ||
"pouchdb-merge": "7.2.2", | ||
"pouchdb-utils": "7.2.2" | ||
"pouchdb-adapter-utils": "7.3.0", | ||
"pouchdb-binary-utils": "7.3.0", | ||
"pouchdb-errors": "7.3.0", | ||
"pouchdb-md5": "7.3.0", | ||
"pouchdb-merge": "7.3.0", | ||
"pouchdb-utils": "7.3.0" | ||
}, | ||
@@ -20,0 +24,0 @@ "module": "./lib/index.es.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Unpopular package
QualityThis package is not very popular.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
109444
2813
0
950
1
+ Addedbuffer-from@1.1.2(transitive)
+ Addedpouchdb-adapter-utils@7.3.0(transitive)
+ Addedpouchdb-binary-utils@7.3.0(transitive)
+ Addedpouchdb-collections@7.3.0(transitive)
+ Addedpouchdb-errors@7.3.0(transitive)
+ Addedpouchdb-md5@7.3.0(transitive)
+ Addedpouchdb-merge@7.3.0(transitive)
+ Addedpouchdb-utils@7.3.0(transitive)
+ Addedspark-md5@3.0.2(transitive)
+ Addeduuid@8.3.2(transitive)
- Removedbuffer-from@1.1.1(transitive)
- Removedpouchdb-adapter-utils@7.2.2(transitive)
- Removedpouchdb-binary-utils@7.2.2(transitive)
- Removedpouchdb-collections@7.2.2(transitive)
- Removedpouchdb-errors@7.2.2(transitive)
- Removedpouchdb-md5@7.2.2(transitive)
- Removedpouchdb-merge@7.2.2(transitive)
- Removedpouchdb-utils@7.2.2(transitive)
- Removedspark-md5@3.0.1(transitive)
- Removeduuid@8.1.0(transitive)
Updatedpouchdb-adapter-utils@7.3.0
Updatedpouchdb-binary-utils@7.3.0
Updatedpouchdb-errors@7.3.0
Updatedpouchdb-md5@7.3.0
Updatedpouchdb-merge@7.3.0
Updatedpouchdb-utils@7.3.0