85 lines
3.1 KiB
Markdown
85 lines
3.1 KiB
Markdown
# 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 blob to be saved in the pouchdb document. The returned
|
|
blob should be a smaller *sentry* blob with just enough information needed to fetch the full version
|
|
that is being proxied. `stringToBlob` is provided to make this process easier for simple string
|
|
identifier cases. Alternatively, you can pass the original attachment through if you do not want it
|
|
to be proxied.
|
|
|
|
When an attachment is requested, the document attached blob (returned from `save`) will be provided
|
|
to a custom `getFn` function to be converted into desired document. `blobToString` is provided to
|
|
make this easier for simple string identifier cases.
|
|
|
|
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. In this case, the document blob will be removed from document
|
|
(effectively orphaning the proxied attachment until it is cleaned asynchronously).
|
|
|
|
## Example
|
|
|
|
To create an attachment proxy, supply an object to the proxy wrapper with the three handler
|
|
functions.
|
|
|
|
```js
|
|
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);
|
|
```
|