[feat] opfs storage
This commit is contained in:
77
src/ts/storage/autoStorage.ts
Normal file
77
src/ts/storage/autoStorage.ts
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
61
src/ts/storage/opfsStorage.ts
Normal file
61
src/ts/storage/opfsStorage.ts
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user