fix(typescript): tighten TypeScript null safety and error handling across backend and ops UI

This commit is contained in:
2026-03-26 07:40:56 +00:00
parent 0195a21f30
commit 44f2a7f0a9
40 changed files with 414 additions and 451 deletions

View File

@@ -48,14 +48,14 @@ export class CacheCleaner {
this.isRunning = true;
// Run cleanup immediately on start
this.runCleanup().catch((error) => {
logger.log('error', `Initial cache cleanup failed: ${error.message}`);
this.runCleanup().catch((error: unknown) => {
logger.log('error', `Initial cache cleanup failed: ${(error as Error).message}`);
});
// Schedule periodic cleanup
this.cleanupInterval = setInterval(() => {
this.runCleanup().catch((error) => {
logger.log('error', `Cache cleanup failed: ${error.message}`);
this.runCleanup().catch((error: unknown) => {
logger.log('error', `Cache cleanup failed: ${(error as Error).message}`);
});
}, this.options.intervalMs);
@@ -113,8 +113,8 @@ export class CacheCleaner {
`Cache cleanup completed. Deleted ${totalDeleted} expired documents. ${summary || 'No deletions.'}`
);
}
} catch (error) {
logger.log('error', `Cache cleanup error: ${error.message}`);
} catch (error: unknown) {
logger.log('error', `Cache cleanup error: ${(error as Error).message}`);
throw error;
}
}
@@ -138,14 +138,14 @@ export class CacheCleaner {
try {
await doc.delete();
deletedCount++;
} catch (deleteError) {
logger.log('warn', `Failed to delete expired document: ${deleteError.message}`);
} catch (deleteError: unknown) {
logger.log('warn', `Failed to delete expired document: ${(deleteError as Error).message}`);
}
}
return deletedCount;
} catch (error) {
logger.log('error', `Error cleaning collection: ${error.message}`);
} catch (error: unknown) {
logger.log('error', `Error cleaning collection: ${(error as Error).message}`);
return 0;
}
}

View File

@@ -22,7 +22,7 @@ export abstract class CachedDocument<T extends CachedDocument<T>> extends plugin
* Timestamp when the document expires and should be cleaned up
* NOTE: Subclasses must add @svDb() decorator
*/
public expiresAt: Date;
public expiresAt!: Date;
/**
* Timestamp of last access (for LRU-style eviction if needed)

View File

@@ -23,8 +23,8 @@ export interface ICacheDbOptions {
export class CacheDb {
private static instance: CacheDb | null = null;
private localTsmDb: plugins.smartmongo.LocalTsmDb;
private smartdataDb: plugins.smartdata.SmartdataDb;
private localTsmDb!: plugins.smartmongo.LocalTsmDb;
private smartdataDb!: plugins.smartdata.SmartdataDb;
private options: Required<ICacheDbOptions>;
private isStarted: boolean = false;
@@ -89,8 +89,8 @@ export class CacheDb {
this.isStarted = true;
logger.log('info', `CacheDb started at ${this.options.storagePath}`);
} catch (error) {
logger.log('error', `Failed to start CacheDb: ${error.message}`);
} catch (error: unknown) {
logger.log('error', `Failed to start CacheDb: ${(error as Error).message}`);
throw error;
}
}
@@ -116,8 +116,8 @@ export class CacheDb {
this.isStarted = false;
logger.log('info', 'CacheDb stopped');
} catch (error) {
logger.log('error', `Error stopping CacheDb: ${error.message}`);
} catch (error: unknown) {
logger.log('error', `Error stopping CacheDb: ${(error as Error).message}`);
throw error;
}
}

View File

@@ -35,55 +35,55 @@ export class CachedEmail extends CachedDocument<CachedEmail> {
*/
@plugins.smartdata.unI()
@plugins.smartdata.svDb()
public id: string;
public id!: string;
/**
* Email message ID (RFC 822 Message-ID header)
*/
@plugins.smartdata.svDb()
public messageId: string;
public messageId!: string;
/**
* Sender email address (envelope from)
*/
@plugins.smartdata.svDb()
public from: string;
public from!: string;
/**
* Recipient email addresses
*/
@plugins.smartdata.svDb()
public to: string[];
public to!: string[];
/**
* CC recipients
*/
@plugins.smartdata.svDb()
public cc: string[];
public cc!: string[];
/**
* BCC recipients
*/
@plugins.smartdata.svDb()
public bcc: string[];
public bcc!: string[];
/**
* Email subject
*/
@plugins.smartdata.svDb()
public subject: string;
public subject!: string;
/**
* Raw RFC822 email content
*/
@plugins.smartdata.svDb()
public rawContent: string;
public rawContent!: string;
/**
* Current status of the email
*/
@plugins.smartdata.svDb()
public status: TCachedEmailStatus;
public status!: TCachedEmailStatus;
/**
* Number of delivery attempts
@@ -101,25 +101,25 @@ export class CachedEmail extends CachedDocument<CachedEmail> {
* Timestamp for next delivery attempt
*/
@plugins.smartdata.svDb()
public nextAttempt: Date;
public nextAttempt!: Date;
/**
* Last error message if delivery failed
*/
@plugins.smartdata.svDb()
public lastError: string;
public lastError!: string;
/**
* Timestamp when the email was successfully delivered
*/
@plugins.smartdata.svDb()
public deliveredAt: Date;
public deliveredAt!: Date;
/**
* Sender domain (for querying/filtering)
*/
@plugins.smartdata.svDb()
public senderDomain: string;
public senderDomain!: string;
/**
* Priority level (higher = more important)
@@ -131,7 +131,7 @@ export class CachedEmail extends CachedDocument<CachedEmail> {
* JSON-serialized route data
*/
@plugins.smartdata.svDb()
public routeData: string;
public routeData!: string;
/**
* DKIM signature status

View File

@@ -45,61 +45,61 @@ export class CachedIPReputation extends CachedDocument<CachedIPReputation> {
*/
@plugins.smartdata.unI()
@plugins.smartdata.svDb()
public ipAddress: string;
public ipAddress!: string;
/**
* Reputation score (0-100, higher = better)
*/
@plugins.smartdata.svDb()
public score: number;
public score!: number;
/**
* Whether the IP is flagged as spam source
*/
@plugins.smartdata.svDb()
public isSpam: boolean;
public isSpam!: boolean;
/**
* Whether the IP is a known proxy
*/
@plugins.smartdata.svDb()
public isProxy: boolean;
public isProxy!: boolean;
/**
* Whether the IP is a Tor exit node
*/
@plugins.smartdata.svDb()
public isTor: boolean;
public isTor!: boolean;
/**
* Whether the IP is a VPN endpoint
*/
@plugins.smartdata.svDb()
public isVPN: boolean;
public isVPN!: boolean;
/**
* Country code (ISO 3166-1 alpha-2)
*/
@plugins.smartdata.svDb()
public country: string;
public country!: string;
/**
* Autonomous System Number
*/
@plugins.smartdata.svDb()
public asn: string;
public asn!: string;
/**
* Organization name
*/
@plugins.smartdata.svDb()
public org: string;
public org!: string;
/**
* List of blacklists the IP appears on
*/
@plugins.smartdata.svDb()
public blacklists: string[];
public blacklists!: string[];
/**
* Number of times this IP has been checked