@dpaskhin/unique
Version:
Ensures unique values by rejecting duplicates.
168 lines (166 loc) • 6.68 kB
text/typescript
/**
* 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 };