1import type { PasswordPolicy } from "./types";23export interface GeneratorOptions {4 length: number;5 includeUppercase: boolean;6 includeLowercase: boolean;7 includeNumbers: boolean;8 includeSymbols: boolean;9 10 forbiddenChars?: string;11}1213141516export function generatePassword(options: Partial<GeneratorOptions> = {}): string {17 const {18 length = 20,19 includeUppercase = true,20 includeLowercase = true,21 includeNumbers = true,22 includeSymbols = true,23 forbiddenChars = "",24 } = options;2526 const forbidden = new Set(forbiddenChars);27 const filter = (pool: string): string =>28 forbidden.size === 029 ? pool30 : Array.from(pool).filter((c) => !forbidden.has(c)).join("");3132 let chars = "";33 if (includeLowercase) chars += filter("abcdefghijklmnopqrstuvwxyz");34 if (includeUppercase) chars += filter("ABCDEFGHIJKLMNOPQRSTUVWXYZ");35 if (includeNumbers) chars += filter("0123456789");36 if (includeSymbols) chars += filter("!@#$%^&*");3738 if (chars.length === 0) chars = filter("abcdefghijklmnopqrstuvwxyz") || "abcdefghijklmnopqrstuvwxyz";3940 const array = crypto.getRandomValues(new Uint32Array(length));41 let password = "";42 for (let i = 0; i < length; i++) {43 password += chars[array[i]! % chars.length];44 }45 return password;46}4748495051525354export function generateSmartPassword(policy: PasswordPolicy = {}): string {55 const defaultLength = 20;56 let length = defaultLength;57 if (policy.minLength) length = Math.max(length, policy.minLength);58 if (policy.maxLength) length = Math.min(length, policy.maxLength);59 if (length < 8) length = 8;6061 return generatePassword({62 length,63 includeSymbols: !policy.forbidsSymbols,64 forbiddenChars: policy.forbiddenChars,65 });66}