import {reduxTools, utils} from "@yoronsoft/js-utils"; import AsyncStorage from "@react-native-async-storage/async-storage"; import {IStorage, IStorageArray, IStorageData, IStorageDataParams, StorageInitParams, StorageType} from "./storage"; class Storage implements IStorage { readonly type: StorageType = { get: "get", set: "set", getJson: "getJson", setJson: "setJson" }; init(params?: StorageInitParams[]): void { params = params || []; if (params.length > 0) params.map((item) => { if (!item.name) return console.error("storage.init 未发现 name", item); if (!item.type) return console.error("storage.init 未发现 type", item); reduxTools.create(item.name, item.value); switch (item.type) { case this.type.get: this.get(item.name).then(data => { if (data) reduxTools.update(item.name, data); }); break; case this.type.getJson: this.getJson(item.name).then(data => { if (data) reduxTools.update(item.name, data); }); break; case this.type.set: this.set(item.name, item.value); break; case this.type.setJson: this.setJson(item.name, item.value); break; } }); } get(name: string): Promise { return new Promise(resolve => { AsyncStorage.getItem(name).then(res => resolve(res === null ? "" : res)); }); } async getJson(name: string): Promise { const data = await this.get(name); return data.length ? JSON.parse(data) : undefined; } remove(name: string): void { AsyncStorage.removeItem(name).then(); } set(name: string, value: string): void { AsyncStorage.setItem(name, value).then(() => { }); } setJson(name: string, value: T): void { if (typeof value !== "object") value = {} as T; AsyncStorage.setItem(name, JSON.stringify(value)).then(); } } class StorageData implements IStorageData { readonly params: IStorageDataParams; constructor(params: IStorageDataParams) { if (typeof params.hasStorage !== "boolean") params.hasStorage = false; if (typeof params.name === "undefined") params.name = "default"; this.params = params; } add(params: T): T { return this.update(params); } get(): T { return reduxTools.get(this.params.name); } redux(data: T): void { if (this.get()) reduxTools.update(this.params.name, data); else reduxTools.create(this.params.name, data); } remove(): void { reduxTools.remove(this.params.name); if (this.params.hasStorage) storage.remove(this.params.name); } storage(data: T): void { if (data) storage.setJson(this.params.name, data as T); } update(params: T): T { const res: any = params ?? {}; const data: any = this.get() ?? {} as T; for (let val in res) { if (res.hasOwnProperty(val)) { data[val] = res[val]; } } this.redux(data); if (this.params.hasStorage) this.storage(data); return data; } } class StorageArray implements IStorageArray { readonly params: IStorageDataParams; constructor(params: IStorageDataParams) { if (typeof params.hasStorage !== "boolean") params.hasStorage = false; if (typeof params.name === "undefined") params.name = "default"; this.params = params; } add(data: T, isFirst?: boolean): T { const list = this.query() ?? []; const id = `${this.params.name}-${new Date().getTime()}-${utils.toRandom()}`; const params = {id, ...data}; if (isFirst) list.unshift(params); else list.push(params); this.redux(list); if (this.params.hasStorage) this.storage(list); return params; } addList(list: T[], isFirst?: boolean): T[] { const queryList = this.query(); let arr: any[] = []; if (list.length) list.map((item: any) => { const id = item.id ? item.id : `${this.params.name}-${new Date().getTime()}-${utils.toRandom()}`; const params = {id, ...item}; arr.push(params); }); let result: T[]; if (isFirst) result = arr.concat(queryList); else result = queryList.concat(arr); return result; } addAll(list: T[]): T[] { this.redux(list); if (this.params.hasStorage) this.storage(list); return this.query(); } delete(id: string): T[] { return this.deleteByIds([id]); } deleteByIds(ids: string[]): T[] { const list = this.query() ?? []; if (ids.length) ids.map(item => { const index = list.findIndex((m: any) => m.id === item); if (index >= 0) list.splice(index, 1); }); this.redux(list); if (this.params.hasStorage) this.storage(list); return this.query(); } get(id: string): T { const list = this.query() ?? []; return list.find((m: any) => m.id === id) as T; } getByParams(params: T): T { const list = this.query() ?? []; return list.find(m => { for (let name in params) { const item = params[name]; if (m[name] !== item) return false; } return true; }) as T; } query(): T[] { return reduxTools.get(this.params.name); } queryByParams(params: T): T[] { const list = this.query() ?? []; return list.filter(m => { for (let name in params) { const item = params[name]; if (m[name] !== item) return false; } return true; }); } remove(): T[] { reduxTools.update(this.params.name, []); if (this.params.hasStorage) storage.setJson(this.params.name, []); return this.query(); } update(id: string, data: T): T { const res: any = data ?? {}; const list = this.query() ?? []; const item: any = list.find((m: any) => m.id === id) ?? {} as T; for (let name in res) { if (res.hasOwnProperty(name)) { item[name] = res[name]; } } this.redux(list); if (this.params.hasStorage) this.storage(list); return item; } updateByParams(params: T, data: T): T[] { const res: any = data ?? {}; const list = this.queryByParams(params) ?? []; if (list.length) list.map((item: any) => { for (let name in res) { if (res.hasOwnProperty(name)) { item[name] = res[name]; } } }); const query = this.query(); this.redux(query); if (this.params.hasStorage) this.storage(query); return query; } storage(data: T[]): void { if (data) storage.setJson(this.params.name, data); } redux(data: T[]): void { if (this.query()) reduxTools.update(this.params.name, data); else reduxTools.create(this.params.name, data); } } const storage: IStorage = new Storage(); export default storage; export { StorageData, StorageArray }; export type { IStorage, IStorageArray, IStorageData, IStorageDataParams, StorageInitParams, StorageType };