first commit
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# `regex` — regex pattern matcher
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Recognises substrings matching a set of regex patterns per Wheeler 2016
|
||||
section 3.6. The default registry covers a `recent_year` pattern matching
|
||||
`19xx` and `20xx`. Callers extend the registry to flag additional patterns
|
||||
(hex strings, phone-number shapes, project-specific identifiers) without
|
||||
forking the scorer.
|
||||
|
||||
## Features
|
||||
|
||||
- Default `recent_year` regex matches `19xx` and `20xx`
|
||||
- Registry-pluggable: callers can register their own named regexes
|
||||
- Global-flag enforced internally so every occurrence is reported
|
||||
- Every match carries the full `RegExpMatchArray` for downstream inspection
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { regexMatch } from "@suaveplan/password-strength/matchers/regex";
|
||||
|
||||
const matches = regexMatch("login1985");
|
||||
console.log(matches[0].regexName); // "recent_year"
|
||||
console.log(matches[0].token); // "1985"
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { regexMatch } from "@suaveplan/password-strength/matchers/regex";
|
||||
|
||||
const matches = regexMatch("token=ABCDEF", { regexes: { hex: /[0-9A-F]+/g } });
|
||||
for (const m of matches) {
|
||||
console.log(m.regexName, m.token);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `regexMatch(password: string, opts?: RegexMatchOptions): RegexMatch[]`
|
||||
- `opts.regexes`: `Record<string, RegExp>` — the registry. Defaults to
|
||||
`DEFAULT_REGEXES`.
|
||||
- `DEFAULT_REGEXES: Readonly<Record<string, RegExp>>` — frozen default
|
||||
registry (currently `recent_year`).
|
||||
- `RegexMatchOptions`: `{ regexes?: Record<string, RegExp> }`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The matcher copies each registered regex with the `g` flag forced on so a
|
||||
global walk over the password emits every occurrence. The walk uses
|
||||
`String.prototype.matchAll` rather than mutating `lastIndex` so zero-width
|
||||
matches do not loop. The full `RegExpMatchArray` is preserved on each
|
||||
output record so callers can read capture groups when their regex uses
|
||||
them.
|
||||
|
||||
## Additional Implementation Notes
|
||||
|
||||
The implementation follows the canonical zxcvbn algorithm from Wheeler 2016 with
|
||||
the suaveplan-style additions described in the package proposal: structured error
|
||||
codes via the `defineCodes` registry, Zod boundaries at every public entry
|
||||
point, OTel histograms and counters keyed to low-cardinality attributes, and
|
||||
a strict input-length guard at 200 characters. Consumers integrate with their
|
||||
existing observability stack by installing a meter provider before importing
|
||||
the package, and with their i18n stack via the `MessageResolver` callback type
|
||||
declared in `@suaveplan/types`. The bundled data tables are intentionally
|
||||
small to keep the package bundle compact; production deployments should swap
|
||||
in fuller frequency-ranked tables via `loadDictionaries`. The default English
|
||||
dictionary set is a frozen `DictionarySet` that the matcher never mutates;
|
||||
caller-supplied dictionaries override defaults by name.
|
||||
Reference in New Issue
Block a user