From 8d4e122732ffef4c06ed9b259475ae3d1dbec692 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:53:11 +0000 Subject: [PATCH 1/2] chore(deps-dev): bump eslint-plugin-perfectionist from 3.9.1 to 4.0.2 Bumps [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist) from 3.9.1 to 4.0.2. - [Release notes](https://github.com/azat-io/eslint-plugin-perfectionist/releases) - [Changelog](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/changelog.md) - [Commits](https://github.com/azat-io/eslint-plugin-perfectionist/compare/v3.9.1...v4.0.2) --- updated-dependencies: - dependency-name: eslint-plugin-perfectionist dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 77 +++++++++++------------------------------------ package.json | 2 +- 2 files changed, 19 insertions(+), 60 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9036e5b..9c4c44c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "@types/stylis": "^4.2.6", "@wxt-dev/module-react": "^1.1.2", "eslint": "^9.15.0", - "eslint-plugin-perfectionist": "^3.9.1", + "eslint-plugin-perfectionist": "^4.0.2", "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.14", @@ -42,6 +42,9 @@ "typescript": "5.6.3", "typescript-eslint": "^8.15.0", "wxt": "^0.19.16" + }, + "engines": { + "node": "22" } }, "node_modules/@aklinker1/rollup-plugin-visualizer": { @@ -4763,66 +4766,20 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.9.1.tgz", - "integrity": "sha512-9WRzf6XaAxF4Oi5t/3TqKP5zUjERhasHmLFHin2Yw6ZAp/EP/EVA2dr3BhQrrHWCm5SzTMZf0FcjDnBkO2xFkA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.0.2.tgz", + "integrity": "sha512-zWdgyg2SdHqhp/P9d9vKwo5qD9is28xMAGzBslHqkZz5mVIikjyz1qvuJ4yS7Wrsf4KlbGorORefb4Kbe7Puzg==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.9.0", - "@typescript-eslint/utils": "^8.9.0", - "minimatch": "^9.0.5", - "natural-compare-lite": "^1.4.0" + "@typescript-eslint/types": "^8.15.0", + "@typescript-eslint/utils": "^8.15.0", + "natural-orderby": "^5.0.0" }, "engines": { "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { - "astro-eslint-parser": "^1.0.2", - "eslint": ">=8.0.0", - "svelte": ">=3.0.0", - "svelte-eslint-parser": "^0.41.1", - "vue-eslint-parser": ">=9.0.0" - }, - "peerDependenciesMeta": { - "astro-eslint-parser": { - "optional": true - }, - "svelte": { - "optional": true - }, - "svelte-eslint-parser": { - "optional": true - }, - "vue-eslint-parser": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-perfectionist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/eslint-plugin-perfectionist/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "eslint": ">=8.0.0" } }, "node_modules/eslint-plugin-react": { @@ -7490,12 +7447,14 @@ "dev": true, "license": "MIT" }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "node_modules/natural-orderby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz", + "integrity": "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=18" + } }, "node_modules/ncp": { "version": "2.0.0", diff --git a/package.json b/package.json index b39e655..b725e67 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@types/stylis": "^4.2.6", "@wxt-dev/module-react": "^1.1.2", "eslint": "^9.15.0", - "eslint-plugin-perfectionist": "^3.9.1", + "eslint-plugin-perfectionist": "^4.0.2", "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.14", From ea274a7c3ad9ceb4a87ad8fa194099f26c740da6 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Tue, 19 Nov 2024 18:08:24 +0200 Subject: [PATCH 2/2] refactor(source): reorder definitions for clarity --- src/entrypoints/background.ts | 294 +++++++++--------- src/entrypoints/content.ts | 40 +-- src/hooks/useFormHandlers.tsx | 86 ++--- src/hooks/usePasswordStrength.tsx | 68 ++-- .../services/StrengthChecker.ts | 38 +-- .../services/ZxcvbnStrengthChecker.ts | 56 ++-- src/libs/password-strength/types/index.ts | 70 ++--- src/libs/secure-key-generator/errors/types.ts | 50 +-- .../passphrase/PassphraseGeneratorService.ts | 50 +-- .../password/PasswordGeneratorService.ts | 154 ++++----- .../services/random/CryptoRandomGenerator.ts | 56 ++-- .../validation/PasswordValidationService.ts | 54 ++-- src/libs/secure-key-generator/types/index.ts | 142 ++++----- src/shared/controls/types/control.types.ts | 24 +- src/stores/alert/alert.types.ts | 10 +- src/stores/direction/direction.service.ts | 22 +- src/stores/direction/direction.types.ts | 12 +- src/stores/generator/generator.types.ts | 18 +- src/stores/history/core/history.types.ts | 12 +- src/stores/history/ui/history-ui.types.ts | 8 +- src/stores/startup/startup.types.ts | 8 +- src/stores/theme/theme.types.ts | 14 +- 22 files changed, 643 insertions(+), 643 deletions(-) diff --git a/src/entrypoints/background.ts b/src/entrypoints/background.ts index 42908e2..e8d8357 100644 --- a/src/entrypoints/background.ts +++ b/src/entrypoints/background.ts @@ -21,14 +21,6 @@ import { defineBackground } from "wxt/sandbox"; import { browser } from "wxt/browser"; import { storage } from "wxt/storage"; -/** Interface for managing password history operations */ -interface HistoryManager { - /** Adds a new password to the history storage */ - addPassword(password: string): Promise; - /** Retrieves all stored passwords */ - getPasswords(): Promise; -} - /** Interface for managing context menu operations */ interface ContextMenuManager { /** Determines the generation mode based on the menu item ID */ @@ -43,68 +35,20 @@ interface ContextMenuManager { init(): Promise; } +/** Interface for managing password history operations */ +interface HistoryManager { + /** Adds a new password to the history storage */ + addPassword(password: string): Promise; + /** Retrieves all stored passwords */ + getPasswords(): Promise; +} + /** Interface for password generation operations */ interface PasswordGenerator { /** Generates a new password or passphrase based on the specified mode */ generate(mode: GenerationMode): Promise; } -/** - * Service for managing password history - * Handles storing and retrieving passwords with a maximum history size - */ -class HistoryManagerService implements HistoryManager { - private readonly STORAGE_KEY = "local:history-storage"; - private readonly MAX_HISTORY_SIZE = 2048; - - /** - * Adds a new password to the history - * @param password - The password to add to history - * @throws Error if saving to storage fails - */ - async addPassword(password: string): Promise { - try { - const passwords = await this.getPasswords(); - - const newPassword: Password = { - createdAt: new Date().toISOString(), - value: password, - id: Date.now(), - }; - - const updatedPasswords = [newPassword, ...passwords].slice( - 0, - this.MAX_HISTORY_SIZE, - ); - - await storage.setItem(this.STORAGE_KEY, { - state: { - passwords: updatedPasswords, - }, - }); - } catch (error) { - console.error("Failed to add password to history:", error); - throw new Error("Failed to save password to history"); - } - } - - /** - * Retrieves all passwords from storage - * @returns Array of stored passwords - */ - async getPasswords(): Promise { - try { - const historyState = await storage.getItem>( - this.STORAGE_KEY, - ); - return historyState?.state.passwords || []; - } catch (error) { - console.error("Failed to retrieve passwords from storage:", error); - return []; - } - } -} - /** * Service for managing browser context menu operations * Handles creating, updating, and managing context menu items @@ -120,19 +64,6 @@ class ContextMenuManagerService implements ContextMenuManager { private readonly STORAGE_KEY = "sync:ContextMenu"; - /** - * Helper function to get localized messages using browser.i18n - * @param key - The message key to lookup - */ - private getMessage(key: string): string { - // Since we cannot use #i18n in the background script, we have to use native browser API - // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n - // TODO: Submit an issue to the @wxt-dev/i18n to support background scripts - // @ts-expect-error - @wxt-dev/i18n cannot generate utility types for background.ts due to circular dependency: - // background.ts needs i18n utilities, but those utilities need background.ts for generation - return browser.i18n.getMessage(key.replace(/\./g, "_")); - } - /** * Creates the context menu structure */ @@ -234,6 +165,145 @@ class ContextMenuManagerService implements ContextMenuManager { ? "passphrase" : "password"; } + + /** + * Helper function to get localized messages using browser.i18n + * @param key - The message key to lookup + */ + private getMessage(key: string): string { + // Since we cannot use #i18n in the background script, we have to use native browser API + // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n + // TODO: Submit an issue to the @wxt-dev/i18n to support background scripts + // @ts-expect-error - @wxt-dev/i18n cannot generate utility types for background.ts due to circular dependency: + // background.ts needs i18n utilities, but those utilities need background.ts for generation + return browser.i18n.getMessage(key.replace(/\./g, "_")); + } +} + +/** + * Main background application class + * Coordinates all background services and handles event listeners + */ +class BackgroundApp { + private readonly contextMenu: ContextMenuManager; + private readonly generator: PasswordGenerator; + private readonly history: HistoryManager; + + constructor() { + this.history = new HistoryManagerService(); + this.contextMenu = new ContextMenuManagerService(); + this.generator = new PasswordGeneratorService(); + } + + /** + * Sets up event listeners for context menu interactions + */ + setupEventListeners(): void { + browser.contextMenus.onClicked.addListener(async (info, tab) => { + const { menuItemId } = info; + + if (this.contextMenu.isGenerationMenuItem(menuItemId)) { + await this.handlePasswordGeneration(menuItemId, tab); + } else if (menuItemId === "open-extension") { + await browser.action.openPopup(); + } + }); + } + + /** + * Starts the background application + * Initializes all services and sets up event handlers + */ + async start(): Promise { + try { + this.setupEventListeners(); + await this.contextMenu.init(); + } catch (error) { + console.error("Failed to start background app:", error); + } + } + + /** + * Handles password generation requests from context menu + * @param menuItemId - The ID of the clicked menu item + * @param tab - The current browser tab + */ + private async handlePasswordGeneration( + menuItemId: string | number, + tab?: Tabs.Tab, + ): Promise { + try { + const mode = this.contextMenu.getGenerationMode(menuItemId); + const password = await this.generator.generate(mode); + + await this.history.addPassword(password); + + if (tab?.id) { + await ClipboardManagerService.copyText(tab.id, password); + } else { + await navigator.clipboard.writeText(password); + } + } catch (error) { + console.error("Failed to handle password generation:", error); + await browser.action.openPopup(); + } + } +} + +/** + * Service for managing password history + * Handles storing and retrieving passwords with a maximum history size + */ +class HistoryManagerService implements HistoryManager { + private readonly STORAGE_KEY = "local:history-storage"; + private readonly MAX_HISTORY_SIZE = 2048; + + /** + * Adds a new password to the history + * @param password - The password to add to history + * @throws Error if saving to storage fails + */ + async addPassword(password: string): Promise { + try { + const passwords = await this.getPasswords(); + + const newPassword: Password = { + createdAt: new Date().toISOString(), + value: password, + id: Date.now(), + }; + + const updatedPasswords = [newPassword, ...passwords].slice( + 0, + this.MAX_HISTORY_SIZE, + ); + + await storage.setItem(this.STORAGE_KEY, { + state: { + passwords: updatedPasswords, + }, + }); + } catch (error) { + console.error("Failed to add password to history:", error); + throw new Error("Failed to save password to history"); + } + } + + /** + * Retrieves all passwords from storage + * @returns Array of stored passwords + */ + async getPasswords(): Promise { + try { + const historyState = await storage.getItem>( + this.STORAGE_KEY, + ); + return historyState?.state.passwords || []; + } catch (error) { + console.error("Failed to retrieve passwords from storage:", error); + return []; + } + } } /** @@ -310,76 +380,6 @@ class ClipboardManagerService { } } -/** - * Main background application class - * Coordinates all background services and handles event listeners - */ -class BackgroundApp { - private readonly contextMenu: ContextMenuManager; - private readonly generator: PasswordGenerator; - private readonly history: HistoryManager; - - constructor() { - this.history = new HistoryManagerService(); - this.contextMenu = new ContextMenuManagerService(); - this.generator = new PasswordGeneratorService(); - } - - /** - * Handles password generation requests from context menu - * @param menuItemId - The ID of the clicked menu item - * @param tab - The current browser tab - */ - private async handlePasswordGeneration( - menuItemId: string | number, - tab?: Tabs.Tab, - ): Promise { - try { - const mode = this.contextMenu.getGenerationMode(menuItemId); - const password = await this.generator.generate(mode); - - await this.history.addPassword(password); - - if (tab?.id) { - await ClipboardManagerService.copyText(tab.id, password); - } else { - await navigator.clipboard.writeText(password); - } - } catch (error) { - console.error("Failed to handle password generation:", error); - await browser.action.openPopup(); - } - } - - /** - * Sets up event listeners for context menu interactions - */ - setupEventListeners(): void { - browser.contextMenus.onClicked.addListener(async (info, tab) => { - const { menuItemId } = info; - - if (this.contextMenu.isGenerationMenuItem(menuItemId)) { - await this.handlePasswordGeneration(menuItemId, tab); - } else if (menuItemId === "open-extension") { - await browser.action.openPopup(); - } - }); - } - - /** - * Starts the background application - * Initializes all services and sets up event handlers - */ - async start(): Promise { - try { - this.setupEventListeners(); - await this.contextMenu.init(); - } catch (error) { - console.error("Failed to start background app:", error); - } - } -} - export default defineBackground(() => { const app = new BackgroundApp(); diff --git a/src/entrypoints/content.ts b/src/entrypoints/content.ts index a64cc7b..b9bbf84 100644 --- a/src/entrypoints/content.ts +++ b/src/entrypoints/content.ts @@ -29,26 +29,6 @@ interface TabMessage { text: string; } -/** - * Service for handling clipboard operations in the content script context - * Implements the core clipboard functionality using the Navigator API - */ -class MessageHandlerService implements MessageHandler { - /** - * Copies the provided text to clipboard - * @param text - The text to copy - * @throws Error if clipboard operation fails - */ - async handleCopyText(text: string): Promise { - try { - await navigator.clipboard.writeText(text); - } catch (error) { - console.error("Failed to copy text to clipboard:", error); - throw new Error("Failed to copy to clipboard"); - } - } -} - /** * Main content script application class * Handles message routing and clipboard operations within the browser tab @@ -95,6 +75,26 @@ class ContentApp { } } +/** + * Service for handling clipboard operations in the content script context + * Implements the core clipboard functionality using the Navigator API + */ +class MessageHandlerService implements MessageHandler { + /** + * Copies the provided text to clipboard + * @param text - The text to copy + * @throws Error if clipboard operation fails + */ + async handleCopyText(text: string): Promise { + try { + await navigator.clipboard.writeText(text); + } catch (error) { + console.error("Failed to copy text to clipboard:", error); + throw new Error("Failed to copy to clipboard"); + } + } +} + /** * Content script definition for the browser extension * Configures the script to run on all URLs and initializes the content application diff --git a/src/hooks/useFormHandlers.tsx b/src/hooks/useFormHandlers.tsx index dd9b951..cb67787 100644 --- a/src/hooks/useFormHandlers.tsx +++ b/src/hooks/useFormHandlers.tsx @@ -44,30 +44,6 @@ interface FormCommand { execute(...args: T[]): Promise | void; } -/** - * Handles copying text to clipboard with error handling - * @class ClipboardCommand - * @implements {FormCommand} - */ -class ClipboardCommand implements FormCommand { - constructor(private showAlert: (message: string) => void) {} - - /** - * Copies text to clipboard and shows alert on error - * @param text - Text to copy to clipboard - */ - async execute(text: string): Promise { - try { - await navigator.clipboard.writeText(text); - } catch (error: unknown) { - const errorMessage = - error instanceof Error ? error.message : i18n.t("error.unknown"); - - this.showAlert(errorMessage); - } - } -} - /** * Handles updates to password generation options * @class PasswordOptionsCommand @@ -145,6 +121,49 @@ class PasswordGenerationCommand } } +/** + * Handles copying text to clipboard with error handling + * @class ClipboardCommand + * @implements {FormCommand} + */ +class ClipboardCommand implements FormCommand { + constructor(private showAlert: (message: string) => void) {} + + /** + * Copies text to clipboard and shows alert on error + * @param text - Text to copy to clipboard + */ + async execute(text: string): Promise { + try { + await navigator.clipboard.writeText(text); + } catch (error: unknown) { + const errorMessage = + error instanceof Error ? error.message : i18n.t("error.unknown"); + + this.showAlert(errorMessage); + } + } +} + +/** + * Handles updates to passphrase number inclusion + * @class PassphraseNumberCommand + * @implements {FormCommand} + */ +class PassphraseNumberCommand implements FormCommand { + constructor( + private updateOptions: (updates: Partial) => void, + ) {} + + /** + * Updates number inclusion in passphrase options + * @param includeNumber - Whether to include numbers + */ + execute(includeNumber: boolean): void { + this.updateOptions({ includeNumber }); + } +} + /** * Handles updates to passphrase word count * @class PassphraseWordCountCommand @@ -202,25 +221,6 @@ class PassphraseStyleCommand implements FormCommand { } } -/** - * Handles updates to passphrase number inclusion - * @class PassphraseNumberCommand - * @implements {FormCommand} - */ -class PassphraseNumberCommand implements FormCommand { - constructor( - private updateOptions: (updates: Partial) => void, - ) {} - - /** - * Updates number inclusion in passphrase options - * @param includeNumber - Whether to include numbers - */ - execute(includeNumber: boolean): void { - this.updateOptions({ includeNumber }); - } -} - /** * Custom hook that provides form handlers for password/passphrase generation * @returns {FormHandlerState} Object containing form handler functions diff --git a/src/hooks/usePasswordStrength.tsx b/src/hooks/usePasswordStrength.tsx index a72236c..f1d4728 100644 --- a/src/hooks/usePasswordStrength.tsx +++ b/src/hooks/usePasswordStrength.tsx @@ -5,17 +5,6 @@ import { strengthChecker } from "@/libs/password-strength"; import { useEffect, useState } from "react"; import { i18n } from "#i18n"; -/** - * Represents color configuration for strength indicator - * @interface StrengthColor - */ -export interface StrengthColor { - /** Primary color for strength indicator */ - main: string; - /** Base/background color for strength indicator */ - base: string; -} - /** * State interface for password strength analysis * @interface PasswordStrengthState @@ -31,6 +20,17 @@ export interface PasswordStrengthState { strengthLevel: string; } +/** + * Represents color configuration for strength indicator + * @interface StrengthColor + */ +export interface StrengthColor { + /** Primary color for strength indicator */ + main: string; + /** Base/background color for strength indicator */ + base: string; +} + /** * Configuration for strength levels and associated colors * @constant STRENGTH_CONFIG @@ -63,29 +63,6 @@ interface StrengthStrategy { }; } -/** - * Default implementation of password strength analysis strategy - * @class DefaultStrengthStrategy - * @implements {StrengthStrategy} - */ -class DefaultStrengthStrategy implements StrengthStrategy { - /** - * Analyzes password strength and maps it to visual indicators - * @param strength - Password strength analysis result - * @returns Object containing visual representation data - */ - analyze(strength: Result | null) { - const score = strength?.score ?? -1; - const index = Math.min(Math.max(score, 0), 4); - - return { - percent: strength ? (score + 1) * 20 : 0, - color: STRENGTH_CONFIG.colors[index], - level: STRENGTH_CONFIG.levels[index], - }; - } -} - /** * Observer class that handles password strength analysis lifecycle * @class StrengthObserver @@ -130,6 +107,29 @@ class StrengthObserver { } } +/** + * Default implementation of password strength analysis strategy + * @class DefaultStrengthStrategy + * @implements {StrengthStrategy} + */ +class DefaultStrengthStrategy implements StrengthStrategy { + /** + * Analyzes password strength and maps it to visual indicators + * @param strength - Password strength analysis result + * @returns Object containing visual representation data + */ + analyze(strength: Result | null) { + const score = strength?.score ?? -1; + const index = Math.min(Math.max(score, 0), 4); + + return { + percent: strength ? (score + 1) * 20 : 0, + color: STRENGTH_CONFIG.colors[index], + level: STRENGTH_CONFIG.levels[index], + }; + } +} + /** * Custom hook for password strength analysis * Provides real-time strength analysis with visual indicators diff --git a/src/libs/password-strength/services/StrengthChecker.ts b/src/libs/password-strength/services/StrengthChecker.ts index 14552fa..93b08a9 100644 --- a/src/libs/password-strength/services/StrengthChecker.ts +++ b/src/libs/password-strength/services/StrengthChecker.ts @@ -37,6 +37,25 @@ export abstract class BaseStrengthChecker implements StrengthChecker { */ protected initialized = false; + /** + * Checks the strength of a password + * Must be implemented by concrete classes + * + * @abstract + * @param password - Password to analyze + * @returns Promise resolving to strength analysis result + */ + abstract checkStrength(password: string): Promise; + + /** + * Initializes the strength checker + * Must be implemented by concrete classes + * + * @abstract + * @returns Promise that resolves when initialization is complete + */ + abstract initialize(): Promise; + /** * Ensures the checker is initialized before use * Handles initialization lifecycle and error cases @@ -61,23 +80,4 @@ export abstract class BaseStrengthChecker implements StrengthChecker { return this.initializationPromise; } - - /** - * Checks the strength of a password - * Must be implemented by concrete classes - * - * @abstract - * @param password - Password to analyze - * @returns Promise resolving to strength analysis result - */ - abstract checkStrength(password: string): Promise; - - /** - * Initializes the strength checker - * Must be implemented by concrete classes - * - * @abstract - * @returns Promise that resolves when initialization is complete - */ - abstract initialize(): Promise; } diff --git a/src/libs/password-strength/services/ZxcvbnStrengthChecker.ts b/src/libs/password-strength/services/ZxcvbnStrengthChecker.ts index 430170b..a7e1053 100644 --- a/src/libs/password-strength/services/ZxcvbnStrengthChecker.ts +++ b/src/libs/password-strength/services/ZxcvbnStrengthChecker.ts @@ -20,34 +20,6 @@ import { BaseStrengthChecker } from "./StrengthChecker"; * ``` */ export class ZxcvbnStrengthChecker extends BaseStrengthChecker { - /** - * Loads required dictionaries and configuration for zxcvbn - * Fetches both common patterns and English language specifics - * - * @private - * @returns Promise resolving to strength checker options - * - * @remarks - * - Loads dictionaries asynchronously for better initial load performance - * - Combines common patterns with language-specific patterns - * - Currently includes English language support - */ - private async loadOptions(): Promise { - const [zxcvbnCommonPackage, zxcvbnEnPackage] = await Promise.all([ - import("@zxcvbn-ts/language-common"), - import("@zxcvbn-ts/language-en"), - ]); - - return { - dictionary: { - ...zxcvbnCommonPackage.dictionary, - ...zxcvbnEnPackage.dictionary, - }, - graphs: zxcvbnCommonPackage.adjacencyGraphs, - translations: zxcvbnEnPackage.translations, - }; - } - /** * Initializes the zxcvbn checker with required dictionaries and configurations * Implements the abstract initialize method from BaseStrengthChecker @@ -92,4 +64,32 @@ export class ZxcvbnStrengthChecker extends BaseStrengthChecker { return zxcvbn(password); } + + /** + * Loads required dictionaries and configuration for zxcvbn + * Fetches both common patterns and English language specifics + * + * @private + * @returns Promise resolving to strength checker options + * + * @remarks + * - Loads dictionaries asynchronously for better initial load performance + * - Combines common patterns with language-specific patterns + * - Currently includes English language support + */ + private async loadOptions(): Promise { + const [zxcvbnCommonPackage, zxcvbnEnPackage] = await Promise.all([ + import("@zxcvbn-ts/language-common"), + import("@zxcvbn-ts/language-en"), + ]); + + return { + dictionary: { + ...zxcvbnCommonPackage.dictionary, + ...zxcvbnEnPackage.dictionary, + }, + graphs: zxcvbnCommonPackage.adjacencyGraphs, + translations: zxcvbnEnPackage.translations, + }; + } } diff --git a/src/libs/password-strength/types/index.ts b/src/libs/password-strength/types/index.ts index e1a949f..38c9a57 100644 --- a/src/libs/password-strength/types/index.ts +++ b/src/libs/password-strength/types/index.ts @@ -1,5 +1,40 @@ import type { ZxcvbnResult, Options } from "@zxcvbn-ts/core"; +/** + * Interface for password strength checker implementations + * Defines required methods for analyzing password strength + * + * @interface StrengthChecker + * + * @example + * ```typescript + * class CustomChecker implements StrengthChecker { + * async initialize(): Promise { + * // Load necessary resources + * } + * + * async checkStrength(password: string): Promise { + * // Analyze password strength + * return analysis; + * } + * } + * ``` + */ +export interface StrengthChecker { + /** + * Analyzes the strength of a given password + * @param password - Password to analyze + * @returns Promise resolving to detailed strength analysis + */ + checkStrength(password: string): Promise; + + /** + * Initializes the strength checker with required resources + * @returns Promise resolving when initialization is complete + */ + initialize(): Promise; +} + /** * Configuration options for password strength checker * Extends zxcvbn options to allow partial configuration @@ -42,38 +77,3 @@ export type StrengthCheckerOptions = Partial; * ``` */ export type Result = ZxcvbnResult; - -/** - * Interface for password strength checker implementations - * Defines required methods for analyzing password strength - * - * @interface StrengthChecker - * - * @example - * ```typescript - * class CustomChecker implements StrengthChecker { - * async initialize(): Promise { - * // Load necessary resources - * } - * - * async checkStrength(password: string): Promise { - * // Analyze password strength - * return analysis; - * } - * } - * ``` - */ -export interface StrengthChecker { - /** - * Analyzes the strength of a given password - * @param password - Password to analyze - * @returns Promise resolving to detailed strength analysis - */ - checkStrength(password: string): Promise; - - /** - * Initializes the strength checker with required resources - * @returns Promise resolving when initialization is complete - */ - initialize(): Promise; -} diff --git a/src/libs/secure-key-generator/errors/types.ts b/src/libs/secure-key-generator/errors/types.ts index 0ff054d..d11e136 100644 --- a/src/libs/secure-key-generator/errors/types.ts +++ b/src/libs/secure-key-generator/errors/types.ts @@ -1,17 +1,32 @@ import type { errorMessages } from "./constants/errorMessages"; /** - * Valid error codes corresponding to predefined error messages - * Derived from keys of errorMessages constant + * Structured error information for generator errors + * Combines error code, message, and optional metadata * - * @typedef {keyof typeof errorMessages} ErrorCode + * @interface ErrorDetails * * @example * ```typescript - * const code: ErrorCode = 'INVALID_PASSWORD_LENGTH'; + * const details: ErrorDetails = { + * code: 'INVALID_PASSWORD_LENGTH', + * message: 'Length must correlate with strict guidelines', + * metadata: { + * minLength: 8, + * maxLength: 128, + * providedLength: 4 + * } + * }; * ``` */ -export type ErrorCode = keyof typeof errorMessages; +export interface ErrorDetails { + /** Additional contextual information about the error */ + metadata?: Record; + /** Error code identifying the type of error */ + code: ErrorCode; + /** Human-readable error message */ + message: string; +} /** * Predefined error message strings @@ -27,29 +42,14 @@ export type ErrorCode = keyof typeof errorMessages; export type ErrorMessage = (typeof errorMessages)[ErrorCode]; /** - * Structured error information for generator errors - * Combines error code, message, and optional metadata + * Valid error codes corresponding to predefined error messages + * Derived from keys of errorMessages constant * - * @interface ErrorDetails + * @typedef {keyof typeof errorMessages} ErrorCode * * @example * ```typescript - * const details: ErrorDetails = { - * code: 'INVALID_PASSWORD_LENGTH', - * message: 'Length must correlate with strict guidelines', - * metadata: { - * minLength: 8, - * maxLength: 128, - * providedLength: 4 - * } - * }; + * const code: ErrorCode = 'INVALID_PASSWORD_LENGTH'; * ``` */ -export interface ErrorDetails { - /** Additional contextual information about the error */ - metadata?: Record; - /** Error code identifying the type of error */ - code: ErrorCode; - /** Human-readable error message */ - message: string; -} +export type ErrorCode = keyof typeof errorMessages; diff --git a/src/libs/secure-key-generator/services/passphrase/PassphraseGeneratorService.ts b/src/libs/secure-key-generator/services/passphrase/PassphraseGeneratorService.ts index 6cf9421..d59457d 100644 --- a/src/libs/secure-key-generator/services/passphrase/PassphraseGeneratorService.ts +++ b/src/libs/secure-key-generator/services/passphrase/PassphraseGeneratorService.ts @@ -45,31 +45,6 @@ export class PassphraseGeneratorService { private readonly wordStyleService: WordStyleService, ) {} - /** - * Validates passphrase generation options - * @param wordCount - Number of words requested - * @throws {GeneratorError} If word count is invalid or word list is empty - * @private - */ - private validateOptions(wordCount: number): void { - if (wordCount < 1) { - throw ErrorHandler.createError("INVALID_WORD_COUNT"); - } - - if (this.wordListProvider.getWords().length === 0) { - throw ErrorHandler.createError("EMPTY_WORD_LIST"); - } - } - - /** - * Generates a random single digit (0-9) - * @returns Single digit as string - * @private - */ - private generateRandomDigit(): string { - return this.randomGenerator.getRandomNumber(10).toString(); - } - /** * Generates a passphrase based on provided options * @@ -141,4 +116,29 @@ export class PassphraseGeneratorService { style: "lowercase", }; } + + /** + * Validates passphrase generation options + * @param wordCount - Number of words requested + * @throws {GeneratorError} If word count is invalid or word list is empty + * @private + */ + private validateOptions(wordCount: number): void { + if (wordCount < 1) { + throw ErrorHandler.createError("INVALID_WORD_COUNT"); + } + + if (this.wordListProvider.getWords().length === 0) { + throw ErrorHandler.createError("EMPTY_WORD_LIST"); + } + } + + /** + * Generates a random single digit (0-9) + * @returns Single digit as string + * @private + */ + private generateRandomDigit(): string { + return this.randomGenerator.getRandomNumber(10).toString(); + } } diff --git a/src/libs/secure-key-generator/services/password/PasswordGeneratorService.ts b/src/libs/secure-key-generator/services/password/PasswordGeneratorService.ts index be739a9..f7081be 100644 --- a/src/libs/secure-key-generator/services/password/PasswordGeneratorService.ts +++ b/src/libs/secure-key-generator/services/password/PasswordGeneratorService.ts @@ -54,83 +54,6 @@ export class PasswordGeneratorService { } } - /** - * Generates a single password attempt - * Ensures required characters are included and randomly placed - * - * @param length - Desired password length - * @param options - Password generation options - * @param pool - Character pool to use - * @returns Generated password attempt - * @private - */ - private generateAttempt( - length: number, - options: PasswordOptions, - pool: string, - ): string { - // Create TypedArray for secure random values - const randomValues = new Uint32Array(length * 2); // Extra values in case of modulo bias - - crypto.getRandomValues(randomValues); - - const chars: string[] = []; - - // Get required characters from each enabled set - const requiredChars = this.characterPoolService.getRequiredChars(options); - - chars.push(...requiredChars); - - // Fill remaining length with secure random characters - let valueIndex = 0; - - while (chars.length < length) { - // Reject values that would create modulo bias - let randomValue = randomValues[valueIndex]; - const maxAcceptable = - Math.floor(0xffffffff / pool.length) * pool.length - 1; - - // Get next value if current would introduce bias - while (randomValue > maxAcceptable) { - valueIndex++; - - if (valueIndex >= randomValues.length) { - // If we run out of values, get more - crypto.getRandomValues(randomValues); - valueIndex = 0; - } - - randomValue = randomValues[valueIndex]; - } - - chars.push(pool[randomValue % pool.length]); - valueIndex++; - } - - // Randomly shuffle using Fisher-Yates with cryptographically secure values - for (let i = chars.length - 1; i > 0; i--) { - // Get new secure random values for shuffling - const shuffleValues = new Uint32Array(1); - - crypto.getRandomValues(shuffleValues); - - // Reject values that would create modulo bias - let randomValue = shuffleValues[0]; - const maxAcceptable = Math.floor(0xffffffff / (i + 1)) * (i + 1) - 1; - - while (randomValue > maxAcceptable) { - crypto.getRandomValues(shuffleValues); - randomValue = shuffleValues[0]; - } - - const j = randomValue % (i + 1); - - [chars[i], chars[j]] = [chars[j], chars[i]]; - } - - return chars.join(""); - } - /** * Generates a password meeting all specified requirements * Attempts multiple generations if needed to meet criteria @@ -216,4 +139,81 @@ export class PasswordGeneratorService { length: 24, }; } + + /** + * Generates a single password attempt + * Ensures required characters are included and randomly placed + * + * @param length - Desired password length + * @param options - Password generation options + * @param pool - Character pool to use + * @returns Generated password attempt + * @private + */ + private generateAttempt( + length: number, + options: PasswordOptions, + pool: string, + ): string { + // Create TypedArray for secure random values + const randomValues = new Uint32Array(length * 2); // Extra values in case of modulo bias + + crypto.getRandomValues(randomValues); + + const chars: string[] = []; + + // Get required characters from each enabled set + const requiredChars = this.characterPoolService.getRequiredChars(options); + + chars.push(...requiredChars); + + // Fill remaining length with secure random characters + let valueIndex = 0; + + while (chars.length < length) { + // Reject values that would create modulo bias + let randomValue = randomValues[valueIndex]; + const maxAcceptable = + Math.floor(0xffffffff / pool.length) * pool.length - 1; + + // Get next value if current would introduce bias + while (randomValue > maxAcceptable) { + valueIndex++; + + if (valueIndex >= randomValues.length) { + // If we run out of values, get more + crypto.getRandomValues(randomValues); + valueIndex = 0; + } + + randomValue = randomValues[valueIndex]; + } + + chars.push(pool[randomValue % pool.length]); + valueIndex++; + } + + // Randomly shuffle using Fisher-Yates with cryptographically secure values + for (let i = chars.length - 1; i > 0; i--) { + // Get new secure random values for shuffling + const shuffleValues = new Uint32Array(1); + + crypto.getRandomValues(shuffleValues); + + // Reject values that would create modulo bias + let randomValue = shuffleValues[0]; + const maxAcceptable = Math.floor(0xffffffff / (i + 1)) * (i + 1) - 1; + + while (randomValue > maxAcceptable) { + crypto.getRandomValues(shuffleValues); + randomValue = shuffleValues[0]; + } + + const j = randomValue % (i + 1); + + [chars[i], chars[j]] = [chars[j], chars[i]]; + } + + return chars.join(""); + } } diff --git a/src/libs/secure-key-generator/services/random/CryptoRandomGenerator.ts b/src/libs/secure-key-generator/services/random/CryptoRandomGenerator.ts index 02f1096..83274fc 100644 --- a/src/libs/secure-key-generator/services/random/CryptoRandomGenerator.ts +++ b/src/libs/secure-key-generator/services/random/CryptoRandomGenerator.ts @@ -35,34 +35,6 @@ export class CryptoRandomGenerator implements RandomGenerator { this.randomIndex = this.RANDOM_BATCH_SIZE; } - /** - * Gets next 32-bit random value from buffer - * Refills buffer when exhausted - * - * @returns 32-bit random unsigned integer - * @private - * - * @remarks - * Uses batching to reduce calls to crypto.getRandomValues - * Each value is read as a 32-bit unsigned integer - */ - private getNextRandomValue(): number { - if (this.randomIndex >= this.randomValues.length) { - crypto.getRandomValues(this.randomValues); - this.randomIndex = 0; - } - - const value = new DataView( - this.randomValues.buffer, - this.randomIndex, - 4, - ).getUint32(0); - - this.randomIndex += 4; - - return value; - } - /** * Generates a cryptographically secure random number * Uses rejection sampling to ensure uniform distribution @@ -94,4 +66,32 @@ export class CryptoRandomGenerator implements RandomGenerator { return rand; } + + /** + * Gets next 32-bit random value from buffer + * Refills buffer when exhausted + * + * @returns 32-bit random unsigned integer + * @private + * + * @remarks + * Uses batching to reduce calls to crypto.getRandomValues + * Each value is read as a 32-bit unsigned integer + */ + private getNextRandomValue(): number { + if (this.randomIndex >= this.randomValues.length) { + crypto.getRandomValues(this.randomValues); + this.randomIndex = 0; + } + + const value = new DataView( + this.randomValues.buffer, + this.randomIndex, + 4, + ).getUint32(0); + + this.randomIndex += 4; + + return value; + } } diff --git a/src/libs/secure-key-generator/services/validation/PasswordValidationService.ts b/src/libs/secure-key-generator/services/validation/PasswordValidationService.ts index d12acf8..a7b5938 100644 --- a/src/libs/secure-key-generator/services/validation/PasswordValidationService.ts +++ b/src/libs/secure-key-generator/services/validation/PasswordValidationService.ts @@ -42,33 +42,6 @@ export class PasswordValidationService { ["numbers", /[0-9]/], ]); - /** - * Calculates minimum required password length based on enabled character sets - * Each enabled character set requires at least one character - * - * @param options - Password generation options - * @returns Minimum required length - * @private - * - * @example - * ```typescript - * // If uppercase, lowercase, and numbers are enabled: - * const minLength = calculateMinimumLength({ - * uppercase: true, - * lowercase: true, - * numbers: true, - * symbols: false - * }); - * // Returns: 3 - * ``` - */ - private calculateMinimumLength(options: PasswordOptions): number { - return Object.entries(options).filter( - ([key, value]) => - key !== "length" && key !== "customization" && value === true, - ).length; - } - /** * Validates that a password meets all required character set constraints * Checks presence of characters from each enabled set @@ -127,4 +100,31 @@ export class PasswordValidationService { throw ErrorHandler.createError("INVALID_PASSWORD_LENGTH"); } } + + /** + * Calculates minimum required password length based on enabled character sets + * Each enabled character set requires at least one character + * + * @param options - Password generation options + * @returns Minimum required length + * @private + * + * @example + * ```typescript + * // If uppercase, lowercase, and numbers are enabled: + * const minLength = calculateMinimumLength({ + * uppercase: true, + * lowercase: true, + * numbers: true, + * symbols: false + * }); + * // Returns: 3 + * ``` + */ + private calculateMinimumLength(options: PasswordOptions): number { + return Object.entries(options).filter( + ([key, value]) => + key !== "length" && key !== "customization" && value === true, + ).length; + } } diff --git a/src/libs/secure-key-generator/types/index.ts b/src/libs/secure-key-generator/types/index.ts index ffa8c9e..082c199 100644 --- a/src/libs/secure-key-generator/types/index.ts +++ b/src/libs/secure-key-generator/types/index.ts @@ -1,49 +1,57 @@ /** - * Available character set categories for password generation - * @typedef {'lowercase' | 'uppercase' | 'numbers' | 'symbols'} CharacterSet - */ -export type CharacterSet = "lowercase" | "uppercase" | "numbers" | "symbols"; - -/** - * Available word casing styles for passphrase generation - * @typedef {'capitalize' | 'uppercase' | 'lowercase'} WordStyle + * Configuration options for passphrase generation + * + * @interface PassphraseOptions * * @example - * 'capitalize': "Word" - * 'uppercase': "WORD" - * 'lowercase': "word" - */ -export type WordStyle = "capitalize" | "uppercase" | "lowercase"; - -/** - * Additional rules for password generation customization - * @typedef {'exclude'} AdditionalRule - */ -export type AdditionalRule = "exclude"; - -/** - * Toggle options for password generation behavior - * @typedef {'skipAmbiguous'} SwitchOption + * ```typescript + * const options: PassphraseOptions = { + * wordCount: 4, + * separator: "-", + * style: "lowercase", + * includeNumber: true + * }; + * // Result example: "correct-horse-battery-staple4" + * ``` */ -export type SwitchOption = "skipAmbiguous"; +export interface PassphraseOptions { + /** Whether to add a random number to single word */ + includeNumber: boolean; + /** Number of words to include */ + wordCount: number; + /** Character(s) to use between words */ + separator: string; + /** Word casing style */ + style: WordStyle; +} /** - * Configuration for enabling/disabling character sets - * Maps each character set to a boolean flag + * Complete configuration options for password generation * - * @typedef {Record} CharacterSetOptions + * @interface PasswordOptions + * @extends {CharacterSetOptions} * * @example * ```typescript - * const options: CharacterSetOptions = { + * const options: PasswordOptions = { * lowercase: true, * uppercase: true, * numbers: true, - * symbols: false + * symbols: false, + * length: 16, + * customization: { + * exclude: "meow", + * skipAmbiguous: true + * } * }; * ``` */ -export type CharacterSetOptions = Record; +export interface PasswordOptions extends CharacterSetOptions { + /** Additional customization settings */ + customization: CustomizationOptions; + /** Desired password length */ + length: number; +} /** * Additional customization options for password generation @@ -68,59 +76,39 @@ export type CustomizationOptions = { }; /** - * Complete configuration options for password generation - * - * @interface PasswordOptions - * @extends {CharacterSetOptions} + * Available character set categories for password generation + * @typedef {'lowercase' | 'uppercase' | 'numbers' | 'symbols'} CharacterSet + */ +export type CharacterSet = "lowercase" | "uppercase" | "numbers" | "symbols"; + +/** + * Available word casing styles for passphrase generation + * @typedef {'capitalize' | 'uppercase' | 'lowercase'} WordStyle * * @example - * ```typescript - * const options: PasswordOptions = { - * lowercase: true, - * uppercase: true, - * numbers: true, - * symbols: false, - * length: 16, - * customization: { - * exclude: "meow", - * skipAmbiguous: true - * } - * }; - * ``` + * 'capitalize': "Word" + * 'uppercase': "WORD" + * 'lowercase': "word" */ -export interface PasswordOptions extends CharacterSetOptions { - /** Additional customization settings */ - customization: CustomizationOptions; - /** Desired password length */ - length: number; -} +export type WordStyle = "capitalize" | "uppercase" | "lowercase"; /** - * Configuration options for passphrase generation + * Configuration for enabling/disabling character sets + * Maps each character set to a boolean flag * - * @interface PassphraseOptions + * @typedef {Record} CharacterSetOptions * * @example * ```typescript - * const options: PassphraseOptions = { - * wordCount: 4, - * separator: "-", - * style: "lowercase", - * includeNumber: true + * const options: CharacterSetOptions = { + * lowercase: true, + * uppercase: true, + * numbers: true, + * symbols: false * }; - * // Result example: "correct-horse-battery-staple4" * ``` */ -export interface PassphraseOptions { - /** Whether to add a random number to single word */ - includeNumber: boolean; - /** Number of words to include */ - wordCount: number; - /** Character(s) to use between words */ - separator: string; - /** Word casing style */ - style: WordStyle; -} +export type CharacterSetOptions = Record; /** * Maps character set categories to their actual characters @@ -140,3 +128,15 @@ export interface PassphraseOptions { export type CharacterPool = { [K in CharacterSet]: string; }; + +/** + * Toggle options for password generation behavior + * @typedef {'skipAmbiguous'} SwitchOption + */ +export type SwitchOption = "skipAmbiguous"; + +/** + * Additional rules for password generation customization + * @typedef {'exclude'} AdditionalRule + */ +export type AdditionalRule = "exclude"; diff --git a/src/shared/controls/types/control.types.ts b/src/shared/controls/types/control.types.ts index bf6533c..62abe71 100644 --- a/src/shared/controls/types/control.types.ts +++ b/src/shared/controls/types/control.types.ts @@ -1,31 +1,31 @@ -export interface CheckboxData { - checked: boolean; +export interface SelectData { + options: SelectEntry[]; + value: string; label: string; id: string; } -export interface SwitchData { - checked: boolean; +export interface InputData { + placeholder: string; + value: string; label: string; id: string; } -export interface InputData { - placeholder: string; - value: string; +export interface CheckboxData { + checked: boolean; label: string; id: string; } -export interface SelectEntry { +export interface SwitchData { + checked: boolean; label: string; - value: string; id: string; } -export interface SelectData { - options: SelectEntry[]; - value: string; +export interface SelectEntry { label: string; + value: string; id: string; } diff --git a/src/stores/alert/alert.types.ts b/src/stores/alert/alert.types.ts index ba2b716..06d5bfc 100644 --- a/src/stores/alert/alert.types.ts +++ b/src/stores/alert/alert.types.ts @@ -1,11 +1,11 @@ -export interface AlertState { - message: string | null; - open: boolean; -} - export interface AlertActions { showAlert: (message: string) => void; hideAlert: () => void; } +export interface AlertState { + message: string | null; + open: boolean; +} + export type AlertStore = AlertActions & AlertState; diff --git a/src/stores/direction/direction.service.ts b/src/stores/direction/direction.service.ts index e270f5e..15a9215 100644 --- a/src/stores/direction/direction.service.ts +++ b/src/stores/direction/direction.service.ts @@ -27,17 +27,6 @@ export class DirectionService { }; } - /** - * Determines direction based on language code - * @param language - Language code - * @returns Appropriate direction for the language - */ - private static getDirectionFromLanguage(language: string): Direction { - return this.RTL_LANGUAGES.some((rtlLang) => language.startsWith(rtlLang)) - ? "rtl" - : "ltr"; - } - /** * Detects direction based on browser language * @returns Detected direction @@ -57,4 +46,15 @@ export class DirectionService { direction: "ltr", }; } + + /** + * Determines direction based on language code + * @param language - Language code + * @returns Appropriate direction for the language + */ + private static getDirectionFromLanguage(language: string): Direction { + return this.RTL_LANGUAGES.some((rtlLang) => language.startsWith(rtlLang)) + ? "rtl" + : "ltr"; + } } diff --git a/src/stores/direction/direction.types.ts b/src/stores/direction/direction.types.ts index 6aca7c5..68fee98 100644 --- a/src/stores/direction/direction.types.ts +++ b/src/stores/direction/direction.types.ts @@ -1,12 +1,12 @@ -export type Direction = "ltr" | "rtl"; - -export interface DirectionState { - direction: Direction; -} - export interface DirectionActions { setDirection: (direction: Direction) => void; initializeDirection: () => void; } export type DirectionStore = DirectionActions & DirectionState; + +export interface DirectionState { + direction: Direction; +} + +export type Direction = "ltr" | "rtl"; diff --git a/src/stores/generator/generator.types.ts b/src/stores/generator/generator.types.ts index f01f3f7..dbf04e4 100644 --- a/src/stores/generator/generator.types.ts +++ b/src/stores/generator/generator.types.ts @@ -3,15 +3,6 @@ import type { PasswordOptions, } from "@/libs/secure-key-generator"; -export type GenerationMode = "passphrase" | "password"; - -export interface GeneratorState { - passphraseOptions: PassphraseOptions; - passwordOptions: PasswordOptions; - mode: GenerationMode; - password: string; -} - export interface GeneratorActions { updatePassphraseOptions: (updates: Partial) => void; updatePasswordOptions: (updates: Partial) => void; @@ -20,4 +11,13 @@ export interface GeneratorActions { setMode: (mode: GenerationMode) => void; } +export interface GeneratorState { + passphraseOptions: PassphraseOptions; + passwordOptions: PasswordOptions; + mode: GenerationMode; + password: string; +} + export type GeneratorStore = GeneratorActions & GeneratorState; + +export type GenerationMode = "passphrase" | "password"; diff --git a/src/stores/history/core/history.types.ts b/src/stores/history/core/history.types.ts index af54e4d..e5d3eba 100644 --- a/src/stores/history/core/history.types.ts +++ b/src/stores/history/core/history.types.ts @@ -1,3 +1,9 @@ +export interface HistoryActions { + addPassword: (password: string) => void; + removePassword: (id: number) => void; + clearHistory: () => void; +} + export interface Password { createdAt: string; value: string; @@ -8,10 +14,4 @@ export interface HistoryState { passwords: Password[]; } -export interface HistoryActions { - addPassword: (password: string) => void; - removePassword: (id: number) => void; - clearHistory: () => void; -} - export type HistoryStore = HistoryActions & HistoryState; diff --git a/src/stores/history/ui/history-ui.types.ts b/src/stores/history/ui/history-ui.types.ts index 5c746af..cbf8161 100644 --- a/src/stores/history/ui/history-ui.types.ts +++ b/src/stores/history/ui/history-ui.types.ts @@ -1,10 +1,10 @@ -export interface HistoryUIState { - open: boolean; -} - export interface HistoryUIActions { showHistory: () => void; hideHistory: () => void; } export type HistoryUIStore = HistoryUIActions & HistoryUIState; + +export interface HistoryUIState { + open: boolean; +} diff --git a/src/stores/startup/startup.types.ts b/src/stores/startup/startup.types.ts index 917f336..6e10e8e 100644 --- a/src/stores/startup/startup.types.ts +++ b/src/stores/startup/startup.types.ts @@ -1,9 +1,9 @@ -export interface StartupState { - hasSeenWelcome: boolean; -} - export interface StartupActions { setHasSeenWelcome: (value: boolean) => void; } +export interface StartupState { + hasSeenWelcome: boolean; +} + export type StartupStore = StartupActions & StartupState; diff --git a/src/stores/theme/theme.types.ts b/src/stores/theme/theme.types.ts index 5da1fb9..39cce9c 100644 --- a/src/stores/theme/theme.types.ts +++ b/src/stores/theme/theme.types.ts @@ -1,14 +1,14 @@ -export type Theme = "light" | "dark"; - -export interface ThemeState { - isSystemTheme: boolean; - theme: Theme; -} - export interface ThemeActions { setTheme: (theme: Theme) => void; syncWithSystem: () => void; toggleTheme: () => void; } +export interface ThemeState { + isSystemTheme: boolean; + theme: Theme; +} + export type ThemeStore = ThemeActions & ThemeState; + +export type Theme = "light" | "dark";