Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
72 lines
2.7 KiB
JavaScript
72 lines
2.7 KiB
JavaScript
export class DataStoresIndexedDB {
|
|
constructor(factory, keyRange, uuid) {
|
|
Object.assign(this, { factory, keyRange, uuid });
|
|
}
|
|
open() {
|
|
return (this.database ||= new Promise((resolve, reject) => {
|
|
const request = this.factory.open('vulpes-datastores-v1', 1);
|
|
request.onupgradeneeded = () => {
|
|
request.result.createObjectStore('values');
|
|
request.result.createObjectStore('revisions');
|
|
};
|
|
request.onerror = () => reject(request.error);
|
|
request.onsuccess = () => {
|
|
request.result.onversionchange = () => request.result.close();
|
|
resolve(request.result);
|
|
};
|
|
}));
|
|
}
|
|
async run(key, operation, args) {
|
|
const db = await this.open();
|
|
return new Promise((resolve, reject) => {
|
|
const write = ['add', 'put', 'remove', 'clear'].includes(operation);
|
|
const tx = db.transaction(['values', 'revisions'], write ? 'readwrite' : 'readonly');
|
|
const store = tx.objectStore('values'),
|
|
revisions = tx.objectStore('revisions');
|
|
const range = this.keyRange.bound([key], [key, []]);
|
|
let value,
|
|
revisionId = '',
|
|
entries = [];
|
|
tx.onabort = () => reject(tx.error || new Error('TRANSACTION_ABORTED'));
|
|
tx.onerror = () => {};
|
|
tx.oncomplete = () => resolve({ value, revisionId });
|
|
if (operation === 'get') {
|
|
value = [];
|
|
args.forEach((id, index) => {
|
|
store.get([key, id]).onsuccess = (event) => {
|
|
if (args.length === 1) value = event.target.result;
|
|
else value[index] = event.target.result;
|
|
};
|
|
});
|
|
} else if (operation === 'snapshot') {
|
|
revisions.get(key).onsuccess = (event) => {
|
|
revisionId = event.target.result || '';
|
|
};
|
|
store.openCursor(range).onsuccess = (event) => {
|
|
const cursor = event.target.result;
|
|
if (cursor) {
|
|
entries.push({ id: cursor.key[1], data: cursor.value });
|
|
cursor.continue();
|
|
} else value = { revisionId, entries };
|
|
};
|
|
} else if (operation === 'length') {
|
|
store.count(range).onsuccess = (event) => {
|
|
value = event.target.result;
|
|
};
|
|
} else if (write) {
|
|
revisionId = this.uuid();
|
|
revisions.put(revisionId, key);
|
|
if (operation === 'clear') store.delete(range);
|
|
else if (operation === 'remove') {
|
|
store.count([key, args[0]]).onsuccess = (event) => {
|
|
value = event.target.result > 0;
|
|
};
|
|
store.delete([key, args[0]]);
|
|
} else {
|
|
value = args[1] === undefined ? this.uuid() : args[1];
|
|
store[operation === 'add' ? 'add' : 'put'](args[0], [key, value]);
|
|
}
|
|
} else tx.abort();
|
|
});
|
|
}
|
|
}
|