mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-22 20:31:29 +03:00
142 lines
3.4 KiB
JavaScript
142 lines
3.4 KiB
JavaScript
/**
|
|
* @type {import('idb')}
|
|
*/
|
|
const idb = window.idb;
|
|
|
|
const createUniqueIndex = (() => {
|
|
let index = 0;
|
|
return () => ++index;
|
|
})();
|
|
|
|
function replaceBinary(value, binaries) {
|
|
if (value instanceof Uint8Array) {
|
|
const name = `__BINARY__${createUniqueIndex()}`;
|
|
binaries[name] = Array.from(value);
|
|
return name;
|
|
}
|
|
|
|
if (Array.isArray(value)) {
|
|
return value.map(item => replaceBinary(item, binaries));
|
|
}
|
|
|
|
if (typeof value === 'object' && value !== null) {
|
|
const replaced = {};
|
|
for (const key of Object.keys(value)) {
|
|
replaced[key] = replaceBinary(value[key], binaries);
|
|
}
|
|
return replaced;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
function recoveryBinary(value, binaries) {
|
|
if (typeof value === 'string') {
|
|
const arr = binaries[value];
|
|
if (arr) {
|
|
return new Uint8Array(arr);
|
|
}
|
|
}
|
|
|
|
if (Array.isArray(value)) {
|
|
return value.map(item => recoveryBinary(item, binaries));
|
|
}
|
|
|
|
if (typeof value === 'object' && value !== null) {
|
|
const result = {};
|
|
for (const key of Object.keys(value)) {
|
|
result[key] = recoveryBinary(value[key], binaries);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
async function readAffineDatabase() {
|
|
const idbData = [];
|
|
const binaries = {};
|
|
|
|
const databases = await indexedDB.databases();
|
|
for (const databaseInfo of databases) {
|
|
const idbDatabase = await idb.openDB(
|
|
databaseInfo.name,
|
|
databaseInfo.version
|
|
);
|
|
if (!idbDatabase) {
|
|
throw new Error('idbDatabase is null');
|
|
}
|
|
|
|
const stores = [];
|
|
const objectStoreNames = Array.from(idbDatabase.objectStoreNames);
|
|
const transaction = idbDatabase.transaction(objectStoreNames, 'readonly');
|
|
|
|
for (const storeName of objectStoreNames) {
|
|
const objectStore = transaction.objectStore(storeName);
|
|
const objectValues = await objectStore.getAll();
|
|
|
|
stores.push({
|
|
name: storeName,
|
|
keyPath: objectStore.keyPath,
|
|
values: replaceBinary(objectValues, binaries),
|
|
});
|
|
}
|
|
|
|
idbData.push({ ...databaseInfo, stores });
|
|
}
|
|
|
|
return { idbData, binaries };
|
|
}
|
|
|
|
async function writeAffineDatabase(allDatabases, binaries) {
|
|
for (const database of allDatabases) {
|
|
const idbDatabase = await idb.openDB(database.name, database.version, {
|
|
upgrade(db) {
|
|
for (const objectStore of database.stores) {
|
|
db.createObjectStore(objectStore.name, {
|
|
keyPath: objectStore.keyPath,
|
|
});
|
|
}
|
|
},
|
|
});
|
|
|
|
for (const store of database.stores) {
|
|
const transaction = idbDatabase.transaction(store.name, 'readwrite');
|
|
const objectStore = transaction.objectStore(store.name);
|
|
|
|
for (const value of store.values) {
|
|
await objectStore.add(recoveryBinary(value, binaries));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function readAffineLocalStorage() {
|
|
const data = {};
|
|
|
|
const keys = [
|
|
'jotai-workspaces',
|
|
'last_page_id',
|
|
'last_workspace_id',
|
|
'affine-local-workspace',
|
|
'is-first-open',
|
|
];
|
|
for (const key of keys) {
|
|
const value = window.localStorage.getItem(key);
|
|
data[key] = value;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
async function writeAffineLocalStorage(data) {
|
|
for (const [key, value] of Object.entries(data)) {
|
|
window.localStorage.setItem(key, value);
|
|
}
|
|
}
|
|
|
|
window.readAffineDatabase = readAffineDatabase;
|
|
window.writeAffineDatabase = writeAffineDatabase;
|
|
window.readAffineLocalStorage = readAffineLocalStorage;
|
|
window.writeAffineLocalStorage = writeAffineLocalStorage;
|