Make AttProxy handle storing/loading the storage mapping object
This simplifies storage plugins as simple get/remove/save objects.
This commit is contained in:
parent
060da481a7
commit
a8bab0c4fa
@ -1,9 +1,8 @@
|
|||||||
import core from 'pouchdb-core';
|
import core from 'pouchdb-core';
|
||||||
import { PouchDBAttachmentProxy } from '../utils/attachmentProxy.js';
|
import { PouchDBAttachmentProxy } from '../utils/attachmentProxy.js';
|
||||||
import { deepAssign, blobToString } from '../utils/conversion.js';
|
import { deepAssign, blobToArrayBuffer } from '../utils/conversion.js';
|
||||||
import { prop, computed, stream } from 'frptools';
|
import { prop, computed, stream } from 'frptools';
|
||||||
|
import { sha1 } from '../utils/crypto.js';
|
||||||
const STORAGE_MIMETYPE = 'application/b2storagemap';
|
|
||||||
|
|
||||||
export const B2Adapter = function(b2apikey, b2secret, b2bucket) {
|
export const B2Adapter = function(b2apikey, b2secret, b2bucket) {
|
||||||
const authDate = prop(null);
|
const authDate = prop(null);
|
||||||
@ -72,62 +71,47 @@ export const B2Adapter = function(b2apikey, b2secret, b2bucket) {
|
|||||||
return s.downloadUrl + '/b2api/v1/b2_download_file_by_id?fileId=' + fileId;
|
return s.downloadUrl + '/b2api/v1/b2_download_file_by_id?fileId=' + fileId;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readStorageMap(blob) {
|
|
||||||
return JSON.parse(await blobToString(blob));
|
|
||||||
}
|
|
||||||
|
|
||||||
return PouchDBAttachmentProxy({
|
return PouchDBAttachmentProxy({
|
||||||
getFn: async function getAttachment(docId, attName, att) {
|
getFn: async function getAttachment(obj) {
|
||||||
if (att.type !== STORAGE_MIMETYPE) {
|
const res = await fetch(await downloadUrl(obj.fileId), {
|
||||||
return att;
|
|
||||||
}
|
|
||||||
const storagemap = await readStorageMap(att);
|
|
||||||
const res = await fetch(await downloadUrl(storagemap.fileId), {
|
|
||||||
headers: await headers()
|
headers: await headers()
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.blob();
|
return res.blob();
|
||||||
},
|
},
|
||||||
remove: async function removeAttachment(docId, attName, rev, att) {
|
remove: async function removeAttachment(obj) {
|
||||||
const s = await session();
|
const s = await session();
|
||||||
const storagemap = await readStorageMap(att);
|
|
||||||
return fetch('/api/v1/remove_file', {
|
return fetch('/api/v1/remove_file', {
|
||||||
headers: await headers(),
|
headers: await headers(),
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
fileName: storagemap.fileName,
|
fileName: obj.fileName,
|
||||||
fileId: storagemap.fileId
|
fileId: obj.fileId
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
save: async function saveAttachment(doc, attName, obj) {
|
save: async function saveAttachment(blob) {
|
||||||
try {
|
try {
|
||||||
const uploadAuth = await uploadAuthorization();
|
const uploadAuth = await uploadAuthorization();
|
||||||
|
const digest = await sha1(await blobToArrayBuffer(blob));
|
||||||
const res = await fetch(uploadAuth.uploadUrl, {
|
const res = await fetch(uploadAuth.uploadUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: await headers({
|
headers: await headers({
|
||||||
Authorization: uploadAuth.authorizationToken,
|
Authorization: uploadAuth.authorizationToken,
|
||||||
'X-Bz-File-Name': encodeURIComponent(obj.data.name),
|
'X-Bz-File-Name': encodeURIComponent(blob.name),
|
||||||
'Content-Type': obj.data.type,
|
'Content-Type': blob.type,
|
||||||
'Content-Length': obj.data.size,
|
'Content-Length': blob.size,
|
||||||
'X-Bz-Content-Sha1': doc.digest
|
'X-Bz-Content-Sha1': digest
|
||||||
}),
|
}),
|
||||||
body: obj.data
|
body: blob
|
||||||
});
|
|
||||||
const resData = await res.json();
|
|
||||||
deepAssign(doc, {
|
|
||||||
_attachments: {
|
|
||||||
[attName]: {
|
|
||||||
content_type: STORAGE_MIMETYPE,
|
|
||||||
data: btoa(JSON.stringify(resData))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
id: await res.json()
|
||||||
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Error:', e);
|
|
||||||
return { ok: false, error: e };
|
return { ok: false, error: e };
|
||||||
}
|
}
|
||||||
return { ok: true };
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,9 +1,16 @@
|
|||||||
import core from 'pouchdb-core';
|
import core from 'pouchdb-core';
|
||||||
import { backgroundTask } from '../utils/event.js';
|
import { backgroundTask } from '../utils/event.js';
|
||||||
|
import { deepAssign, blobToString } from '../utils/conversion.js';
|
||||||
|
import { error, log } from '../services/console.js';
|
||||||
|
|
||||||
const pouchBulkDocs = core.prototype.bulkDocs;
|
const pouchBulkDocs = core.prototype.bulkDocs;
|
||||||
const pouchGetAttachment = core.prototype.getAttachment;
|
const pouchGetAttachment = core.prototype.getAttachment;
|
||||||
const pouchRemoveAttachment = core.prototype.removeAttachment;
|
const pouchRemoveAttachment = core.prototype.removeAttachment;
|
||||||
|
const STORAGE_MIMETYPE = 'application/b2storagemap';
|
||||||
|
|
||||||
|
async function readStorageMap(blob) {
|
||||||
|
return JSON.parse(await blobToString(blob));
|
||||||
|
}
|
||||||
|
|
||||||
export function PouchDBAttachmentProxy({ save, getFn, remove }) {
|
export function PouchDBAttachmentProxy({ save, getFn, remove }) {
|
||||||
const override = {};
|
const override = {};
|
||||||
@ -11,18 +18,22 @@ export function PouchDBAttachmentProxy({ save, getFn, remove }) {
|
|||||||
if (getFn) {
|
if (getFn) {
|
||||||
override.getAttachment = async function getAttachment(...args) {
|
override.getAttachment = async function getAttachment(...args) {
|
||||||
const att = await pouchGetAttachment.apply(this, args);
|
const att = await pouchGetAttachment.apply(this, args);
|
||||||
return await getFn.apply(this, args.concat(att));
|
if (att.type !== STORAGE_MIMETYPE) {
|
||||||
|
return att;
|
||||||
|
}
|
||||||
|
return await getFn.call(this, await readStorageMap(att));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remove) {
|
if (remove) {
|
||||||
override.removeAttachment = async function removeAttachment(...args) {
|
override.removeAttachment = async function removeAttachment(...args) {
|
||||||
const att = await pouchGetAttachment.apply(this, args);
|
const att = await pouchGetAttachment.apply(this, args);
|
||||||
try {
|
if (att.type === STORAGE_MIMETYPE) {
|
||||||
await remove.apply(this, args.concat(att));
|
try {
|
||||||
} catch (e) {
|
await remove.call(this, await readStorageMap(att));
|
||||||
console.log('Error:', e);
|
} catch (e) {
|
||||||
return;
|
error(`Failed to remove attachment ${args}`, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return await pouchRemoveAttachment.apply(this, args);
|
return await pouchRemoveAttachment.apply(this, args);
|
||||||
};
|
};
|
||||||
@ -30,8 +41,6 @@ export function PouchDBAttachmentProxy({ save, getFn, remove }) {
|
|||||||
|
|
||||||
if (save || remove) {
|
if (save || remove) {
|
||||||
override.bulkDocs = function bulkDocs(...args) {
|
override.bulkDocs = function bulkDocs(...args) {
|
||||||
console.log('fad', ...args);
|
|
||||||
|
|
||||||
let docs;
|
let docs;
|
||||||
if (Array.isArray(args[0])) {
|
if (Array.isArray(args[0])) {
|
||||||
docs = args[0];
|
docs = args[0];
|
||||||
@ -49,8 +58,8 @@ export function PouchDBAttachmentProxy({ save, getFn, remove }) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (f._attachments && f._attachments.data.data instanceof Blob) {
|
if (f._attachments && f._attachments.data.data instanceof Blob) {
|
||||||
console.log(`Saving File ${f._id} attachment`);
|
log(`Saving File ${f._id} attachment`);
|
||||||
attachments.push([f, 'data', f._attachments.data]);
|
attachments.push([f, 'data', f._attachments.data.data]);
|
||||||
delete f._attachments.data;
|
delete f._attachments.data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -58,7 +67,22 @@ export function PouchDBAttachmentProxy({ save, getFn, remove }) {
|
|||||||
deletedFiles.forEach(cleanupFiles);
|
deletedFiles.forEach(cleanupFiles);
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
attachments.map(([doc, attName, obj]) => save.call(this, doc, attName, obj))
|
attachments.map(([doc, attName, blob]) =>
|
||||||
|
save.call(this, blob).then(resData => {
|
||||||
|
if (resData && resData.ok) {
|
||||||
|
deepAssign(doc, {
|
||||||
|
_attachments: {
|
||||||
|
[attName]: {
|
||||||
|
content_type: STORAGE_MIMETYPE,
|
||||||
|
data: btoa(JSON.stringify(resData.id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
error(`Failed to save attachment ${doc._id}[${attName}]`, resData);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
).then(() => {
|
).then(() => {
|
||||||
return pouchBulkDocs.call(this, ...args);
|
return pouchBulkDocs.call(this, ...args);
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user