import Keyv from 'keyv'
import Store from './lib/store.js'
import { removeExpired } from './lib/helper.js'
import config from './lib/config.js'
import { get as getRs, set as setRs, clear as clearRs, remove as removeRs } from './lib/result-set.js'
import { get as getGeneric, set as setGeneric, clear as clearGeneric, remove as removeGeneric } from './lib/generic.js'
import { get as getFn, set as setFn, clear as clearFn, remove as removeFn } from './lib/function.js'
/**
* Plugin factory
*
* **Never** call this function directly!!! It's only-meant to be called by the {@link https://ardhi.github.io/bajo|Bajo framework} during plugin initialization.
*
* @param {string} pkgName - NPM package name
* @returns {BajoCache} - Returns the BajoCache class
*/
async function factory (pkgName) {
const me = this
/**
* BajoCache class definition.
*
* This class is used to manage caching in the Bajo framework. It provides methods to set, get, clear, and remove cached items,
* as well as a method to synchronize cache with the underlying data source.
*
* It supports caching for result sets, generic items, and function results, with configurable time-to-live (TTL)
* and expiration handling.
*
* @class
*/
class BajoCache extends this.app.baseClass.Base {
constructor () {
super(pkgName, me.app)
/**
* Configuration object.
* @type {BajoCache.TConfig}
*/
this.config = config
/**
* Array container for cached functions
*
* @type {Array}
*/
this.fnCache = []
}
/**
* Start the plugin.
*
* @async
* @method
* @returns {Promise<void>}
*/
start = async () => {
const store = this.app.dobo ? new Store(this) : undefined
this.instance = new Keyv({ store })
const fn = removeExpired.bind(this)
setInterval(fn, this.config.removeExpiredDur)
}
/**
* Clear cached items.
*
* @async
* @method
* @param {Object} [opts={}] - Options for clearing cache
* @returns {Promise<void>}
*/
clear = async (opts = {}) => {
if (opts.model) return await clearRs.call(this, opts)
if (opts.key && opts.key.startsWith('fn:')) return await clearFn.call(this, opts)
return await clearGeneric.call(this, opts)
}
/**
* Get cached items.
*
* @async
* @method
* @param {Object} [opts={}] - Options for getting cache
* @returns {Promise<any>} - Returns the cached item or undefined if not found
*/
get = async (opts = {}) => {
if (opts.model && (opts.filter || opts.id)) return await getRs.call(this, opts)
if (opts.key && opts.key.startsWith('fn:')) return await getFn.call(this, opts)
return await getGeneric.call(this, opts)
}
/**
* Remove cached items.
*
* @async
* @method
* @param {Object} [opts={}] - Options for removing cache
* @returns {Promise<void>}
*/
remove = async (opts = {}) => {
if (opts.model && (opts.filter || opts.id)) return await removeRs.call(this, opts)
if (opts.key && opts.key.startsWith('fn:')) return await removeFn.call(this, opts)
return await removeGeneric.call(this, opts)
}
/**
* Set cached items.
*
* @async
* @method
* @param {Object} [opts={}] - Options for setting cache
* @returns {Promise<void>}
*/
set = async (opts = {}) => {
if (opts.model && (opts.filter || opts.id)) return await setRs.call(this, opts)
if (opts.key && opts.key.startsWith('fn:')) return await setFn.call(this, opts)
return await setGeneric.call(this, opts)
}
/**
* Sync cached items.
*
* @async
* @method
* @param {Object} [opts={}] - Options for syncing cache
* @returns {Promise<any>} - Returns the cached item or the value set
*/
sync = async (opts) => {
const item = await this.get(opts)
if (item) return item
await this.set(opts)
return opts.value
}
}
return BajoCache
}
export default factory