2023-04-05 20:40:17 +01:00
|
|
|
import { StorageBackend } from "@types";
|
|
|
|
|
import { MMKVManager, FileManager } from "@lib/native";
|
2023-12-17 10:09:12 +08:00
|
|
|
import { ReactNative as RN } from "@metro/common";
|
|
|
|
|
|
|
|
|
|
const ILLEGAL_CHARS_REGEX = /[<>:"\/\\|?*]/g;
|
2023-02-06 08:48:55 +01:00
|
|
|
|
2023-12-17 10:09:12 +08:00
|
|
|
const filePathFixer = (file: string): string => RN.Platform.select({
|
|
|
|
|
default: file,
|
|
|
|
|
ios: FileManager.saveFileToGallery ? file : `Documents/${file}`,
|
2023-02-06 08:48:55 +01:00
|
|
|
});
|
|
|
|
|
|
2023-12-17 10:09:12 +08:00
|
|
|
const getMMKVPath = (name: string): string => {
|
|
|
|
|
if (ILLEGAL_CHARS_REGEX.test(name)) {
|
|
|
|
|
// Replace forbidden characters with hyphens
|
|
|
|
|
name = name.replace(ILLEGAL_CHARS_REGEX, '-').replace(/-+/g, '-');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return `vd_mmkv/${name}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const purgeStorage = async (store: string) => {
|
|
|
|
|
if (await MMKVManager.getItem(store)) {
|
|
|
|
|
MMKVManager.removeItem(store);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mmkvPath = getMMKVPath(store);
|
|
|
|
|
if (await FileManager.fileExists(`${FileManager.getConstants().DocumentsDirPath}/${mmkvPath}`)) {
|
|
|
|
|
await FileManager.removeFile?.("documents", mmkvPath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const createMMKVBackend = (store: string) => {
|
|
|
|
|
const mmkvPath = getMMKVPath(store);
|
|
|
|
|
return createFileBackend(mmkvPath, (async () => {
|
2024-02-08 14:17:58 +08:00
|
|
|
const path = `${FileManager.getConstants().DocumentsDirPath}/${mmkvPath}`;
|
|
|
|
|
if (await FileManager.fileExists(path)) return;
|
2023-12-17 10:09:12 +08:00
|
|
|
|
2024-02-08 14:17:58 +08:00
|
|
|
let oldData = await MMKVManager.getItem(store) ?? "{}";
|
2023-12-17 10:09:12 +08:00
|
|
|
|
2024-02-08 14:17:58 +08:00
|
|
|
// From the testing on Android, it seems to return this if the data is too large
|
|
|
|
|
if (oldData === "!!LARGE_VALUE!!") {
|
|
|
|
|
const cachePath = `${FileManager.getConstants().CacheDirPath}/mmkv/${store}`;
|
|
|
|
|
if (await FileManager.fileExists(cachePath)) {
|
|
|
|
|
oldData = await FileManager.readFile(cachePath, "utf8")
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`${store}: Experienced data loss :(`);
|
|
|
|
|
oldData = "{}";
|
2023-12-17 10:09:12 +08:00
|
|
|
}
|
2024-02-08 14:17:58 +08:00
|
|
|
}
|
2023-12-17 10:09:12 +08:00
|
|
|
|
2024-02-08 14:17:58 +08:00
|
|
|
try {
|
|
|
|
|
JSON.parse(oldData);
|
|
|
|
|
} catch {
|
|
|
|
|
console.error(`${store} had an unparseable data while migrating`);
|
|
|
|
|
oldData = "{}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await FileManager.writeFile("documents", filePathFixer(mmkvPath), oldData, "utf8");
|
|
|
|
|
if (await MMKVManager.getItem(store) !== null) {
|
|
|
|
|
MMKVManager.removeItem(store);
|
|
|
|
|
console.log(`Successfully migrated ${store} store from MMKV storage to fs`);
|
2023-12-17 10:09:12 +08:00
|
|
|
}
|
|
|
|
|
})());
|
|
|
|
|
}
|
2023-03-17 21:58:37 +00:00
|
|
|
|
2023-12-17 10:09:12 +08:00
|
|
|
export const createFileBackend = (file: string, migratePromise?: Promise<void>): StorageBackend => {
|
2023-02-26 01:34:16 +01:00
|
|
|
return {
|
|
|
|
|
get: async () => {
|
2023-12-17 10:09:12 +08:00
|
|
|
await migratePromise;
|
2023-04-05 20:40:17 +01:00
|
|
|
const path = `${FileManager.getConstants().DocumentsDirPath}/${file}`;
|
2024-02-08 14:17:58 +08:00
|
|
|
if (await FileManager.fileExists(path)) {
|
|
|
|
|
const content = await FileManager.readFile(path, "utf8");
|
|
|
|
|
try {
|
|
|
|
|
return JSON.parse(content);
|
|
|
|
|
} catch {
|
|
|
|
|
// Corrupted content, ignore
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await FileManager.writeFile("documents", filePathFixer(file), "{}", "utf8");
|
2023-04-05 20:40:17 +01:00
|
|
|
return JSON.parse(await FileManager.readFile(path, "utf8"));
|
2023-02-26 01:34:16 +01:00
|
|
|
},
|
2023-12-17 10:09:12 +08:00
|
|
|
set: async (data) => {
|
|
|
|
|
await migratePromise;
|
|
|
|
|
await FileManager.writeFile("documents", filePathFixer(file), JSON.stringify(data), "utf8");
|
|
|
|
|
}
|
2023-02-26 01:34:16 +01:00
|
|
|
};
|
2023-04-05 22:18:22 +02:00
|
|
|
};
|