index.js

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