Refactor imports and improve error handling across multiple files for better maintainability and clarity

This commit is contained in:
2025-11-08 10:55:51 +01:00
parent c150fa8657
commit 1ff521f505
9 changed files with 130 additions and 52 deletions

View File

@@ -122,6 +122,8 @@ export class BuyModeSelector {
}
private displayAccountList(): void {
// Note: console.log is intentionally used here for interactive user prompts
// This is a CLI menu, not system logging - should go directly to stdout
console.log('\nAvailable accounts:')
console.log('─'.repeat(60))

View File

@@ -1,10 +1,10 @@
import { BrowserContext, Cookie } from 'rebrowser-playwright'
import { BrowserFingerprintWithHeaders } from 'fingerprint-generator'
import fs from 'fs'
import path from 'path'
import { BrowserContext, Cookie } from 'rebrowser-playwright'
import { Account } from '../interface/Account'
import { Config, ConfigSaveFingerprint, ConfigBrowser, ConfigScheduling } from '../interface/Config'
import { Config, ConfigBrowser, ConfigSaveFingerprint, ConfigScheduling } from '../interface/Config'
import { Util } from './Utils'
const utils = new Util()
@@ -71,7 +71,12 @@ function stripJsonComments(input: string): string {
// Normalize both legacy (flat) and new (nested) config schemas into the flat Config interface
function normalizeConfig(raw: unknown): Config {
// Using any here is necessary to support both legacy flat config and new nested config structures
// TYPE SAFETY NOTE: Using `any` here is necessary for backwards compatibility
// The config format has evolved from flat structure to nested structure over time
// We need to support both formats dynamically without knowing which one we'll receive
// Alternative approaches (discriminated unions, multiple interfaces) would require
// runtime type checking on every property access, making the code much more complex
// The validation happens implicitly through the Config interface return type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const n = (raw || {}) as any
@@ -345,6 +350,9 @@ export function loadAccounts(): Account[] {
if (!Array.isArray(parsed)) throw new Error('accounts must be an array')
// minimal shape validation
for (const entry of parsed) {
// TYPE SAFETY NOTE: Using `any` for account validation
// Accounts come from user-provided JSON with unknown structure
// We validate each property explicitly below rather than trusting the type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const a = entry as any
if (!a || typeof a.email !== 'string' || typeof a.password !== 'string') {

View File

@@ -1,9 +1,9 @@
import axios from 'axios'
import chalk from 'chalk'
import { Ntfy } from './Ntfy'
import { loadConfig } from './Load'
import { DISCORD } from '../constants'
import { loadConfig } from './Load'
import { Ntfy } from './Ntfy'
/**
* Safe error logger for catch blocks
@@ -95,7 +95,9 @@ async function sendBatch(url: string, buf: WebhookBuffer) {
} catch (error) {
// Re-queue failed batch at front and exit loop
buf.lines = chunk.concat(buf.lines)
console.error('[Webhook] live log delivery failed:', error)
// Note: Using stderr directly here to avoid circular dependency with log()
// This is an internal logger error that shouldn't go through the logging system
process.stderr.write(`[Webhook] live log delivery failed: ${error}\n`)
break
}
}
@@ -255,7 +257,8 @@ export function log(isMobile: boolean | 'main', title: string, message: string,
enqueueWebhookLog(liveUrl, cleanStr)
}
} catch (error) {
console.error('[Logger] Failed to enqueue webhook log:', error)
// Note: Using stderr directly to avoid recursion - this is an internal logger error
process.stderr.write(`[Logger] Failed to enqueue webhook log: ${error}\n`)
}
// Return an Error when logging an error so callers can `throw log(...)`

View File

@@ -10,9 +10,9 @@ export class Util {
const MAX_WAIT_MS = 3600000 // 1 hour max to prevent infinite waits
const MIN_WAIT_MS = 0
// Validate and clamp input
if (!Number.isFinite(ms)) {
throw new Error(`Invalid wait time: ${ms}. Must be a finite number.`)
// Validate and clamp input - explicit NaN check before isFinite
if (typeof ms !== 'number' || Number.isNaN(ms) || !Number.isFinite(ms)) {
throw new Error(`Invalid wait time: ${ms}. Must be a finite number (not NaN or Infinity).`)
}
const safeMs = Math.min(Math.max(MIN_WAIT_MS, ms), MAX_WAIT_MS)