Files
skills/docs/security-stack/security/password-strength/src/assess/assess-reactive.md
2026-05-29 08:20:56 +01:00

2.4 KiB

assess-reactive — streaming assessment with debounce + cancel

Purpose

Debounce + cancel-on-newer-input wrapper around assess for UI strength meters that update as the user types. Each new input cancels the pending assessment for the previous input; only the latest stable value reaches the consumer. The wrapper honours an optional AbortSignal so callers can tear down a meter without orphaning pending work.

Features

  • Configurable debounceMs (default 150 ms, range [0, 5000])
  • Cancel-on-newer-input — superseded inputs do not yield results
  • Clean AbortSignal completion (no thrown error on abort)
  • 200-character DoS guard surfaced as INPUT_TOO_LONG
  • Backed by an AsyncIterable<StrengthResult> so consumers integrate via for await

Usage: Basic Example

import { assessReactive } from "@suaveplan/password-strength";

async function* keystrokes() {
 yield "p";
 yield "pa";
 yield "pas";
 yield "pass";
}

for await (const r of assessReactive(keystrokes())) {
 console.log(r.password, r.score);
}

Usage: Advanced Example

import { assessReactive } from "@suaveplan/password-strength";

const controller = new AbortController();
const stream = assessReactive(keystrokes(), {
 debounceMs: 100,
 signal: controller.signal,
 assessOptions: { userInputs: ["alice@example.com"] },
});

setTimeout(() => controller.abort(), 50);

for await (const r of stream) {
 console.log(r.score);
}

API Reference

  • assessReactive(input$: AsyncIterable<string>, opts?: AssessReactiveOptions): AsyncIterable<StrengthResult>
    • Throws PasswordStrengthError(PWSTRENGTH.INVALID_OPTIONS) on schema failure; throws PasswordStrengthError(PWSTRENGTH.INPUT_TOO_LONG) when an input exceeds 200 characters.
  • AssessReactiveOptions: { debounceMs?, signal?, assessOptions? }.

Implementation Notes

The wrapper schedules each input via setTimeout(debounceMs). A newer input cancels the pending timer and reschedules. Consumers awaiting the next iteration are tracked in an internal resolver queue; an emitted result settles the next resolver or buffers if none is waiting. Abort clears the pending timer and resolves every waiting consumer with { done: true }; the iterable then completes cleanly without throwing. The ABORTED error code is registered with the OTel counter on abort so operators can monitor cancellation rates without inspecting the iterator itself.