first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
# `charsets`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Defines the canonical character-class constants used by every generator in the package — `LOWERCASE`, `UPPERCASE`, `DIGITS`, `SYMBOLS`, plus the curated `AMBIGUOUS` and `LOOKALIKES` sets that callers subtract to avoid characters confusable in fixed-width fonts. Exposing each class as a frozen `ReadonlySet<string>` lets callers compose custom unions (`new Set([...LOWERCASE, ...DIGITS])`) without depending on any private representation.
The `buildEffectiveCharset(opts)` helper merges the enabled classes and subtracts `opts.exclude` to produce the deduplicated string array a generator can index into via `randomInt`. The four built-in classes are pairwise disjoint by construction, so insertion-order union is enough to deduplicate — adding a `Set`-tracked check would be dead code.
## Features
- Frozen `ReadonlySet<string>` for each class — safe to share across modules.
- `AMBIGUOUS` (`0Ol1I`) and `LOOKALIKES` curated by frequency of human misreads.
- `SYMBOLS` drawn from the OWASP-recommended printable range; excludes shell-quoting hazards (backtick, backslash, whitespace).
- `buildEffectiveCharset(opts)` accepts string / array / `Set` exclusions.
## Usage: Basic Example
```ts
import {
AMBIGUOUS,
buildEffectiveCharset,
} from "@suaveplan/password-generator";
const charset = buildEffectiveCharset({ exclude: AMBIGUOUS });
```
## Usage: Advanced Example
```ts
import {
DIGITS,
LOWERCASE,
UPPERCASE,
buildEffectiveCharset,
} from "@suaveplan/password-generator";
// Hex charset only (digits + a-f) via two passes
const hexLower = [
...buildEffectiveCharset({ uppercase: false, symbols: false }),
].filter((c) => DIGITS.has(c) || "abcdef".includes(c));
// "Vault-friendly" passwords: drop ambiguous + shell-hostile chars
const safe = buildEffectiveCharset({ exclude: "0Ol1I`\\\"' " });
const charset = safe.filter((c) => !UPPERCASE.has(c) || LOWERCASE.has(c.toLowerCase()));
```
## API Reference
### Constants
- `LOWERCASE: ReadonlySet<string>` — `a–z` (26 entries).
- `UPPERCASE: ReadonlySet<string>` — `A–Z` (26 entries).
- `DIGITS: ReadonlySet<string>` — `0–9` (10 entries).
- `SYMBOLS: ReadonlySet<string>` — `!@#$%^&*()-_=+[]{};:,.<>/?` (25 entries).
- `AMBIGUOUS: ReadonlySet<string>` — `0Ol1I`.
- `LOOKALIKES: ReadonlySet<string>` — `0OQ1lI5S2Z8B`.
### `buildEffectiveCharset(opts?: CharsetOptions): string[]`
Builds the deduplicated union of enabled classes minus `opts.exclude`. Returns a fresh array on every call; insertion order is lowercase → uppercase → digits → symbols.
- `lowercase` / `uppercase` / `digits` / `symbols` — each defaults to `true`.
- `exclude` — `string` (per-character), `readonly string[]`, or `ReadonlySet<string>`; defaults to none.
## Implementation Notes
Every set is frozen at module load via `Object.freeze`, which only freezes the `Set` object itself (not the underlying internal storage). The intent is to surface accidental `.add` / `.delete` calls at call sites; consumers who need to add or remove characters must clone the set first.
`SYMBOLS` intentionally omits whitespace, the backslash, double-quote, and backtick. Those characters routinely break shell interpolations and CSV exports; including them would force every caller to filter them out before interpolating the generated password into a deployment script. Callers who want them can compose `new Set([...SYMBOLS, "\\\""])` themselves — the omission is conservative-by-default but trivially reversible.