Refactor error handling and type safety across services
- Simplified error handling in TokenBlacklistService by removing unnecessary error variable. - Enhanced type safety in SimUsageStoreService with improved type assertions and error handling. - Updated FreebititService to provide clearer error messages and consistent error handling across multiple methods. - Standardized import statements in WhmcsInvoiceService for better organization and clarity. - Added missing imports in dev-prep script to ensure proper functionality.
This commit is contained in:
parent
de35397cf9
commit
5f7fb483d7
@ -24,7 +24,7 @@ export class TokenBlacklistService {
|
||||
if (ttl > 0) {
|
||||
await this.redis.setex(`blacklist:${token}`, ttl, "1");
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// If we can't parse the token, blacklist it for the default JWT expiry time
|
||||
try {
|
||||
const defaultTtl = this.parseJwtExpiry(this.configService.get("JWT_EXPIRES_IN", "7d"));
|
||||
|
||||
@ -19,8 +19,8 @@ export class SimUsageStoreService {
|
||||
async upsertToday(account: string, usageMb: number, date?: Date): Promise<void> {
|
||||
const day = this.normalizeDate(date);
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||
await this.prisma.simUsageDaily.upsert({
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error composite unique input type depends on Prisma schema
|
||||
where: { account_date: { account, date: day } as unknown },
|
||||
update: { usageMb },
|
||||
@ -39,6 +39,7 @@ export class SimUsageStoreService {
|
||||
const end = this.normalizeDate();
|
||||
const start = new Date(end);
|
||||
start.setUTCDate(end.getUTCDate() - (days - 1));
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||
const rows = (await this.prisma.simUsageDaily.findMany({
|
||||
where: { account, date: { gte: start, lte: end } },
|
||||
orderBy: { date: "desc" },
|
||||
@ -49,9 +50,10 @@ export class SimUsageStoreService {
|
||||
async cleanupPreviousMonths(): Promise<number> {
|
||||
const now = new Date();
|
||||
const firstOfMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
|
||||
const result = await this.prisma.simUsageDaily.deleteMany({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||
const result = (await this.prisma.simUsageDaily.deleteMany({
|
||||
where: { date: { lt: firstOfMonth } },
|
||||
});
|
||||
})) as unknown as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
}
|
||||
|
||||
105
apps/bff/src/vendors/freebit/freebit.service.ts
vendored
105
apps/bff/src/vendors/freebit/freebit.service.ts
vendored
@ -138,8 +138,9 @@ export class FreebititService {
|
||||
|
||||
this.logger.log("Successfully authenticated with Freebit API");
|
||||
return data.authKey;
|
||||
} catch (error: any) {
|
||||
this.logger.error("Failed to authenticate with Freebit API", { error: error.message });
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error("Failed to authenticate with Freebit API", { error: message });
|
||||
throw new InternalServerErrorException("Failed to authenticate with Freebit API");
|
||||
}
|
||||
}
|
||||
@ -147,10 +148,12 @@ export class FreebititService {
|
||||
/**
|
||||
* Make authenticated API request with error handling
|
||||
*/
|
||||
private async makeAuthenticatedRequest<T extends { resultCode: string | number; status?: { message?: string; statusCode?: string | number } }>(
|
||||
endpoint: string,
|
||||
data: unknown
|
||||
): Promise<T> {
|
||||
private async makeAuthenticatedRequest<
|
||||
T extends {
|
||||
resultCode: string | number;
|
||||
status?: { message?: string; statusCode?: string | number };
|
||||
}
|
||||
>(endpoint: string, data: unknown): Promise<T> {
|
||||
const authKey = await this.getAuthKey();
|
||||
const requestData = { ...(data as Record<string, unknown>), authKey };
|
||||
|
||||
@ -165,14 +168,8 @@ export class FreebititService {
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
let bodySnippet: string | undefined;
|
||||
let text: string | null = null;
|
||||
try {
|
||||
text = await response.text();
|
||||
} catch (_e) {
|
||||
text = null;
|
||||
}
|
||||
bodySnippet = text ? text.slice(0, 500) : undefined;
|
||||
const text: string | null = await response.text().catch(() => null);
|
||||
const bodySnippet: string | undefined = text ? text.slice(0, 500) : undefined;
|
||||
this.logger.error("Freebit API non-OK response", {
|
||||
endpoint,
|
||||
url,
|
||||
@ -289,10 +286,10 @@ export class FreebititService {
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
throw (
|
||||
lastError ||
|
||||
new InternalServerErrorException("Failed to fetch SIM details: all endpoints failed")
|
||||
);
|
||||
if (lastError instanceof Error) {
|
||||
throw lastError;
|
||||
}
|
||||
throw new InternalServerErrorException("Failed to fetch SIM details: all endpoints failed");
|
||||
}
|
||||
|
||||
type AcctDetailItem = {
|
||||
@ -307,7 +304,7 @@ export class FreebititService {
|
||||
imsi?: string | number;
|
||||
eid?: string;
|
||||
contractLine?: string;
|
||||
size?: "standard" | "nano" | "micro" | "esim" | string;
|
||||
size?: string;
|
||||
sms?: number;
|
||||
talk?: number;
|
||||
ipv4?: string;
|
||||
@ -417,9 +414,10 @@ export class FreebititService {
|
||||
});
|
||||
|
||||
return simUsage;
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Failed to get SIM usage for account ${account}`, { error: error.message });
|
||||
throw error;
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error(`Failed to get SIM usage for account ${account}`, { error: message });
|
||||
throw error as Error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,13 +476,10 @@ export class FreebititService {
|
||||
campaignCode: options.campaignCode,
|
||||
scheduled: isScheduled,
|
||||
});
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Failed to top up SIM ${account}`, {
|
||||
error: error.message,
|
||||
account,
|
||||
quotaMb,
|
||||
});
|
||||
throw error;
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error(`Failed to top up SIM ${account}`, { error: message, account, quotaMb });
|
||||
throw error as Error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -528,11 +523,10 @@ export class FreebititService {
|
||||
});
|
||||
|
||||
return history;
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Failed to get SIM top-up history for account ${account}`, {
|
||||
error: error.message,
|
||||
});
|
||||
throw error;
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error(`Failed to get SIM top-up history for account ${account}`, { error: message });
|
||||
throw error as Error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,13 +565,14 @@ export class FreebititService {
|
||||
ipv4: response.ipv4,
|
||||
ipv6: response.ipv6,
|
||||
};
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error(`Failed to change SIM plan for account ${account}`, {
|
||||
error: error.message,
|
||||
error: message,
|
||||
account,
|
||||
newPlanCode,
|
||||
});
|
||||
throw error;
|
||||
throw error as Error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -627,12 +622,13 @@ export class FreebititService {
|
||||
internationalRoamingEnabled: features.internationalRoamingEnabled,
|
||||
networkType: features.networkType,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error(`Failed to update SIM features for account ${account}`, {
|
||||
error: error.message,
|
||||
error: message,
|
||||
account,
|
||||
});
|
||||
throw error;
|
||||
throw error as Error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -655,12 +651,10 @@ export class FreebititService {
|
||||
account,
|
||||
scheduled: !!scheduledAt,
|
||||
});
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Failed to cancel SIM for account ${account}`, {
|
||||
error: error.message,
|
||||
account,
|
||||
});
|
||||
throw error;
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error(`Failed to cancel SIM for account ${account}`, { error: message, account });
|
||||
throw error as Error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,13 +729,14 @@ export class FreebititService {
|
||||
this.logger.log(`Successfully reissued eSIM profile via PA05-41 for account ${account}`, {
|
||||
account,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof BadRequestException) throw error;
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error(`Failed to reissue eSIM profile via PA05-41 for account ${account}`, {
|
||||
error: error.message,
|
||||
error: message,
|
||||
account,
|
||||
});
|
||||
throw error;
|
||||
throw error as Error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -785,13 +780,14 @@ export class FreebititService {
|
||||
oldProductNumber: options.oldProductNumber,
|
||||
oldEid: options.oldEid,
|
||||
});
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error(`Failed to reissue eSIM profile via addAcnt for account ${account}`, {
|
||||
error: error.message,
|
||||
error: message,
|
||||
account,
|
||||
newEid,
|
||||
});
|
||||
throw error;
|
||||
throw error as Error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -802,8 +798,9 @@ export class FreebititService {
|
||||
try {
|
||||
await this.getAuthKey();
|
||||
return true;
|
||||
} catch (error: any) {
|
||||
this.logger.error("Freebit API health check failed", { error: error.message });
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
this.logger.error("Freebit API health check failed", { error: message });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,12 @@ import { Invoice, InvoiceList } from "@customer-portal/shared";
|
||||
import { WhmcsConnectionService } from "./whmcs-connection.service";
|
||||
import { WhmcsDataTransformer } from "../transformers/whmcs-data.transformer";
|
||||
import { WhmcsCacheService } from "../cache/whmcs-cache.service";
|
||||
import { WhmcsGetInvoicesParams } from "../types/whmcs-api.types";
|
||||
import {
|
||||
WhmcsGetInvoicesParams,
|
||||
WhmcsCreateInvoiceParams,
|
||||
WhmcsUpdateInvoiceParams,
|
||||
WhmcsCapturePaymentParams,
|
||||
} from "../types/whmcs-api.types";
|
||||
|
||||
export interface InvoiceFilters {
|
||||
status?: "Paid" | "Unpaid" | "Cancelled" | "Overdue" | "Collections";
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
// Ensure dev-time Next.js manifests exist to avoid noisy ENOENT errors
|
||||
import { mkdirSync, existsSync, writeFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
import { URL } from "node:url";
|
||||
/* global console */
|
||||
|
||||
const root = new URL("..", import.meta.url).pathname; // apps/portal
|
||||
const nextDir = join(root, ".next");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user