[feat] opfs storage

This commit is contained in:
kwaroran
2023-06-29 05:08:42 +09:00
parent 267cdbb448
commit 1f2e9be90f
6 changed files with 167 additions and 27 deletions

View File

@@ -0,0 +1,77 @@
import localforage from "localforage"
import { isNodeServer } from "./globalApi"
import { NodeStorage } from "./nodeStorage"
import { OpfsStorage } from "./opfsStorage"
import { alertConfirm, alertStore } from "../alert"
export class AutoStorage{
realStorage:LocalForage|NodeStorage|OpfsStorage
async setItem(key:string, value:Uint8Array) {
await this.Init()
return await this.realStorage.setItem(key, value)
}
async getItem(key:string):Promise<Buffer> {
await this.Init()
return await this.realStorage.getItem(key)
}
async keys():Promise<string[]>{
await this.Init()
return await this.realStorage.keys()
}
async removeItem(key:string){
await this.Init()
return await this.realStorage.removeItem(key)
}
private async Init(){
if(!this.realStorage){
if(isNodeServer){
console.log("using node storage")
this.realStorage = new NodeStorage()
return
}
else if(window.navigator?.storage?.getDirectory && localStorage.getItem('flag_opfs')){
console.log("using opfs storage")
const forage = localforage.createInstance({
name: "risuai"
})
const i = await forage.getItem("database/database.bin")
if((!i) || (await forage.getItem("migrated"))){
this.realStorage = new OpfsStorage()
return
}
else if(!(await forage.getItem("denied_opfs"))){
console.log("migrating")
const keys = await forage.keys()
let i = 0;
const opfs = new OpfsStorage()
for(const key of keys){
console.log(i)
alertStore.set({
type: "none",
msg: `Migrating your data...(${i}/${keys.length})`
})
await opfs.setItem(key,await forage.getItem(key))
i += 1
}
this.realStorage = opfs
await forage.setItem("migrated", true)
return
}
}
console.log("using forage storage")
this.realStorage = localforage.createInstance({
name: "risuai"
})
}
}
listItem = this.keys
}

View File

@@ -1,6 +1,5 @@
import { writeBinaryFile,BaseDirectory, readBinaryFile, exists, createDir, readDir, removeFile } from "@tauri-apps/api/fs"
import { changeFullscreen, checkNullish, findCharacterbyId, sleep } from "../util"
import localforage from 'localforage'
import { convertFileSrc, invoke } from "@tauri-apps/api/tauri"
import { v4 as uuidv4 } from 'uuid';
import { appDataDir, join } from "@tauri-apps/api/path";
@@ -12,23 +11,21 @@ import { checkOldDomain, checkUpdate } from "../update";
import { selectedCharID } from "../stores";
import { Body, ResponseType, fetch as TauriFetch } from "@tauri-apps/api/http";
import { loadPlugins } from "../plugins/plugins";
import { alertError, alertStore } from "../alert";
import { alertError } from "../alert";
import { checkDriverInit, syncDrive } from "../drive/drive";
import { hasher } from "../parser";
import { characterHubImport } from "../characterCards";
import { cloneDeep } from "lodash";
import { NodeStorage } from "./nodeStorage";
import { defaultJailbreak, defaultMainPrompt, oldJailbreak, oldMainPrompt } from "./defaultPrompts";
import { loadRisuAccountData } from "../drive/accounter";
import { decodeRisuSave, encodeRisuSave } from "./risuSave";
import { AutoStorage } from "./autoStorage";
//@ts-ignore
export const isTauri = !!window.__TAURI__
//@ts-ignore
export const isNodeServer = !!globalThis.__NODE__
export const forageStorage = isNodeServer ? new NodeStorage() : localforage.createInstance({
name: "risuai"
})
export const forageStorage = new AutoStorage()
interface fetchLog{
body:string

View File

@@ -0,0 +1,61 @@
export class OpfsStorage{
opfs:FileSystemDirectoryHandle
async setItem(key:string, value:Uint8Array) {
await this.Init()
const handle = await this.opfs.getFileHandle(Buffer.from(key, 'utf-8').toString('hex'), {
create: true
})
const stream = await handle.createWritable()
await stream.write(value)
stream.close()
}
async getItem(key:string):Promise<Buffer> {
try {
await this.Init()
const handle = await this.opfs.getFileHandle(Buffer.from(key, 'utf-8').toString('hex'), {
create: false
})
const stream = await handle.getFile();
return Buffer.from(await stream.arrayBuffer())
} catch (error) {
if(error instanceof DOMException){
if(error.name === "NotFoundError"){
return null
}
}
throw error
}
}
async keys():Promise<string[]>{
await this.Init()
let entries:string[] = []
for await (const entry of this.opfs.values()) {
entries.push(Buffer.from(entry.name, 'hex').toString('utf-8'))
}
return entries
}
async removeItem(key:string){
try {
await this.Init()
await this.opfs.removeEntry(Buffer.from(key, 'utf-8').toString('hex'))
} catch (error) {
if(error instanceof DOMException){
if(error.name === "NotFoundError"){
return null
}
}
throw error
}
}
private async Init(){
if(!this.opfs){
this.opfs = await window.navigator.storage.getDirectory()
}
}
listItem = this.keys
}