/**
 * Configuration options for the unique value generation process.
 *
 * @template Value The type of the value being processed for uniqueness.
 */
type IOptions<Value> = {
    /**
     * Optional store to keep track of unique values.
     */
    store?: Set<unknown>;
    /**
     * The maximum number of retries allowed to generate a unique value before throwing an error. Defaults to 50.
     */
    maxRetries?: number;
    /**
     * The maximum time allowed (in milliseconds) for generating a unique value before throwing an error. Defaults to 50ms.
     */
    maxTime?: number;
    /**
     * A list of values to be excluded from the result set. When a stringifier is provided, the list will be stringified.
     */
    exclude?: Value[];
    /**
     * A function to stringify a result value before storing it in the set and checking for uniqueness. Defaults to {@link JSON.stringify}.
     */
    stringifier?: (value: Value) => string;
};
/**
 * Creates a function that generates unique values based on the passed function `fn`.
 *
 * @template Fn The type of the function passed to generate values.
 *
 * @param {Fn} fn - The function to generate values
 * @param {IOptions<Fn>} [options={}] - Optional configuration for controlling the uniqueness generation process.
 * @returns {(args: Parameters<Fn>) => ReturnType<Fn>} A new function that generates unique values based on `fn`.
 *
 * @throws {Error} Throws an error if the max retries or max time is exceeded.
 *
 * @example
 * ```ts
 * import { uniqueFactory } from '@dpaskhin/unique';
 * import { faker } from '@faker-js/faker';
 *
 * // Example of generating unique user objects
 * const createUniqueUser = uniqueFactory(() => ({
 *   firstName: faker.person.firstName(),
 *   lastName: faker.person.lastName(),
 *   age: faker.number.int({ min: 18, max: 100 }),
 * }));
 *
 * // Outputs a structurally unique user
 * console.log(createUniqueUser());
 * ```
 */
declare function uniqueFactory<Fn extends (...args: any[]) => any>(fn: Fn, options?: IOptions<ReturnType<Fn>>): (...args: Parameters<Fn>) => ReturnType<Fn>;
/**
 * A global store to track unique values across the application.
 *
 * @example
 * ```ts
 * import { GLOBAL_STORE, unique } from '@dpaskhin/unique';
 *
 * // Uses GLOBAL_STORE
 * const uniqueRandomValue1 = unique(Math.random);
 * // Uses GLOBAL_STORE
 * const uniqueRandomValue2 = unique(Math.random);
 *
 * // Outputs two unique values
 * console.log(uniqueRandomValue1, uniqueRandomValue2);
 *
 * // Clear the global store when needed
 * GLOBAL_STORE.clear();
 * ```
 */
declare const GLOBAL_STORE: Set<unknown>;
/**
 * Generates a unique value using the provided function `fn` that takes no arguments.
 *
 * **Note:** The global store is used by default and shared across the application.
 * For isolated usage, provide a custom `store` in the options.
 *
 * **Best Practice:** Use a custom store to avoid shared state and unexpected results.
 *
 * @template Fn The type of the function that generates values without arguments.
 *
 * @param {Fn} fn - The function to generate values. This function does not accept any arguments.
 * @param {never[]} [args] - No arguments are passed to functions that do not accept arguments.
 * @param {IOptions<ReturnType<Fn>>} [options] - Optional configuration for controlling the uniqueness generation process.
 * @returns {ReturnType<Fn>} The unique value generated by the function `fn`.
 *
 * @throws {Error} Throws an error if the max retries or max time is exceeded.
 *
 * @example
 * ```ts
 * import { unique } from '@dpaskhin/unique';
 * import { faker } from '@faker-js/faker';
 *
 * // Outputs a unique city name
 * console.log(unique(faker.location.city));
 * ```
 */
declare function unique<Fn extends () => any>(fn: Fn, args?: never[], options?: IOptions<ReturnType<Fn>>): ReturnType<Fn>;
/**
 * Generates a unique value using the provided function `fn` that accepts arguments.
 *
 * **Note:** The global store is used by default and shared across the application.
 * For isolated usage, provide a custom `store` in the options.
 *
 * **Best Practice:** Use a custom store to avoid shared state and unexpected results.
 *
 * @template Fn The type of the function that generates values and accepts arguments.
 *
 * @param {Fn} fn - The function to generate values. This function must accept arguments.
 * @param {Parameters<Fn>} args - The arguments to be passed to the function `fn`.
 * @param {IOptions<ReturnType<Fn>>} [options] - Optional configuration for controlling the uniqueness generation process.
 * @returns {ReturnType<Fn>} The unique value generated by the function `fn`.
 *
 * @throws {Error} Throws an error if the max retries or max time is exceeded.
 *
 * @example
 * ```ts
 * import { unique } from '@dpaskhin/unique';
 * import { faker } from '@faker-js/faker';
 *
 * // Example with a function that takes arguments
 * const uniqueEmail = unique(
 *   faker.internet.email,
 *   [{ firstName: faker.person.firstName(), lastName: faker.person.lastName() }],
 *   { maxRetries: 10 }
 * );
 *
 * // Outputs a unique user's email
 * console.log(uniqueEmail);
 * ```
 */
declare function unique<Fn extends (...args: any[]) => any>(fn: Fn, args: Parameters<Fn>, options?: IOptions<ReturnType<Fn>>): ReturnType<Fn>;
/**
 * Ensures a unique value from the provided `value`, which is not a function.
 * There's only one attempt to check the uniqueness of the `value`.
 *
 * **Note:** The global store is used by default and shared across the application.
 * For isolated usage, provide a custom `store` in the options.
 *
 * **Best Practice:** Use a custom store to avoid shared state and unexpected results.
 *
 * @template Value The type of the value to ensure uniqueness.
 *
 * @param {NotFunction<Value>} value - The plain value to ensure uniqueness for. Must not be a function.
 * @param {Omit<IOptions<Value>, 'maxRetries' | 'maxTime'>} [options] - Optional configuration for controlling the uniqueness generation process.
 * @returns {Value} The unique value ensured by the `unique` function.
 *
 * @throws {Error} Throws an error if the value already exists in the store.
 *
 * @example
 * ```ts
 * import { unique } from '@dpaskhin/unique';
 *
 * // Each time outputs a unique ID string or throws an error
 * console.log(unique(window.crypto.randomUUID()));
 * console.log(unique(window.crypto.randomUUID()));
 * console.log(unique(window.crypto.randomUUID()));
 * ```
 */
declare function unique<Value>(value: NotFunction<Value>, options?: Omit<IOptions<Value>, 'maxRetries' | 'maxTime'>): Value;
type NotFunction<T> = T extends (...args: any[]) => any ? never : T;

export { GLOBAL_STORE, unique, uniqueFactory };
