import type { RecursivePartial } from '../interfaces';
import type { IOptions, ISetOptions, IDelOptions } from './jsonCache.types';
interface IJSONCache<T> {
    set(key: string, obj: T, options: ISetOptions): Promise<any>;
    get(key: string): Promise<T | undefined>;
    get(key: string, ...fields: string[]): Promise<Partial<T> | undefined>;
    rewrite(key: string, obj: T, options?: ISetOptions): Promise<any>;
    clearAll(): Promise<any>;
    del(key: string, options?: IDelOptions): Promise<any>;
    incr(key: string, obj: RecursivePartial<T>, options?: IDelOptions): Promise<any>;
}
/**
 * JSONCache eases the difficulties in storing a JSON in redis.
 *
 *  It stores the JSON in hashset for simpler get and set of required
 * fields. It also allows you to override/set specific fields in
 * the JSON without rewriting the whole JSON tree. Which means that it
 * is literally possible to `Object.deepAssign()`.
 *
 *   Everytime you store an object, JSONCache would store two hashset
 * in Redis, one for data and the other for type information. This helps
 * during retrieval of data, to restore the type of data which was originally
 * provided. All these workaround are needed because Redis DOES NOT support
 * any other data type apart from String.
 *
 * Well the easiest way is to store an object in Redis is
 * JSON.stringify(obj) and store the stringified result.
 * But this can cause issue when the obj is
 * too huge or when you would want to retrieve only specific fields
 * from the JSON but do not want to parse the whole JSON.
 *   Also note that this method would end up in returing all the
 * fields as strings and you would have no clue to identify the type of
 * field.
 */
export default class JSONCache<T = any> implements IJSONCache<T> {
    private options;
    private redisClientInt;
    private flattener;
    /**
     * Intializes JSONCache instance
     * @param redisClient RedisClient instance(Preferred ioredis - cient).
     *      It supports any redisClient instance that has
     *      `'hmset' | 'hmget' | 'hgetall' | 'expire' | 'del' | 'keys'`
     *      methods implemented
     * @param options Options for controlling the prefix
     */
    constructor(redisClient: any, options?: IOptions);
    /**
     * Flattens the given json object and
     * stores it in Redis hashset
     *
     * @param key Redis key
     * @param obj JSON object to be stored
     * @param options
     */
    set(key: string, obj: T, options?: ISetOptions): Promise<any>;
    /**
     * Retrieves the hashset from redis and
     * unflattens it back to the original Object
     *
     * @param key Redis key
     * @param fields List of fields to be retreived from redis.
     *    This helps reduce network latency incase only a few fields are
     *    needed.
     *
     * @returns request object from the cache
     */
    get(key: string): Promise<T | undefined>;
    get(key: string, ...fields: string[]): Promise<Partial<T> | undefined>;
    /**
     * Replace the entire hashset for the given key
     *
     * @param key Redis key
     * @param obj JSON Object of type T
     */
    rewrite(key: string, obj: T, options?: ISetOptions): Promise<any>;
    /**
     * Removes/deletes all the keys in the JSON Cache,
     * having the prefix.
     */
    clearAll(): Promise<any>;
    /**
     * Removes the given key from Redis
     *
     * Please use this method instead of
     * directly using `redis.del` as this method
     * ensures that even the corresponding type info
     * is removed. It also ensures that prefix is
     * added to key, ensuring no other key is
     * removed unintentionally
     *
     * @param key Redis key
     */
    del(key: string, options?: IDelOptions): Promise<any>;
    /**
     * Increments the value of a variable in the JSON
     * Note: You can increment multiple variables in the
     * same command (Internally it will split it into multiple
     * commands on the RedisDB)
     *
     * @example
     * ```JS
     * await jsonCache.incr(key, {messages: 10, profile: {age: 1}})
     * ```
     *
     * @param key Redis Cache key
     * @param obj Partial object specifying the path to the required
     *              variable along with value
     */
    incr(key: string, obj: RecursivePartial<T>, options?: IDelOptions): Promise<any>;
    /******************
     * PRIVATE METHODS
     ******************/
    private getKeysToBeRemoved;
    /**
     * Returns the redis storage key for storing data
     * by prefixing custom string, such that it
     * doesn't collide with other keys in usage
     *
     * @param key Storage key
     */
    private getKey;
    /**
     * Returns the redis storage key for storing
     * corresponding types by prefixing custom string,
     * such that it doesn't collide with other keys
     * in usage
     *
     * @param key Storage key
     */
    private getTypeKey;
    /**
     * Will add Set commands to the given array
     * This logic was separated to remove code duplication
     * in set & rewrite methods
     *
     * @param key Storage key
     * @param flattened Flattened object containing data & typeInfo
     * @param commands List of commands to which set commands has to be appended
     * @param expire Redis Key expiry
     */
    private addSetCommands;
    private execTransactionCommands;
    private execCommand;
}
export {};
