2.6 KiB
PouchDB Attachment Proxy
PouchDB Attachment Proxy is a PouchDB plugin that intercepts and allows you to redirect document attachments in a PouchDB database. The intention is to use the PouchDB API to manage all attachment metadata without having the raw data bogging down your PouchDB database.
Overview
Attachment Proxy works by intercepting attachments bound for the pouchdb backend and passing them to
a custom save function that will return a sentry blob to be saved in the pouchdb document.
When an attachment is requested, the sentry blob will be provided to a custom getFn function to be
converted into desired document.
Similar to getFn, the sentry blob is provided to remove when an attachment or its containing
document is deleted.
Each function is expected to be asynchronous and the database will not continue its operation until
the proxy function completes to ensure data integrity. It may be desirable to for the remove
function to delay attachment cleanup. The proxy blob will be removed from document (effectively
orphaning the proxied attachment until it is cleaned).
Example
To create an attachment proxy, supply an object to the proxy wrapper with the three handler functions.
import {
PouchDBAttachmentProxy,
SENTRY_MIMETYPE,
blobToString,
stringToBlob
} from 'pouchdb-attachmentproxy';
const dataUrlToBlob = data => {
const [header, b64str] = data.split(';base64,');
const byteCharacters = atob(b64str);
const byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
return new Blob([byteArray], { type: header.substr(5) });
};
const LocalStorageExampleAdapter = PouchDBAttachmentProxy({
getFn: async function getAttachment(blob) {
const id = await blobToString(blob);
return dataUrlToBlob(localStorage[id]);
},
remove: async function removeAttachment(blob) {
const id = await blobToString(blob);
delete localStorage[id];
},
save: async function saveAttachment(blob) {
let id;
while (!id || localStorage[id] !== undefined) {
id = '' + Math.ceil(Math.random() * 100000);
}
// placeholder to prevent a race condition
localStorage[id] = true;
return new Promise(resolve => {
const reader = new FileReader();
reader.onloadend = function() {
localStorage[id] = reader.result;
// The returned blob must have the SENTRY_MIMETYPE mime_type in
// order to be proxied to `getFn` and `remove`.
resolve(stringToBlob(id, SENTRY_MIMETYPE));
};
reader.readAsDataURL(blob);
});
}
});
const ProxiedPouch = PouchDB.plugin(LocalStorageExampleAdapter);