mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 13:25:12 +00:00
168 lines
5.0 KiB
TypeScript
168 lines
5.0 KiB
TypeScript
import type { IDBPDatabase } from 'idb';
|
|
import { openDB } from 'idb';
|
|
import { mergeUpdates } from 'yjs';
|
|
|
|
import type { BlockSuiteBinaryDB, OldYjsDB, UpdateMessage } from './shared';
|
|
import { dbVersion, DEFAULT_DB_NAME, upgradeDB } from './shared';
|
|
|
|
let allDb: IDBDatabaseInfo[];
|
|
|
|
async function databaseExists(name: string): Promise<boolean> {
|
|
return new Promise(resolve => {
|
|
const req = indexedDB.open(name);
|
|
let existed = true;
|
|
req.onsuccess = function () {
|
|
req.result.close();
|
|
if (!existed) {
|
|
indexedDB.deleteDatabase(name);
|
|
}
|
|
resolve(existed);
|
|
};
|
|
req.onupgradeneeded = function () {
|
|
existed = false;
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* try to migrate the old database to the new database
|
|
* this function will be removed in the future
|
|
* since we don't need to support the old database
|
|
*/
|
|
export async function tryMigrate(
|
|
db: IDBPDatabase<BlockSuiteBinaryDB>,
|
|
id: string,
|
|
dbName = DEFAULT_DB_NAME
|
|
) {
|
|
do {
|
|
if (!allDb || localStorage.getItem(`${dbName}-migration`) !== 'true') {
|
|
try {
|
|
allDb = await indexedDB.databases();
|
|
} catch {
|
|
// in firefox, `indexedDB.databases` is not existed
|
|
if (await databaseExists(id)) {
|
|
await openDB<IDBPDatabase<OldYjsDB>>(id, 1).then(async oldDB => {
|
|
if (!oldDB.objectStoreNames.contains('updates')) {
|
|
return;
|
|
}
|
|
const t = oldDB
|
|
.transaction('updates', 'readonly')
|
|
.objectStore('updates');
|
|
const updates = await t.getAll();
|
|
if (
|
|
!Array.isArray(updates) ||
|
|
!updates.every(update => update instanceof Uint8Array)
|
|
) {
|
|
return;
|
|
}
|
|
const update = mergeUpdates(updates);
|
|
const workspaceTransaction = db
|
|
.transaction('workspace', 'readwrite')
|
|
.objectStore('workspace');
|
|
const data = await workspaceTransaction.get(id);
|
|
if (!data) {
|
|
console.log('upgrading the database');
|
|
await workspaceTransaction.put({
|
|
id,
|
|
updates: [
|
|
{
|
|
timestamp: Date.now(),
|
|
update,
|
|
},
|
|
],
|
|
});
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
// run the migration
|
|
await Promise.all(
|
|
allDb &&
|
|
allDb.map(meta => {
|
|
if (meta.name && meta.version === 1) {
|
|
const name = meta.name;
|
|
const version = meta.version;
|
|
return openDB<IDBPDatabase<OldYjsDB>>(name, version).then(
|
|
async oldDB => {
|
|
if (!oldDB.objectStoreNames.contains('updates')) {
|
|
return;
|
|
}
|
|
const t = oldDB
|
|
.transaction('updates', 'readonly')
|
|
.objectStore('updates');
|
|
const updates = await t.getAll();
|
|
if (
|
|
!Array.isArray(updates) ||
|
|
!updates.every(update => update instanceof Uint8Array)
|
|
) {
|
|
return;
|
|
}
|
|
const update = mergeUpdates(updates);
|
|
const workspaceTransaction = db
|
|
.transaction('workspace', 'readwrite')
|
|
.objectStore('workspace');
|
|
const data = await workspaceTransaction.get(name);
|
|
if (!data) {
|
|
console.log('upgrading the database');
|
|
await workspaceTransaction.put({
|
|
id: name,
|
|
updates: [
|
|
{
|
|
timestamp: Date.now(),
|
|
update,
|
|
},
|
|
],
|
|
});
|
|
}
|
|
}
|
|
);
|
|
}
|
|
return void 0;
|
|
})
|
|
);
|
|
localStorage.setItem(`${dbName}-migration`, 'true');
|
|
break;
|
|
}
|
|
// eslint-disable-next-line no-constant-condition
|
|
} while (false);
|
|
}
|
|
|
|
export async function downloadBinary(
|
|
guid: string,
|
|
dbName = DEFAULT_DB_NAME
|
|
): Promise<UpdateMessage['update'] | false> {
|
|
const dbPromise = openDB<BlockSuiteBinaryDB>(dbName, dbVersion, {
|
|
upgrade: upgradeDB,
|
|
});
|
|
const db = await dbPromise;
|
|
const t = db.transaction('workspace', 'readonly').objectStore('workspace');
|
|
const doc = await t.get(guid);
|
|
if (!doc) {
|
|
return false;
|
|
} else {
|
|
return mergeUpdates(doc.updates.map(({ update }) => update));
|
|
}
|
|
}
|
|
|
|
export async function overwriteBinary(
|
|
guid: string,
|
|
update: UpdateMessage['update'],
|
|
dbName = DEFAULT_DB_NAME
|
|
) {
|
|
const dbPromise = openDB<BlockSuiteBinaryDB>(dbName, dbVersion, {
|
|
upgrade: upgradeDB,
|
|
});
|
|
const db = await dbPromise;
|
|
const t = db.transaction('workspace', 'readwrite').objectStore('workspace');
|
|
await t.put({
|
|
id: guid,
|
|
updates: [
|
|
{
|
|
timestamp: Date.now(),
|
|
update,
|
|
},
|
|
],
|
|
});
|
|
}
|