<commit_before>import Keyv from 'keyv';
import { homedir } from 'os';

const path = `sqlite://${homedir()}/.fotingo_config/cache.sqlite3`;
const keyv = new Keyv(path);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type PromiseFunction = (...args: any[]) => Promise<any>;

type Cacheable = (
  target: any,
  propertyKey: string | symbol,
  descriptor: TypedPropertyDescriptor<PromiseFunction>,
) => TypedPropertyDescriptor<PromiseFunction>;

const isCacheDisabled = process.env.FOTINGO_DISABLE_CACHE !== undefined;

/**
 * Decorator that caches the output of the decorated function
 * in an external data source (SQLite DB) so it can be
 * accessed across multiple executions
 * Caching is based on the function input, the specified
 * prefix and the number of minutes the data is supposed to be
 * cached
 */
export function cacheable({
  getPrefix,
  minutes,
}: {
  getPrefix?: () => string;
  minutes?: number;
}): Cacheable {
  return (
    target: any,
    propertyKey: string | symbol,
    descriptor: TypedPropertyDescriptor<PromiseFunction>,
  ): TypedPropertyDescriptor<PromiseFunction> => {
    const method = descriptor.value;
    if (typeof method !== 'function') {
      throw new TypeError(
        `@cacheable decorator can only be applied to methods not: ${typeof method}`,
      );
    }

    const cachedFn: PromiseFunction = async function (...args) {
      if (isCacheDisabled) {
        return method.call(this, ...args);
      }
      const prefix = getPrefix ? getPrefix.call(this, ...args) : '';
      const keyArgs = args.length > 0 ? `_${args.map((val) => JSON.stringify(val)).join('_')}` : '';
      const key = `${prefix}${target.constructor.name}_${String(propertyKey)}${keyArgs}`;
      const cachedValue = await keyv.get(key);
      if (cachedValue) {
        return Promise.resolve(cachedValue);
      }
      const result = await method.call(this, ...args);
      await keyv.set(key, result, minutes ? minutes * 60 * 1000 : undefined);<commit_msg>chore(cacheable): allow to use Object type<commit_after>import Keyv from 'keyv';
import { homedir } from 'os';

const path = `sqlite://${homedir()}/.fotingo_config/cache.sqlite3`;
const keyv = new Keyv(path);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type PromiseFunction = (...args: any[]) => Promise<any>;

type Cacheable = (
  // eslint-disable-next-line @typescript-eslint/ban-types
  target: Object,
  propertyKey: string | symbol,
  descriptor: TypedPropertyDescriptor<PromiseFunction>,
) => TypedPropertyDescriptor<PromiseFunction>;

const isCacheDisabled = process.env.FOTINGO_DISABLE_CACHE !== undefined;

/**
 * Decorator that caches the output of the decorated function
 * in an external data source (SQLite DB) so it can be
 * accessed across multiple executions
 * Caching is based on the function input, the specified
 * prefix and the number of minutes the data is supposed to be
 * cached
 */
export function cacheable({
  getPrefix,
  minutes,
}: {
  getPrefix?: () => string;
  minutes?: number;
}): Cacheable {
  return (
    // eslint-disable-next-line @typescript-eslint/ban-types
    target: Object,
    propertyKey: string | symbol,
    descriptor: TypedPropertyDescriptor<PromiseFunction>,
  ): TypedPropertyDescriptor<PromiseFunction> => {
    const method = descriptor.value;
    if (typeof method !== 'function') {
      throw new TypeError(
        `@cacheable decorator can only be applied to methods not: ${typeof method}`,
      );
    }

    const cachedFn: PromiseFunction = async function (...args) {
      if (isCacheDisabled) {
        return method.call(this, ...args);
      }
      const prefix = getPrefix ? getPrefix.call(this, ...args) : '';
      const keyArgs = args.length > 0 ? `_${args.map((val) => JSON.stringify(val)).join('_')}` : '';
      const key = `${prefix}${target.constructor.name}_${String(propertyKey)}${keyArgs}`;
      const cachedValue = await keyv.get(key);
      if (cachedValue) {
        return Promise.resolve(cachedValue);
      }
      const result = await method.call(this, ...args);
      await keyv.set(key, result, minutes ? minutes * 60 * 1000 : undefined);
{'fraction_non_alphanumeric': 0.13363833373464964, 'fraction_numerical': 0.003852636648206116, 'mean_word_length': 3.646532438478747, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7278081', 'n_tokens_mistral': 1221, 'n_tokens_neox': 1214, 'n_words': 344}