import { expose } from "comlink" import { nanoid } from "nanoid" import indexedDb from "pouchdb-adapter-indexeddb" import PouchDb from "pouchdb-browser" import { DataType } from "./DataType.enum" import { Model } from "./models/Model" PouchDb.plugin(indexedDb) interface GetAllParams { prefix?: string includeDocs?: boolean includeAttachments?: boolean keys?: string[] } class Data { // oxlint-disable-next-line typescript/ban-types private readonly locale: PouchDB.Database<{}> | null = null constructor() { try { this.locale = new PouchDb("remanso", { adapter: "indexeddb" }) } catch (error) { console.warn("data error", error) } } private buildId(type?: DataType | string, id?: string): string { if (!type) return id || nanoid() return `${type}-${id || nanoid()}` } public async add
(model: Model
): Promise { try { const result = await this.locale?.put(model) return result?.ok ?? false } catch (error) { console.warn(error) return false } } public async update
>( model: T ): Promise { try { if (!model._id) { const result = await this.locale?.put(model) return result?.ok ?? false } const oldModel = await this.get(model._id) if (oldModel) { const result = await this.locale?.put({ ...oldModel, ...model }) return result?.ok ?? false } const result = await this.locale?.put(model) return result?.ok ?? false } catch (error) { console.warn(error) return false } } public async remove(id: string): Promise { try { const doc = await this.get(id) if (!doc) { return false } const result = await this.locale?.put({ ...doc, _deleted: true }) return result?.ok ?? false } catch { return false } } public async get
>( id: string ): Promise { try { return ((await this.locale?.get(id)) as T) || null } catch { return null } } public async getOrCreate
>( id: string, initialValue: T ): Promise { const element = await this.get(id) if (element) { return element } await this.add
({ ...initialValue, _id: id }) return this.getOrCreate(id, initialValue) } public async getAll
>({ prefix, includeDocs = true, includeAttachments = false, keys = [] }: GetAllParams): Promise { if (!this.locale) { return [] } if (keys.length) { const response = await this.locale.allDocs({ include_docs: includeDocs, attachments: includeAttachments, keys: keys.map((key) => this.buildId(prefix, key)) }) if (includeDocs) { return response.rows .map((row) => { if ("error" in row) return null return row.doc }) .filter(Boolean) as T[] } else { return response.rows .map((row) => { if ("error" in row) return null return { _id: row.id } }) .filter(Boolean) as T[] } } const response = await this.locale.allDocs({ include_docs: includeDocs, attachments: includeAttachments, startkey: prefix ? prefix : undefined, endkey: prefix ? `${prefix}\ufff0` : undefined }) return response.rows.map((row) => row.doc) as T[] } } expose(new Data())