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 {
// eslint-disable-next-line @typescript-eslint/ban-types
private readonly locale: PouchDB.Database<{}> | null = null
constructor() {
try {
this.locale = new PouchDb('lite-note', {
adapter: 'indexeddb'
})
} catch (error) {
console.warn('data error', error)
}
}
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 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 data.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.generateId(prefix, key))
})
return response.rows
.map((row) => {
if ('error' in row) {
return null
}
return row.doc
})
.filter((doc) => !!doc) 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[]
}
public generateId(type?: DataType | string, id?: string) {
if (!type) {
return id || nanoid()
}
return `${type}-${id || nanoid()}`
}
}
export const data = new Data()