diff --git a/apps/bff/src/integrations/freebit/interfaces/freebit.types.ts b/apps/bff/src/integrations/freebit/interfaces/freebit.types.ts
index b8ff72c4..62fc96bf 100644
--- a/apps/bff/src/integrations/freebit/interfaces/freebit.types.ts
+++ b/apps/bff/src/integrations/freebit/interfaces/freebit.types.ts
@@ -92,6 +92,7 @@ export interface FreebitTopUpRequest {
quota: number; // KB units (e.g., 102400 for 100MB)
quotaCode?: string; // Campaign code
expire?: string; // YYYYMMDD format
+ runTime?: string; // Scheduled execution time (YYYYMMDDHHmm)
}
export interface FreebitTopUpResponse {
@@ -235,7 +236,13 @@ export interface FreebitCancelAccountResponse {
export interface FreebitEsimReissueRequest {
authKey: string;
- account: string;
+ requestDatas: Array<{
+ kind: "MVNO";
+ account: string;
+ newEid?: string;
+ oldEid?: string;
+ planCode?: string;
+ }>;
}
export interface FreebitEsimReissueResponse {
diff --git a/apps/bff/src/integrations/freebit/services/freebit-operations.service.ts b/apps/bff/src/integrations/freebit/services/freebit-operations.service.ts
index 7be7f482..37a6393b 100644
--- a/apps/bff/src/integrations/freebit/services/freebit-operations.service.ts
+++ b/apps/bff/src/integrations/freebit/services/freebit-operations.service.ts
@@ -144,7 +144,7 @@ export class FreebitOperationsService {
): Promise {
try {
const quotaKb = Math.round(quotaMb * 1024);
- const request: Omit = {
+ const baseRequest: Omit = {
account,
quota: quotaKb,
quotaCode: options.campaignCode,
@@ -153,9 +153,7 @@ export class FreebitOperationsService {
const scheduled = !!options.scheduledAt;
const endpoint = scheduled ? "/mvno/eachQuota/" : "/master/addSpec/";
- if (scheduled) {
- (request as any).runTime = options.scheduledAt;
- }
+ const request = scheduled ? { ...baseRequest, runTime: options.scheduledAt } : baseRequest;
await this.client.makeAuthenticatedRequest(
endpoint,
@@ -348,7 +346,7 @@ export class FreebitOperationsService {
try {
const request: Omit = {
requestDatas: [{ kind: "MVNO", account }],
- } as any;
+ };
await this.client.makeAuthenticatedRequest(
"/mvno/reissueEsim/",
diff --git a/apps/bff/src/integrations/freebit/services/freebit-orchestrator.service.ts b/apps/bff/src/integrations/freebit/services/freebit-orchestrator.service.ts
index 0b4fcdf9..1b1a10e6 100644
--- a/apps/bff/src/integrations/freebit/services/freebit-orchestrator.service.ts
+++ b/apps/bff/src/integrations/freebit/services/freebit-orchestrator.service.ts
@@ -1,12 +1,7 @@
import { Injectable } from "@nestjs/common";
import { FreebitOperationsService } from "./freebit-operations.service";
import { FreebitMapperService } from "./freebit-mapper.service";
-import type {
- SimDetails,
- SimUsage,
- SimTopUpHistory,
- FreebitEsimAddAccountRequest,
-} from "../interfaces/freebit.types";
+import type { SimDetails, SimUsage, SimTopUpHistory } from "../interfaces/freebit.types";
@Injectable()
export class FreebitOrchestratorService {
diff --git a/apps/bff/src/integrations/salesforce/events/pubsub.subscriber.ts b/apps/bff/src/integrations/salesforce/events/pubsub.subscriber.ts
index e58fb0d3..9f962de6 100644
--- a/apps/bff/src/integrations/salesforce/events/pubsub.subscriber.ts
+++ b/apps/bff/src/integrations/salesforce/events/pubsub.subscriber.ts
@@ -15,12 +15,13 @@ import type {
SalesforcePubSubError,
SalesforcePubSubSubscription,
SalesforcePubSubCallbackType,
+ SalesforcePubSubUnknownData,
} from "../types/pubsub-events.types";
type SubscribeCallback = (
subscription: SalesforcePubSubSubscription,
callbackType: SalesforcePubSubCallbackType,
- data: SalesforcePubSubEvent | SalesforcePubSubError | unknown
+ data: SalesforcePubSubEvent | SalesforcePubSubError | SalesforcePubSubUnknownData
) => void | Promise;
interface PubSubClient {
diff --git a/apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts b/apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts
index d4db9c62..948aaa35 100644
--- a/apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts
+++ b/apps/bff/src/integrations/salesforce/types/pubsub-events.types.ts
@@ -33,8 +33,10 @@ export interface SalesforcePubSubError {
export type SalesforcePubSubCallbackType = "data" | "event" | "grpcstatus" | "end" | "error";
+export type SalesforcePubSubUnknownData = Record | null | undefined;
+
export interface SalesforcePubSubCallback {
subscription: SalesforcePubSubSubscription;
callbackType: SalesforcePubSubCallbackType;
- data: SalesforcePubSubEvent | SalesforcePubSubError | unknown;
+ data: SalesforcePubSubEvent | SalesforcePubSubError | SalesforcePubSubUnknownData;
}
diff --git a/apps/bff/src/integrations/whmcs/connection/services/whmcs-connection-orchestrator.service.ts b/apps/bff/src/integrations/whmcs/connection/services/whmcs-connection-orchestrator.service.ts
index 6a504ad7..ea622763 100644
--- a/apps/bff/src/integrations/whmcs/connection/services/whmcs-connection-orchestrator.service.ts
+++ b/apps/bff/src/integrations/whmcs/connection/services/whmcs-connection-orchestrator.service.ts
@@ -6,7 +6,6 @@ import { WhmcsHttpClientService } from "./whmcs-http-client.service";
import { WhmcsErrorHandlerService } from "./whmcs-error-handler.service";
import { WhmcsApiMethodsService } from "./whmcs-api-methods.service";
import type {
- WhmcsApiResponse,
WhmcsErrorResponse,
WhmcsAddClientParams,
WhmcsValidateLoginParams,
diff --git a/apps/bff/src/integrations/whmcs/connection/services/whmcs-error-handler.service.ts b/apps/bff/src/integrations/whmcs/connection/services/whmcs-error-handler.service.ts
index ead43d6e..7b9fdab9 100644
--- a/apps/bff/src/integrations/whmcs/connection/services/whmcs-error-handler.service.ts
+++ b/apps/bff/src/integrations/whmcs/connection/services/whmcs-error-handler.service.ts
@@ -44,7 +44,7 @@ export class WhmcsErrorHandlerService {
/**
* Handle general request errors (network, timeout, etc.)
*/
- handleRequestError(error: unknown, action: string, params: Record): never {
+ handleRequestError(error: unknown, action: string, _params: Record): never {
const message = getErrorMessage(error);
if (this.isTimeoutError(error)) {
diff --git a/apps/bff/src/integrations/whmcs/connection/services/whmcs-http-client.service.ts b/apps/bff/src/integrations/whmcs/connection/services/whmcs-http-client.service.ts
index 17f0a8e4..7368b9f9 100644
--- a/apps/bff/src/integrations/whmcs/connection/services/whmcs-http-client.service.ts
+++ b/apps/bff/src/integrations/whmcs/connection/services/whmcs-http-client.service.ts
@@ -189,14 +189,53 @@ export class WhmcsHttpClientService {
// Add parameters
for (const [key, value] of Object.entries(params)) {
- if (value !== undefined && value !== null) {
- formData.append(key, String(value));
+ if (value === undefined || value === null) {
+ continue;
}
+
+ const serialized = this.serializeParamValue(value);
+ formData.append(key, serialized);
}
return formData.toString();
}
+ private serializeParamValue(value: unknown): string {
+ if (typeof value === "string") {
+ return value;
+ }
+
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
+ return String(value);
+ }
+
+ if (value instanceof Date) {
+ return value.toISOString();
+ }
+
+ if (Array.isArray(value)) {
+ return value.map(entry => this.serializeParamValue(entry)).join(",");
+ }
+
+ if (typeof value === "object" && value !== null) {
+ try {
+ return JSON.stringify(value);
+ } catch {
+ return Object.prototype.toString.call(value);
+ }
+ }
+
+ if (typeof value === "symbol") {
+ return value.description ? `Symbol(${value.description})` : "Symbol()";
+ }
+
+ if (typeof value === "function") {
+ return value.name ? `[Function ${value.name}]` : "[Function anonymous]";
+ }
+
+ return Object.prototype.toString.call(value);
+ }
+
/**
* Parse WHMCS API response
*/
diff --git a/apps/bff/src/integrations/whmcs/services/whmcs-invoice.service.ts b/apps/bff/src/integrations/whmcs/services/whmcs-invoice.service.ts
index 14b66704..24f9904c 100644
--- a/apps/bff/src/integrations/whmcs/services/whmcs-invoice.service.ts
+++ b/apps/bff/src/integrations/whmcs/services/whmcs-invoice.service.ts
@@ -4,7 +4,7 @@ import { Injectable, NotFoundException, Inject } from "@nestjs/common";
import { Invoice, InvoiceList } from "@customer-portal/domain";
import {
invoiceListSchema,
- invoiceSchema as invoiceEntitySchema,
+ invoiceSchema,
} from "@customer-portal/domain/validation/shared/entities";
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service";
import { InvoiceTransformerService } from "../transformers/services/invoice-transformer.service";
@@ -15,9 +15,6 @@ import {
WhmcsCreateInvoiceParams,
WhmcsUpdateInvoiceParams,
WhmcsCapturePaymentParams,
- WhmcsCreateInvoiceResponse,
- WhmcsUpdateInvoiceResponse,
- WhmcsCapturePaymentResponse,
} from "../types/whmcs-api.types";
export interface InvoiceFilters {
@@ -88,7 +85,7 @@ export class WhmcsInvoiceService {
this.logger.log(
`Fetched ${result.invoices.length} invoices for client ${clientId}, page ${page}`
);
- return result;
+ return result as InvoiceList;
} catch (error) {
this.logger.error(`Failed to fetch invoices for client ${clientId}`, {
error: getErrorMessage(error),
@@ -117,7 +114,7 @@ export class WhmcsInvoiceService {
try {
// Get detailed invoice with items
const detailedInvoice = await this.getInvoiceById(clientId, userId, invoice.id);
- const parseResult = invoiceEntitySchema.safeParse(detailedInvoice);
+ const parseResult = invoiceSchema.safeParse(detailedInvoice);
if (!parseResult.success) {
this.logger.error("Failed to parse detailed invoice", {
error: parseResult.error.issues,
@@ -139,7 +136,7 @@ export class WhmcsInvoiceService {
);
const result: InvoiceList = {
- invoices: invoicesWithItems,
+ invoices: invoicesWithItems as Invoice[],
pagination: invoiceList.pagination,
};
@@ -184,7 +181,7 @@ export class WhmcsInvoiceService {
// Transform invoice
const invoice = this.invoiceTransformer.transformInvoice(response);
- const parseResult = invoiceEntitySchema.safeParse(invoice);
+ const parseResult = invoiceSchema.safeParse(invoice);
if (!parseResult.success) {
throw new Error(`Invalid invoice data after transformation`);
}
@@ -232,8 +229,8 @@ export class WhmcsInvoiceService {
for (const whmcsInvoice of response.invoices.invoice) {
try {
const transformed = this.invoiceTransformer.transformInvoice(whmcsInvoice);
- const parsed = invoiceEntitySchema.parse(transformed);
- invoices.push(parsed);
+ const parsed = invoiceSchema.parse(transformed);
+ invoices.push(parsed as Invoice);
} catch (error) {
this.logger.error(`Failed to transform invoice ${whmcsInvoice.id}`, {
error: getErrorMessage(error),
diff --git a/apps/bff/src/integrations/whmcs/transformers/services/invoice-transformer.service.ts b/apps/bff/src/integrations/whmcs/transformers/services/invoice-transformer.service.ts
index cbbc03e3..0c8a2595 100644
--- a/apps/bff/src/integrations/whmcs/transformers/services/invoice-transformer.service.ts
+++ b/apps/bff/src/integrations/whmcs/transformers/services/invoice-transformer.service.ts
@@ -1,11 +1,7 @@
import { Injectable, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { Invoice, InvoiceItem as BaseInvoiceItem } from "@customer-portal/domain";
-import type {
- WhmcsInvoice,
- WhmcsInvoiceItems,
- WhmcsCustomField,
-} from "../../types/whmcs-api.types";
+import type { WhmcsInvoice, WhmcsInvoiceItems } from "../../types/whmcs-api.types";
import { DataUtils } from "../utils/data-utils";
import { StatusNormalizer } from "../utils/status-normalizer";
import { TransformationValidator } from "../validators/transformation-validator";
diff --git a/apps/bff/src/integrations/whmcs/transformers/services/subscription-transformer.service.ts b/apps/bff/src/integrations/whmcs/transformers/services/subscription-transformer.service.ts
index 43248b4b..01b4bbba 100644
--- a/apps/bff/src/integrations/whmcs/transformers/services/subscription-transformer.service.ts
+++ b/apps/bff/src/integrations/whmcs/transformers/services/subscription-transformer.service.ts
@@ -131,7 +131,7 @@ export class SubscriptionTransformerService {
private normalizeFieldName(name: string): string {
return name
.toLowerCase()
- .replace(/[^a-z0-9]+(.)/g, (_, char) => char.toUpperCase())
+ .replace(/[^a-z0-9]+(.)/g, (_match: string, char: string) => char.toUpperCase())
.replace(/^[^a-z]+/, "");
}
diff --git a/apps/bff/src/integrations/whmcs/transformers/services/whmcs-transformer-orchestrator.service.ts b/apps/bff/src/integrations/whmcs/transformers/services/whmcs-transformer-orchestrator.service.ts
index 48f4d849..3721fbdf 100644
--- a/apps/bff/src/integrations/whmcs/transformers/services/whmcs-transformer-orchestrator.service.ts
+++ b/apps/bff/src/integrations/whmcs/transformers/services/whmcs-transformer-orchestrator.service.ts
@@ -30,7 +30,7 @@ export class WhmcsTransformerOrchestratorService {
/**
* Transform WHMCS invoice to our standard Invoice format
*/
- async transformInvoice(whmcsInvoice: WhmcsInvoice): Promise {
+ transformInvoice(whmcsInvoice: WhmcsInvoice): Invoice {
try {
return this.invoiceTransformer.transformInvoice(whmcsInvoice);
} catch (error) {
@@ -60,7 +60,7 @@ export class WhmcsTransformerOrchestratorService {
/**
* Transform WHMCS product/service to our standard Subscription format
*/
- async transformSubscription(whmcsProduct: WhmcsProduct): Promise {
+ transformSubscription(whmcsProduct: WhmcsProduct): Subscription {
try {
return this.subscriptionTransformer.transformSubscription(whmcsProduct);
} catch (error) {
@@ -90,7 +90,7 @@ export class WhmcsTransformerOrchestratorService {
/**
* Transform WHMCS payment gateway to shared PaymentGateway interface
*/
- async transformPaymentGateway(whmcsGateway: WhmcsPaymentGateway): Promise {
+ transformPaymentGateway(whmcsGateway: WhmcsPaymentGateway): PaymentGateway {
try {
return this.paymentTransformer.transformPaymentGateway(whmcsGateway);
} catch (error) {
@@ -120,7 +120,7 @@ export class WhmcsTransformerOrchestratorService {
/**
* Transform WHMCS payment method to shared PaymentMethod interface
*/
- async transformPaymentMethod(whmcsPayMethod: WhmcsPaymentMethod): Promise {
+ transformPaymentMethod(whmcsPayMethod: WhmcsPaymentMethod): PaymentMethod {
try {
return this.paymentTransformer.transformPaymentMethod(whmcsPayMethod);
} catch (error) {
@@ -150,16 +150,16 @@ export class WhmcsTransformerOrchestratorService {
/**
* Transform multiple invoices in batch with error handling
*/
- async transformInvoices(whmcsInvoices: WhmcsInvoice[]): Promise<{
+ transformInvoices(whmcsInvoices: WhmcsInvoice[]): {
successful: Invoice[];
failed: Array<{ invoice: WhmcsInvoice; error: string }>;
- }> {
+ } {
const successful: Invoice[] = [];
const failed: Array<{ invoice: WhmcsInvoice; error: string }> = [];
for (const whmcsInvoice of whmcsInvoices) {
try {
- const transformed = await this.transformInvoice(whmcsInvoice);
+ const transformed = this.transformInvoice(whmcsInvoice);
successful.push(transformed);
} catch (error) {
failed.push({
@@ -181,16 +181,16 @@ export class WhmcsTransformerOrchestratorService {
/**
* Transform multiple subscriptions in batch with error handling
*/
- async transformSubscriptions(whmcsProducts: WhmcsProduct[]): Promise<{
+ transformSubscriptions(whmcsProducts: WhmcsProduct[]): {
successful: Subscription[];
failed: Array<{ product: WhmcsProduct; error: string }>;
- }> {
+ } {
const successful: Subscription[] = [];
const failed: Array<{ product: WhmcsProduct; error: string }> = [];
for (const whmcsProduct of whmcsProducts) {
try {
- const transformed = await this.transformSubscription(whmcsProduct);
+ const transformed = this.transformSubscription(whmcsProduct);
successful.push(transformed);
} catch (error) {
failed.push({
@@ -212,16 +212,16 @@ export class WhmcsTransformerOrchestratorService {
/**
* Transform multiple payment methods in batch with error handling
*/
- async transformPaymentMethods(whmcsPayMethods: WhmcsPaymentMethod[]): Promise<{
+ transformPaymentMethods(whmcsPayMethods: WhmcsPaymentMethod[]): {
successful: PaymentMethod[];
failed: Array<{ payMethod: WhmcsPaymentMethod; error: string }>;
- }> {
+ } {
const successful: PaymentMethod[] = [];
const failed: Array<{ payMethod: WhmcsPaymentMethod; error: string }> = [];
for (const whmcsPayMethod of whmcsPayMethods) {
try {
- const transformed = await this.transformPaymentMethod(whmcsPayMethod);
+ const transformed = this.transformPaymentMethod(whmcsPayMethod);
successful.push(transformed);
} catch (error) {
failed.push({
@@ -243,16 +243,16 @@ export class WhmcsTransformerOrchestratorService {
/**
* Transform multiple payment gateways in batch with error handling
*/
- async transformPaymentGateways(whmcsGateways: WhmcsPaymentGateway[]): Promise<{
+ transformPaymentGateways(whmcsGateways: WhmcsPaymentGateway[]): {
successful: PaymentGateway[];
failed: Array<{ gateway: WhmcsPaymentGateway; error: string }>;
- }> {
+ } {
const successful: PaymentGateway[] = [];
const failed: Array<{ gateway: WhmcsPaymentGateway; error: string }> = [];
for (const whmcsGateway of whmcsGateways) {
try {
- const transformed = await this.transformPaymentGateway(whmcsGateway);
+ const transformed = this.transformPaymentGateway(whmcsGateway);
successful.push(transformed);
} catch (error) {
failed.push({
diff --git a/apps/bff/src/integrations/whmcs/transformers/utils/data-utils.ts b/apps/bff/src/integrations/whmcs/transformers/utils/data-utils.ts
index 43a23aad..d119b353 100644
--- a/apps/bff/src/integrations/whmcs/transformers/utils/data-utils.ts
+++ b/apps/bff/src/integrations/whmcs/transformers/utils/data-utils.ts
@@ -126,18 +126,59 @@ export class DataUtils {
if (!customFields) return undefined;
// Try exact match first
- if (customFields[fieldName]) {
- return String(customFields[fieldName]);
+ const directValue = DataUtils.toStringValue(customFields[fieldName]);
+ if (directValue !== undefined) {
+ return directValue;
}
// Try case-insensitive match
const lowerFieldName = fieldName.toLowerCase();
for (const [key, value] of Object.entries(customFields)) {
if (key.toLowerCase() === lowerFieldName) {
- return String(value);
+ return DataUtils.toStringValue(value);
}
}
return undefined;
}
+
+ private static toStringValue(value: unknown): string | undefined {
+ if (value === undefined || value === null) {
+ return undefined;
+ }
+
+ if (typeof value === "string") {
+ return value;
+ }
+
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
+ return String(value);
+ }
+
+ if (value instanceof Date) {
+ return value.toISOString();
+ }
+
+ if (Array.isArray(value)) {
+ return value.map(entry => DataUtils.toStringValue(entry) ?? "").join(",");
+ }
+
+ if (typeof value === "object") {
+ try {
+ return JSON.stringify(value);
+ } catch {
+ return Object.prototype.toString.call(value);
+ }
+ }
+
+ if (typeof value === "symbol") {
+ return value.description ? `Symbol(${value.description})` : "Symbol()";
+ }
+
+ if (typeof value === "function") {
+ return value.name ? `[Function ${value.name}]` : "[Function anonymous]";
+ }
+
+ return Object.prototype.toString.call(value);
+ }
}
diff --git a/apps/bff/src/main.ts b/apps/bff/src/main.ts
index f08a3bca..283f2d5d 100644
--- a/apps/bff/src/main.ts
+++ b/apps/bff/src/main.ts
@@ -1,3 +1,4 @@
+import "tsconfig-paths/register";
import { Logger, type INestApplication } from "@nestjs/common";
import { bootstrap } from "./app/bootstrap";
diff --git a/apps/bff/src/modules/invoices/invoices.controller.ts b/apps/bff/src/modules/invoices/invoices.controller.ts
index 360ccc32..cc57346e 100644
--- a/apps/bff/src/modules/invoices/invoices.controller.ts
+++ b/apps/bff/src/modules/invoices/invoices.controller.ts
@@ -173,10 +173,10 @@ export class InvoicesController {
@ApiParam({ name: "id", type: Number, description: "Invoice ID" })
@ApiOkResponse({ description: "List of related subscriptions" })
@ApiResponse({ status: 404, description: "Invoice not found" })
- async getInvoiceSubscriptions(
+ getInvoiceSubscriptions(
@Request() req: AuthenticatedRequest,
@Param("id", ParseIntPipe) invoiceId: number
- ): Promise {
+ ): Subscription[] {
if (invoiceId <= 0) {
throw new BadRequestException("Invoice ID must be a positive number");
}
diff --git a/apps/bff/src/modules/invoices/services/invoices-orchestrator.service.ts b/apps/bff/src/modules/invoices/services/invoices-orchestrator.service.ts
index 267f2e16..d3ded4ff 100644
--- a/apps/bff/src/modules/invoices/services/invoices-orchestrator.service.ts
+++ b/apps/bff/src/modules/invoices/services/invoices-orchestrator.service.ts
@@ -1,13 +1,6 @@
import { Injectable, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
-import {
- Invoice,
- InvoiceList,
- InvoiceSsoLink,
- InvoicePaymentLink,
- PaymentMethodList,
- PaymentGatewayList,
-} from "@customer-portal/domain";
+import { Invoice, InvoiceList } from "@customer-portal/domain";
import { InvoiceRetrievalService } from "./invoice-retrieval.service";
import { InvoiceHealthService } from "./invoice-health.service";
import { InvoiceValidatorService } from "../validators/invoice-validator.service";
diff --git a/apps/bff/src/modules/subscriptions/sim-management.service.ts b/apps/bff/src/modules/subscriptions/sim-management.service.ts
index b63ab6b5..a1fc6bad 100644
--- a/apps/bff/src/modules/subscriptions/sim-management.service.ts
+++ b/apps/bff/src/modules/subscriptions/sim-management.service.ts
@@ -13,6 +13,7 @@ import type {
SimTopUpHistoryRequest,
SimFeaturesUpdateRequest,
} from "./sim-management/types/sim-requests.types";
+import type { SimNotificationContext } from "./sim-management/interfaces/sim-base.interface";
@Injectable()
export class SimManagementService {
@@ -25,9 +26,9 @@ export class SimManagementService {
private async notifySimAction(
action: string,
status: "SUCCESS" | "ERROR",
- context: Record
+ context: SimNotificationContext
): Promise {
- return this.simNotification.notifySimAction(action, status, context as any);
+ return this.simNotification.notifySimAction(action, status, context);
}
/**
diff --git a/apps/bff/src/modules/subscriptions/subscriptions.service.ts b/apps/bff/src/modules/subscriptions/subscriptions.service.ts
index 4b750f2d..89bd7aef 100644
--- a/apps/bff/src/modules/subscriptions/subscriptions.service.ts
+++ b/apps/bff/src/modules/subscriptions/subscriptions.service.ts
@@ -6,7 +6,7 @@ import { WhmcsService } from "@bff/integrations/whmcs/whmcs.service";
import { MappingsService } from "@bff/modules/id-mappings/mappings.service";
import { Logger } from "nestjs-pino";
import { z } from "zod";
-import { subscriptionSchema } from "@customer-portal/domain/validation/shared/entities";
+import { subscriptionSchema } from "@customer-portal/domain";
import type {
WhmcsProduct,
WhmcsProductsResponse,
diff --git a/apps/bff/tsconfig.build.json b/apps/bff/tsconfig.build.json
index b0b3023c..3796e8d6 100644
--- a/apps/bff/tsconfig.build.json
+++ b/apps/bff/tsconfig.build.json
@@ -13,7 +13,6 @@
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "test", "**/*.spec.ts"],
"references": [
- { "path": "../../packages/domain" },
- { "path": "../../packages/validation" }
+ { "path": "../../packages/domain" }
]
}
diff --git a/apps/portal/scripts/stubs/core-api.ts b/apps/portal/scripts/stubs/core-api.ts
index df6d3690..a21dca65 100644
--- a/apps/portal/scripts/stubs/core-api.ts
+++ b/apps/portal/scripts/stubs/core-api.ts
@@ -3,14 +3,14 @@ export type PostCall = [path: string, options?: unknown];
export const postCalls: PostCall[] = [];
export const apiClient = {
- POST: async (path: string, options?: unknown) => {
+ POST: (path: string, options?: unknown) => {
postCalls.push([path, options]);
- return { data: null } as const;
+ return Promise.resolve({ data: null } as const);
},
- GET: async () => ({ data: null }) as const,
- PUT: async () => ({ data: null }) as const,
- PATCH: async () => ({ data: null }) as const,
- DELETE: async () => ({ data: null }) as const,
+ GET: () => Promise.resolve({ data: null } as const),
+ PUT: () => Promise.resolve({ data: null } as const),
+ PATCH: () => Promise.resolve({ data: null } as const),
+ DELETE: () => Promise.resolve({ data: null } as const),
};
export const configureApiClientAuth = () => undefined;
diff --git a/apps/portal/scripts/test-request-password-reset.cjs b/apps/portal/scripts/test-request-password-reset.cjs
index 9f2e75b3..784cb2be 100755
--- a/apps/portal/scripts/test-request-password-reset.cjs
+++ b/apps/portal/scripts/test-request-password-reset.cjs
@@ -1,4 +1,6 @@
#!/usr/bin/env node
+/* eslint-env node */
+/* global __dirname, console, process */
const fs = require("node:fs");
const path = require("node:path");
@@ -94,7 +96,7 @@ const { useAuthStore } = require("../src/features/auth/services/auth.store.ts");
const [endpoint, options] = coreApiStub.postCalls[0];
if (endpoint !== "/auth/request-password-reset") {
throw new Error(
- `Expected endpoint \"/auth/request-password-reset\" but received \"${endpoint}\"`
+ `Expected endpoint "/auth/request-password-reset" but received "${endpoint}"`
);
}
@@ -109,7 +111,7 @@ const { useAuthStore } = require("../src/features/auth/services/auth.store.ts");
if (body.email !== payload.email) {
throw new Error(
- `Expected request body email to be \"${payload.email}\" but received \"${body.email}\"`
+ `Expected request body email to be "${payload.email}" but received "${body.email}"`
);
}
diff --git a/apps/portal/src/components/organisms/AppShell/Sidebar.tsx b/apps/portal/src/components/organisms/AppShell/Sidebar.tsx
index 5adc3ec9..2b2ab08b 100644
--- a/apps/portal/src/components/organisms/AppShell/Sidebar.tsx
+++ b/apps/portal/src/components/organisms/AppShell/Sidebar.tsx
@@ -140,10 +140,9 @@ const NavigationItem = memo(function NavigationItem({
href={child.href}
prefetch
onMouseEnter={() => {
- try {
- // Warm up code/data for faster clicks
- if (child.href) router.prefetch(child.href);
- } catch {}
+ if (child.href) {
+ void router.prefetch(child.href);
+ }
}}
className={`group flex items-center px-3 py-2 text-sm rounded-md transition-all duration-200 relative ${
isChildActive
@@ -194,9 +193,9 @@ const NavigationItem = memo(function NavigationItem({
href={item.href || "#"}
prefetch
onMouseEnter={() => {
- try {
- if (item.href && item.href !== "#") router.prefetch(item.href);
- } catch {}
+ if (item.href && item.href !== "#") {
+ void router.prefetch(item.href);
+ }
}}
className={`group w-full flex items-center px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 relative ${
isActive
diff --git a/apps/portal/src/features/account/hooks/useAddressEdit.ts b/apps/portal/src/features/account/hooks/useAddressEdit.ts
index e696b13e..ccd7b46e 100644
--- a/apps/portal/src/features/account/hooks/useAddressEdit.ts
+++ b/apps/portal/src/features/account/hooks/useAddressEdit.ts
@@ -11,12 +11,8 @@ import { useZodForm } from "@customer-portal/validation";
export function useAddressEdit(initial: AddressFormData) {
const handleSave = useCallback(async (formData: AddressFormData) => {
- try {
- const requestData = addressFormToRequest(formData);
- await accountService.updateAddress(requestData);
- } catch (error) {
- throw error; // Let useZodForm handle the error state
- }
+ const requestData = addressFormToRequest(formData);
+ await accountService.updateAddress(requestData);
}, []);
return useZodForm({
diff --git a/apps/portal/src/features/account/hooks/useProfileEdit.ts b/apps/portal/src/features/account/hooks/useProfileEdit.ts
index aa8539e8..32e9f043 100644
--- a/apps/portal/src/features/account/hooks/useProfileEdit.ts
+++ b/apps/portal/src/features/account/hooks/useProfileEdit.ts
@@ -12,17 +12,13 @@ import { useZodForm } from "@customer-portal/validation";
export function useProfileEdit(initial: ProfileEditFormData) {
const handleSave = useCallback(async (formData: ProfileEditFormData) => {
- try {
- const requestData = profileFormToRequest(formData);
- const updated = await accountService.updateProfile(requestData);
+ const requestData = profileFormToRequest(formData);
+ const updated = await accountService.updateProfile(requestData);
- useAuthStore.setState(state => ({
- ...state,
- user: state.user ? { ...state.user, ...updated } : state.user,
- }));
- } catch (error) {
- throw error; // Let useZodForm handle the error state
- }
+ useAuthStore.setState(state => ({
+ ...state,
+ user: state.user ? { ...state.user, ...updated } : state.user,
+ }));
}, []);
return useZodForm({
diff --git a/apps/portal/src/features/auth/components/LinkWhmcsForm/LinkWhmcsForm.tsx b/apps/portal/src/features/auth/components/LinkWhmcsForm/LinkWhmcsForm.tsx
index 2eb34c95..7317d7ce 100644
--- a/apps/portal/src/features/auth/components/LinkWhmcsForm/LinkWhmcsForm.tsx
+++ b/apps/portal/src/features/auth/components/LinkWhmcsForm/LinkWhmcsForm.tsx
@@ -22,17 +22,12 @@ export function LinkWhmcsForm({ onTransferred, className = "" }: LinkWhmcsFormPr
const handleLink = useCallback(
async (formData: LinkWhmcsFormData) => {
clearError();
- try {
- const payload: LinkWhmcsRequestInput = {
- email: formData.email,
- password: formData.password,
- };
- const result = await linkWhmcs(payload);
- onTransferred?.({ ...result, email: formData.email });
- } catch (err) {
- // Error is handled by useZodForm
- throw err;
- }
+ const payload: LinkWhmcsRequestInput = {
+ email: formData.email,
+ password: formData.password,
+ };
+ const result = await linkWhmcs(payload);
+ onTransferred?.({ ...result, email: formData.email });
},
[linkWhmcs, onTransferred, clearError]
);
@@ -56,7 +51,7 @@ export function LinkWhmcsForm({ onTransferred, className = "" }: LinkWhmcsFormPr
-