Skip to content

Commit

Permalink
docs: add initial docs (#6)
Browse files Browse the repository at this point in the history
dPaskhin authored Oct 5, 2024
1 parent 27a36e9 commit df3ed06
Showing 3 changed files with 222 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/proud-icons-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@dpaskhin/unique': patch
---

Added initial docs
128 changes: 127 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,127 @@
**@dpaskhin/unique**
# @dpaskhin/unique

**@dpaskhin/unique** is a TypeScript library that ensures the uniqueness of generated values. It wraps any function to
reject
duplicate values and generate new ones until a unique result is produced. Useful for cases where you need unique random
values or want to prevent repeated results.

## Installation

To install **@dpaskhin/unique**, run:

```shell
npm install --save-dev @dpaskhin/unique
```

## Features

- Ensures uniqueness of generated values by using a custom or global store.
- Configurable with options like maximum retries, timeouts, and exclusion of specific values.

## Usage

#### Basic Example

Here’s a quick example using **@dpaskhin/unique** with a custom function:

```ts
import { unique } from '@dpaskhin/unique';

const randomNumber = () => Math.floor(Math.random() * 100);

const uniqueRandomNumber = unique(randomNumber, [], { maxRetries: 5 });

console.log(uniqueRandomNumber); // Outputs a unique random number each time
```

#### Example with Faker.js

**@dpaskhin/unique** works well with libraries like Faker.js for generating unique random data.

```ts
import { unique } from '@dpaskhin/unique';
import { faker } from '@faker-js/faker';

const uniqueName = unique(faker.person.firstName, ['male'], { maxRetries: 10 });

console.log(uniqueName); // Outputs a unique first name
```

## API Reference

### uniqueFactory(fn, options)

Creates a function that ensures unique results based on the provided function fn.

#### Parameters

- fn - The function used to generate values.
- options - Optional. An object containing configuration options:
- store (Set) - A custom store to track unique values. Defaults to a new Set.
- maxRetries (number) - The maximum number of retries for unique values. Defaults to 50.
- maxTime (number) - The maximum allowed time (in ms) for generating a unique value. Defaults to 50ms.
- exclude (Array) - Values to exclude from the result set.

#### Returns

A function that generates unique values based on fn with the same signature.

#### Example

```ts
import { uniqueFactory } from '@dpaskhin/unique';
import { faker } from '@faker-js/faker';

const uniqueAddress = uniqueFactory(faker.location.city, { maxRetries: 5 });

console.log(uniqueAddress()); // Outputs a unique city name
```

### unique(fn, args, options)

Generates a unique value by running fn and ensuring uniqueness via either a provided or global store.

#### Parameters

- fn - The function used to generate values.
- args - Optional. An array of arguments to be passed to fn.
- options - Optional. An object containing configuration options:
- store (Set) - A custom store to track unique values. Defaults to the global store.
- maxRetries (number) - The maximum number of retries for unique values. Defaults to 50.
- maxTime (number) - The maximum allowed time (in ms) for generating a unique value. Defaults to 50ms.
- exclude (Array) - Values to exclude from the result set.

#### Returns

A unique value generated by fn.

#### Example

```ts
import { unique } from '@dpaskhin/unique';
import { faker } from '@faker-js/faker';

const uniqueEmail = unique(faker.internet.email, [
{
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
},
]);

console.log(uniqueEmail); // Outputs a unique email address
```

### Best Practices

- Avoid Global Store for Local Uniqueness: If you need to ensure uniqueness only within a specific context or function,
use a custom store to avoid unexpected results from shared global state.
- Configure Max Retries and Timeouts: Customize maxRetries and maxTime based on the expected uniqueness and complexity
of generated values.

### License

**@dpaskhin/unique** is licensed under the MIT License.

### Contributing

Contributions are welcome! If you have ideas or improvements, feel free to submit a pull request.
107 changes: 90 additions & 17 deletions src/main/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,47 @@
/**
* Configuration options for the unique generation process.
*
* @template Result The type of the result generated by the function.
*
* @property {Set<Result>} [store] - Optional store to keep track of unique values. Defaults to a new Set.
* @property {number} [maxRetries=50] - The maximum number of retries to generate a unique value. Defaults to 50.
* @property {number} [maxTime=50] - The maximum time (in ms) allowed for generating a unique value before throwing an error. Defaults to 50ms.
* @property {Result[]} [exclude] - List of values that should be excluded from the result set.
*/
interface IOptions<Result> {
store?: Set<Result>;
maxRetries?: number;
maxTime?: number;
exclude?: Result[];
}

function createErrorMessage(
code: string,
storeSize: number,
duration: number,
currentIterations: number
): string {
return `
${code} for uniqueness check.
Found ${storeSize} unique entries before throwing error.
retried: ${currentIterations}
total time: ${duration}ms
May not be able to generate any more unique values with current settings.
Try adjusting maxTime or maxRetries parameters.`;
}

/**
* Creates a function that generates unique values based on a passed function `fn`.
* Ensures uniqueness by storing generated values and retrying if duplicates are found.
*
* @template Args The type of the arguments that the function takes.
* @template Result The type of the result generated by the function.
*
* @param {(...args: Args[]) => Result} fn - The function to generate values.
* @param {IOptions<Result>} [options={}] - Optional configuration for controlling the uniqueness generation process.
* @returns {(...args: Args[]) => Result} 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';
*
* // Create a unique generator
* const uniqueNameGen = uniqueFactory(faker.person.firstName);
*
* const name1 = uniqueNameGen(); // Generate a unique name
* const name2 = uniqueNameGen(); // Generate another unique name
*
* console.log(name1, name2); // Two different names
* ```
*/
export function uniqueFactory<Args, Result>(
fn: (...args: Args[]) => Result,
options: IOptions<Result> = {}
@@ -77,8 +97,44 @@ export function uniqueFactory<Args, Result>(
};
}

/**
* A global store to track unique values across multiple invocations of the `unique` function.
* This can be shared across different parts of the code to ensure unique values globally.
*/
export const GLOBAL_STORE = new Set();

/**
* Generates a unique value using the provided function `fn`. It ensures uniqueness by checking
* against previous results and values stored either in the provided `store` or the global store.
*
* **Note:** The global store is shared across multiple invocations, and values will persist globally.
* If you need isolation between different parts of your application, you should provide a custom `store` in the options.
*
* **Best Practice:** Avoid using the global store in environments where global uniqueness is not needed,
* as it may lead to unexpected results due to shared state.
*
* @template Args The type of the arguments that the function takes.
* @template Result The type of the result generated by the function.
*
* @param {(...args: Args[]) => Result} fn - The function to generate values.
* @param {Args[]} [args=[]] - The arguments to be passed to `fn`.
* @param {IOptions<Result>} [options={}] - Optional configuration for controlling the uniqueness generation process.
* When no `store` is provided, the function will default to using the global store.
* @returns {Result} 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';
*
* const phone1 = unique(faker.phone.number); // Generate a unique phone number
* const phone2 = unique(faker.phone.number); // Generate another unique phone number
*
* console.log(phone1, phone2); // Two different phone numbers
* ```
*/
export function unique<Args, Result>(
fn: (...args: Args[]) => Result,
args: Args[] = [],
@@ -89,3 +145,20 @@ export function unique<Args, Result>(
Object.assign(options, { store: options.store || GLOBAL_STORE })
).apply(null, args);
}

function createErrorMessage(
code: string,
storeSize: number,
duration: number,
currentIterations: number
): string {
return `
${code} for uniqueness check.
Found ${storeSize} unique entries before throwing error.
retried: ${currentIterations}
total time: ${duration}ms
May not be able to generate any more unique values with current settings.
Try adjusting maxTime or maxRetries parameters.`;
}

0 comments on commit df3ed06

Please sign in to comment.