Enhance ESLint Rules and Refactor Domain Imports
- Updated ESLint configuration to enforce stricter import rules for the @customer-portal/domain package, promoting better import hygiene and preventing deep imports. - Refactored various files across the BFF and portal applications to comply with the new import rules, ensuring that only the appropriate modules are imported from the domain. - Cleaned up unused imports and optimized code structure for improved maintainability and clarity. - Updated documentation to reflect changes in import practices and domain structure.
This commit is contained in:
parent
fcc9bc247e
commit
a3dbd07183
@ -6,4 +6,5 @@ alwaysApply: true
|
|||||||
1. Have types and validation in the shared domain layer.
|
1. Have types and validation in the shared domain layer.
|
||||||
2. Keep business logic out of the frontend; use services and APIs instead.
|
2. Keep business logic out of the frontend; use services and APIs instead.
|
||||||
3. Reuse existing types and functions; extend them when additional behavior is needed.
|
3. Reuse existing types and functions; extend them when additional behavior is needed.
|
||||||
4. Follow the established folder structures documented in docs/STRUCTURE.md.
|
4. Read and understand the structures and workflows documented in docs. Start from docs/README.md
|
||||||
|
5. Follow structures and our codebase rules inside docs/development directory
|
||||||
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
import type { User as PrismaUser } from "@prisma/client";
|
import type { User as PrismaUser } from "@prisma/client";
|
||||||
import type { UserAuth } from "@customer-portal/domain/customer";
|
import type { UserAuth } from "@customer-portal/domain/customer";
|
||||||
import { Providers as CustomerProviders } from "@customer-portal/domain/customer";
|
import * as CustomerProviders from "@customer-portal/domain/customer/providers";
|
||||||
|
|
||||||
type PrismaUserRaw = Parameters<typeof CustomerProviders.Portal.mapPrismaUserToUserAuth>[0];
|
type PrismaUserRaw = Parameters<typeof CustomerProviders.Portal.mapPrismaUserToUserAuth>[0];
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
type SalesforceAccountPortalUpdate,
|
type SalesforceAccountPortalUpdate,
|
||||||
} from "./services/salesforce-account.service.js";
|
} from "./services/salesforce-account.service.js";
|
||||||
import { SalesforceOperationException } from "@bff/core/exceptions/domain-exceptions.js";
|
import { SalesforceOperationException } from "@bff/core/exceptions/domain-exceptions.js";
|
||||||
import type { SalesforceOrderRecord } from "@customer-portal/domain/orders";
|
import type { SalesforceOrderRecord } from "@customer-portal/domain/orders/providers";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Salesforce Service - Facade for Salesforce operations
|
* Salesforce Service - Facade for Salesforce operations
|
||||||
|
|||||||
@ -3,8 +3,8 @@ import { Logger } from "nestjs-pino";
|
|||||||
import { ConfigService } from "@nestjs/config";
|
import { ConfigService } from "@nestjs/config";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import { SalesforceConnection } from "./salesforce-connection.service.js";
|
import { SalesforceConnection } from "./salesforce-connection.service.js";
|
||||||
import type { SalesforceAccountRecord } from "@customer-portal/domain/customer";
|
import type { SalesforceAccountRecord } from "@customer-portal/domain/customer/providers";
|
||||||
import type { SalesforceResponse } from "@customer-portal/domain/common";
|
import type { SalesforceResponse } from "@customer-portal/domain/common/providers";
|
||||||
import { customerNumberSchema, salesforceIdSchema } from "@customer-portal/domain/common";
|
import { customerNumberSchema, salesforceIdSchema } from "@customer-portal/domain/common";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -14,16 +14,15 @@ import { Logger } from "nestjs-pino";
|
|||||||
import { SalesforceConnection } from "./salesforce-connection.service.js";
|
import { SalesforceConnection } from "./salesforce-connection.service.js";
|
||||||
import { assertSalesforceId } from "../utils/soql.util.js";
|
import { assertSalesforceId } from "../utils/soql.util.js";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import type { SalesforceResponse } from "@customer-portal/domain/common";
|
import type { SalesforceResponse } from "@customer-portal/domain/common/providers";
|
||||||
|
import type { SupportCase, CreateCaseRequest } from "@customer-portal/domain/support";
|
||||||
|
import type { SalesforceCaseRecord } from "@customer-portal/domain/support/providers";
|
||||||
import {
|
import {
|
||||||
type SupportCase,
|
|
||||||
type SalesforceCaseRecord,
|
|
||||||
type CreateCaseRequest,
|
|
||||||
SALESFORCE_CASE_ORIGIN,
|
SALESFORCE_CASE_ORIGIN,
|
||||||
SALESFORCE_CASE_STATUS,
|
SALESFORCE_CASE_STATUS,
|
||||||
SALESFORCE_CASE_PRIORITY,
|
SALESFORCE_CASE_PRIORITY,
|
||||||
Providers,
|
} from "@customer-portal/domain/support/providers";
|
||||||
} from "@customer-portal/domain/support";
|
import * as Providers from "@customer-portal/domain/support/providers";
|
||||||
|
|
||||||
// Access the mapper directly to avoid unbound method issues
|
// Access the mapper directly to avoid unbound method issues
|
||||||
const salesforceMapper = Providers.Salesforce;
|
const salesforceMapper = Providers.Salesforce;
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import { Logger } from "nestjs-pino";
|
|||||||
import { SalesforceConnection } from "./salesforce-connection.service.js";
|
import { SalesforceConnection } from "./salesforce-connection.service.js";
|
||||||
import { assertSalesforceId } from "../utils/soql.util.js";
|
import { assertSalesforceId } from "../utils/soql.util.js";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import type { SalesforceResponse } from "@customer-portal/domain/common";
|
import type { SalesforceResponse } from "@customer-portal/domain/common/providers";
|
||||||
import {
|
import {
|
||||||
type OpportunityStageValue,
|
type OpportunityStageValue,
|
||||||
type OpportunityProductTypeValue,
|
type OpportunityProductTypeValue,
|
||||||
|
|||||||
@ -16,14 +16,13 @@ import { Logger } from "nestjs-pino";
|
|||||||
import { SalesforceConnection } from "./salesforce-connection.service.js";
|
import { SalesforceConnection } from "./salesforce-connection.service.js";
|
||||||
import { assertSalesforceId, buildInClause } from "../utils/soql.util.js";
|
import { assertSalesforceId, buildInClause } from "../utils/soql.util.js";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import {
|
import type { OrderDetails, OrderSummary } from "@customer-portal/domain/orders";
|
||||||
Providers as OrderProviders,
|
import type {
|
||||||
type OrderDetails,
|
SalesforceOrderItemRecord,
|
||||||
type OrderSummary,
|
SalesforceOrderRecord,
|
||||||
type SalesforceOrderRecord,
|
} from "@customer-portal/domain/orders/providers";
|
||||||
type SalesforceOrderItemRecord,
|
import * as OrderProviders from "@customer-portal/domain/orders/providers";
|
||||||
} from "@customer-portal/domain/orders";
|
import type { SalesforceResponse } from "@customer-portal/domain/common/providers";
|
||||||
import type { SalesforceResponse } from "@customer-portal/domain/common";
|
|
||||||
import { OrderFieldMapService } from "@bff/modules/orders/config/order-field-map.service.js";
|
import { OrderFieldMapService } from "@bff/modules/orders/config/order-field-map.service.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import type {
|
|||||||
WhmcsAddClientResponse,
|
WhmcsAddClientResponse,
|
||||||
WhmcsValidateLoginResponse,
|
WhmcsValidateLoginResponse,
|
||||||
WhmcsSsoResponse,
|
WhmcsSsoResponse,
|
||||||
} from "@customer-portal/domain/customer";
|
} from "@customer-portal/domain/customer/providers";
|
||||||
import type {
|
import type {
|
||||||
WhmcsGetInvoicesParams,
|
WhmcsGetInvoicesParams,
|
||||||
WhmcsCreateInvoiceParams,
|
WhmcsCreateInvoiceParams,
|
||||||
@ -25,16 +25,18 @@ import type {
|
|||||||
WhmcsCreateInvoiceResponse,
|
WhmcsCreateInvoiceResponse,
|
||||||
WhmcsUpdateInvoiceResponse,
|
WhmcsUpdateInvoiceResponse,
|
||||||
WhmcsCapturePaymentResponse,
|
WhmcsCapturePaymentResponse,
|
||||||
} from "@customer-portal/domain/billing";
|
} from "@customer-portal/domain/billing/providers";
|
||||||
import type { WhmcsGetPayMethodsParams } from "@customer-portal/domain/payments";
|
import type { WhmcsGetPayMethodsParams } from "@customer-portal/domain/payments/providers";
|
||||||
import type {
|
import type {
|
||||||
WhmcsPaymentMethodListResponse,
|
WhmcsPaymentMethodListResponse,
|
||||||
WhmcsPaymentGatewayListResponse,
|
WhmcsPaymentGatewayListResponse,
|
||||||
} from "@customer-portal/domain/payments";
|
} from "@customer-portal/domain/payments/providers";
|
||||||
import type { WhmcsGetClientsProductsParams } from "@customer-portal/domain/subscriptions";
|
import type {
|
||||||
import type { WhmcsProductListResponse } from "@customer-portal/domain/subscriptions";
|
WhmcsGetClientsProductsParams,
|
||||||
import type { WhmcsCatalogProductListResponse } from "@customer-portal/domain/services";
|
WhmcsProductListResponse,
|
||||||
import type { WhmcsErrorResponse } from "@customer-portal/domain/common";
|
} from "@customer-portal/domain/subscriptions/providers";
|
||||||
|
import type { WhmcsCatalogProductListResponse } from "@customer-portal/domain/services/providers";
|
||||||
|
import type { WhmcsErrorResponse } from "@customer-portal/domain/common/providers";
|
||||||
import type { WhmcsRequestOptions, WhmcsConnectionStats } from "../types/connection.types.js";
|
import type { WhmcsRequestOptions, WhmcsConnectionStats } from "../types/connection.types.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
import { Injectable, HttpStatus } from "@nestjs/common";
|
import { Injectable, HttpStatus } from "@nestjs/common";
|
||||||
import {
|
import { ErrorCode, type ErrorCodeType } from "@customer-portal/domain/common";
|
||||||
ErrorCode,
|
import type { WhmcsErrorResponse } from "@customer-portal/domain/common/providers";
|
||||||
type ErrorCodeType,
|
|
||||||
type WhmcsErrorResponse,
|
|
||||||
} from "@customer-portal/domain/common";
|
|
||||||
import { DomainHttpException } from "@bff/core/http/domain-http.exception.js";
|
import { DomainHttpException } from "@bff/core/http/domain-http.exception.js";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Injectable, Inject } from "@nestjs/common";
|
import { Injectable, Inject } from "@nestjs/common";
|
||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import type { WhmcsResponse } from "@customer-portal/domain/common";
|
import type { WhmcsResponse } from "@customer-portal/domain/common/providers";
|
||||||
import type {
|
import type {
|
||||||
WhmcsApiConfig,
|
WhmcsApiConfig,
|
||||||
WhmcsRequestOptions,
|
WhmcsRequestOptions,
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { Logger } from "nestjs-pino";
|
|||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
||||||
import { WhmcsCacheService } from "../cache/whmcs-cache.service.js";
|
import { WhmcsCacheService } from "../cache/whmcs-cache.service.js";
|
||||||
import { Providers as CustomerProviders } from "@customer-portal/domain/customer";
|
import * as CustomerProviders from "@customer-portal/domain/customer/providers";
|
||||||
import type { WhmcsClient } from "@customer-portal/domain/customer";
|
import type { WhmcsClient } from "@customer-portal/domain/customer";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -9,8 +9,8 @@ import type {
|
|||||||
WhmcsClientResponse,
|
WhmcsClientResponse,
|
||||||
WhmcsAddClientResponse,
|
WhmcsAddClientResponse,
|
||||||
WhmcsValidateLoginResponse,
|
WhmcsValidateLoginResponse,
|
||||||
} from "@customer-portal/domain/customer";
|
} from "@customer-portal/domain/customer/providers";
|
||||||
import { Providers as CustomerProviders } from "@customer-portal/domain/customer";
|
import * as CustomerProviders from "@customer-portal/domain/customer/providers";
|
||||||
import type { WhmcsClient } from "@customer-portal/domain/customer";
|
import type { WhmcsClient } from "@customer-portal/domain/customer";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@ -4,16 +4,14 @@ import { Logger } from "nestjs-pino";
|
|||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import { WhmcsOperationException } from "@bff/core/exceptions/domain-exceptions.js";
|
import { WhmcsOperationException } from "@bff/core/exceptions/domain-exceptions.js";
|
||||||
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
||||||
import {
|
import { FALLBACK_CURRENCY } from "@customer-portal/domain/billing";
|
||||||
FALLBACK_CURRENCY,
|
import type { Currency } from "@customer-portal/domain/billing";
|
||||||
type WhmcsCurrenciesResponse,
|
import type { WhmcsCurrenciesResponse } from "@customer-portal/domain/billing/providers";
|
||||||
type WhmcsCurrency,
|
|
||||||
} from "@customer-portal/domain/billing";
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WhmcsCurrencyService implements OnModuleInit, OnModuleDestroy {
|
export class WhmcsCurrencyService implements OnModuleInit, OnModuleDestroy {
|
||||||
private defaultCurrency: WhmcsCurrency | null = null;
|
private defaultCurrency: Currency | null = null;
|
||||||
private currencies: WhmcsCurrency[] = [];
|
private currencies: Currency[] = [];
|
||||||
private readonly REFRESH_INTERVAL_MS = 6 * 60 * 60 * 1000; // 6 hours
|
private readonly REFRESH_INTERVAL_MS = 6 * 60 * 60 * 1000; // 6 hours
|
||||||
private refreshTimer: NodeJS.Timeout | null = null;
|
private refreshTimer: NodeJS.Timeout | null = null;
|
||||||
|
|
||||||
@ -70,21 +68,21 @@ export class WhmcsCurrencyService implements OnModuleInit, OnModuleDestroy {
|
|||||||
/**
|
/**
|
||||||
* Get the default currency (first currency from WHMCS or JPY fallback)
|
* Get the default currency (first currency from WHMCS or JPY fallback)
|
||||||
*/
|
*/
|
||||||
getDefaultCurrency(): WhmcsCurrency {
|
getDefaultCurrency(): Currency {
|
||||||
return this.defaultCurrency ? { ...this.defaultCurrency } : { ...FALLBACK_CURRENCY };
|
return this.defaultCurrency ? { ...this.defaultCurrency } : { ...FALLBACK_CURRENCY };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all available currencies
|
* Get all available currencies
|
||||||
*/
|
*/
|
||||||
getAllCurrencies(): WhmcsCurrency[] {
|
getAllCurrencies(): Currency[] {
|
||||||
return this.currencies;
|
return this.currencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find currency by code
|
* Find currency by code
|
||||||
*/
|
*/
|
||||||
getCurrencyByCode(code: string): WhmcsCurrency | null {
|
getCurrencyByCode(code: string): Currency | null {
|
||||||
return this.currencies.find(c => c.code.toUpperCase() === code.toUpperCase()) || null;
|
return this.currencies.find(c => c.code.toUpperCase() === code.toUpperCase()) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,8 +138,8 @@ export class WhmcsCurrencyService implements OnModuleInit, OnModuleDestroy {
|
|||||||
* Parse WHMCS response format into currency objects
|
* Parse WHMCS response format into currency objects
|
||||||
* Handles both flat format (currencies[currency][0][id]) and nested format (currencies.currency[])
|
* Handles both flat format (currencies[currency][0][id]) and nested format (currencies.currency[])
|
||||||
*/
|
*/
|
||||||
private parseWhmcsCurrenciesResponse(response: WhmcsCurrenciesResponse): WhmcsCurrency[] {
|
private parseWhmcsCurrenciesResponse(response: WhmcsCurrenciesResponse): Currency[] {
|
||||||
const currencies: WhmcsCurrency[] = [];
|
const currencies: Currency[] = [];
|
||||||
|
|
||||||
// Check if response has nested currency structure
|
// Check if response has nested currency structure
|
||||||
if (
|
if (
|
||||||
@ -154,7 +152,7 @@ export class WhmcsCurrencyService implements OnModuleInit, OnModuleDestroy {
|
|||||||
: [response.currencies.currency];
|
: [response.currencies.currency];
|
||||||
|
|
||||||
for (const currencyData of currencyArray) {
|
for (const currencyData of currencyArray) {
|
||||||
const currency: WhmcsCurrency = {
|
const currency: Currency = {
|
||||||
id: parseInt(String(currencyData.id)) || 0,
|
id: parseInt(String(currencyData.id)) || 0,
|
||||||
code: String(currencyData.code || ""),
|
code: String(currencyData.code || ""),
|
||||||
prefix: String(currencyData.prefix || ""),
|
prefix: String(currencyData.prefix || ""),
|
||||||
@ -184,7 +182,7 @@ export class WhmcsCurrencyService implements OnModuleInit, OnModuleDestroy {
|
|||||||
|
|
||||||
// Build currency objects from the flat response
|
// Build currency objects from the flat response
|
||||||
for (const index of currencyIndices) {
|
for (const index of currencyIndices) {
|
||||||
const currency: WhmcsCurrency = {
|
const currency: Currency = {
|
||||||
id: parseInt(String(response[`currencies[currency][${index}][id]`])) || 0,
|
id: parseInt(String(response[`currencies[currency][${index}][id]`])) || 0,
|
||||||
code: String(response[`currencies[currency][${index}][code]`] || ""),
|
code: String(response[`currencies[currency][${index}][code]`] || ""),
|
||||||
prefix: String(response[`currencies[currency][${index}][prefix]`] || ""),
|
prefix: String(response[`currencies[currency][${index}][prefix]`] || ""),
|
||||||
|
|||||||
@ -2,8 +2,9 @@ import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
|||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { Injectable, NotFoundException, Inject } from "@nestjs/common";
|
import { Injectable, NotFoundException, Inject } from "@nestjs/common";
|
||||||
import { WhmcsOperationException } from "@bff/core/exceptions/domain-exceptions.js";
|
import { WhmcsOperationException } from "@bff/core/exceptions/domain-exceptions.js";
|
||||||
import { invoiceListSchema, invoiceSchema, Providers } from "@customer-portal/domain/billing";
|
import { invoiceListSchema, invoiceSchema } from "@customer-portal/domain/billing";
|
||||||
import type { Invoice, InvoiceList } from "@customer-portal/domain/billing";
|
import type { Invoice, InvoiceList } from "@customer-portal/domain/billing";
|
||||||
|
import * as Providers from "@customer-portal/domain/billing/providers";
|
||||||
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
||||||
import { WhmcsCurrencyService } from "./whmcs-currency.service.js";
|
import { WhmcsCurrencyService } from "./whmcs-currency.service.js";
|
||||||
import { WhmcsCacheService } from "../cache/whmcs-cache.service.js";
|
import { WhmcsCacheService } from "../cache/whmcs-cache.service.js";
|
||||||
@ -12,14 +13,14 @@ import type {
|
|||||||
WhmcsCreateInvoiceParams,
|
WhmcsCreateInvoiceParams,
|
||||||
WhmcsUpdateInvoiceParams,
|
WhmcsUpdateInvoiceParams,
|
||||||
WhmcsCapturePaymentParams,
|
WhmcsCapturePaymentParams,
|
||||||
} from "@customer-portal/domain/billing";
|
} from "@customer-portal/domain/billing/providers";
|
||||||
import type {
|
import type {
|
||||||
WhmcsInvoiceListResponse,
|
WhmcsInvoiceListResponse,
|
||||||
WhmcsInvoiceResponse,
|
WhmcsInvoiceResponse,
|
||||||
WhmcsCreateInvoiceResponse,
|
WhmcsCreateInvoiceResponse,
|
||||||
WhmcsUpdateInvoiceResponse,
|
WhmcsUpdateInvoiceResponse,
|
||||||
WhmcsCapturePaymentResponse,
|
WhmcsCapturePaymentResponse,
|
||||||
} from "@customer-portal/domain/billing";
|
} from "@customer-portal/domain/billing/providers";
|
||||||
|
|
||||||
export type InvoiceFilters = Partial<{
|
export type InvoiceFilters = Partial<{
|
||||||
status: "Paid" | "Unpaid" | "Cancelled" | "Overdue" | "Collections";
|
status: "Paid" | "Unpaid" | "Cancelled" | "Overdue" | "Collections";
|
||||||
|
|||||||
@ -9,12 +9,12 @@ import type {
|
|||||||
WhmcsAddOrderParams,
|
WhmcsAddOrderParams,
|
||||||
WhmcsAddOrderResponse,
|
WhmcsAddOrderResponse,
|
||||||
WhmcsOrderResult,
|
WhmcsOrderResult,
|
||||||
} from "@customer-portal/domain/orders";
|
} from "@customer-portal/domain/orders/providers";
|
||||||
|
import * as Providers from "@customer-portal/domain/orders/providers";
|
||||||
import {
|
import {
|
||||||
Providers,
|
|
||||||
whmcsAddOrderResponseSchema,
|
whmcsAddOrderResponseSchema,
|
||||||
whmcsAcceptOrderResponseSchema,
|
whmcsAcceptOrderResponseSchema,
|
||||||
} from "@customer-portal/domain/orders";
|
} from "@customer-portal/domain/orders/providers";
|
||||||
|
|
||||||
export type { WhmcsOrderItem, WhmcsAddOrderParams, WhmcsOrderResult };
|
export type { WhmcsOrderItem, WhmcsAddOrderParams, WhmcsOrderResult };
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,25 @@
|
|||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { Injectable, Inject } from "@nestjs/common";
|
import { Injectable, Inject } from "@nestjs/common";
|
||||||
import { Providers } from "@customer-portal/domain/payments";
|
import * as Providers from "@customer-portal/domain/payments/providers";
|
||||||
import type {
|
import type {
|
||||||
PaymentMethodList,
|
PaymentMethodList,
|
||||||
PaymentGateway,
|
PaymentGateway,
|
||||||
PaymentGatewayList,
|
PaymentGatewayList,
|
||||||
PaymentMethod,
|
PaymentMethod,
|
||||||
} from "@customer-portal/domain/payments";
|
} from "@customer-portal/domain/payments";
|
||||||
import {
|
import type { WhmcsCatalogProductNormalized } from "@customer-portal/domain/services/providers";
|
||||||
Providers as CatalogProviders,
|
import * as CatalogProviders from "@customer-portal/domain/services/providers";
|
||||||
type WhmcsCatalogProductNormalized,
|
|
||||||
} from "@customer-portal/domain/services";
|
|
||||||
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
||||||
import { WhmcsCacheService } from "../cache/whmcs-cache.service.js";
|
import { WhmcsCacheService } from "../cache/whmcs-cache.service.js";
|
||||||
import type { WhmcsCreateSsoTokenParams } from "@customer-portal/domain/customer";
|
import type { WhmcsCreateSsoTokenParams } from "@customer-portal/domain/customer/providers";
|
||||||
import type { WhmcsGetPayMethodsParams } from "@customer-portal/domain/payments";
|
import type { WhmcsGetPayMethodsParams } from "@customer-portal/domain/payments/providers";
|
||||||
import type {
|
import type {
|
||||||
WhmcsPaymentMethod,
|
WhmcsPaymentMethod,
|
||||||
WhmcsPaymentMethodListResponse,
|
WhmcsPaymentMethodListResponse,
|
||||||
WhmcsPaymentGateway,
|
WhmcsPaymentGateway,
|
||||||
WhmcsPaymentGatewayListResponse,
|
WhmcsPaymentGatewayListResponse,
|
||||||
} from "@customer-portal/domain/payments";
|
} from "@customer-portal/domain/payments/providers";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WhmcsPaymentService {
|
export class WhmcsPaymentService {
|
||||||
|
|||||||
@ -2,8 +2,10 @@ import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
|||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { Injectable, Inject } from "@nestjs/common";
|
import { Injectable, Inject } from "@nestjs/common";
|
||||||
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
||||||
import type { WhmcsCreateSsoTokenParams } from "@customer-portal/domain/customer";
|
import type {
|
||||||
import type { WhmcsSsoResponse } from "@customer-portal/domain/customer";
|
WhmcsCreateSsoTokenParams,
|
||||||
|
WhmcsSsoResponse,
|
||||||
|
} from "@customer-portal/domain/customer/providers";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WhmcsSsoService {
|
export class WhmcsSsoService {
|
||||||
|
|||||||
@ -2,12 +2,12 @@ import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
|||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { Injectable, NotFoundException, Inject } from "@nestjs/common";
|
import { Injectable, NotFoundException, Inject } from "@nestjs/common";
|
||||||
import { WhmcsOperationException } from "@bff/core/exceptions/domain-exceptions.js";
|
import { WhmcsOperationException } from "@bff/core/exceptions/domain-exceptions.js";
|
||||||
import { Providers } from "@customer-portal/domain/subscriptions";
|
import * as Providers from "@customer-portal/domain/subscriptions/providers";
|
||||||
import type { Subscription, SubscriptionList } from "@customer-portal/domain/subscriptions";
|
import type { Subscription, SubscriptionList } from "@customer-portal/domain/subscriptions";
|
||||||
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js";
|
||||||
import { WhmcsCurrencyService } from "./whmcs-currency.service.js";
|
import { WhmcsCurrencyService } from "./whmcs-currency.service.js";
|
||||||
import { WhmcsCacheService } from "../cache/whmcs-cache.service.js";
|
import { WhmcsCacheService } from "../cache/whmcs-cache.service.js";
|
||||||
import type { WhmcsGetClientsProductsParams } from "@customer-portal/domain/subscriptions";
|
import type { WhmcsGetClientsProductsParams } from "@customer-portal/domain/subscriptions/providers";
|
||||||
|
|
||||||
export interface SubscriptionFilters {
|
export interface SubscriptionFilters {
|
||||||
status?: string;
|
status?: string;
|
||||||
|
|||||||
@ -2,12 +2,8 @@ import { Injectable, Inject } from "@nestjs/common";
|
|||||||
import type { Invoice, InvoiceList } from "@customer-portal/domain/billing";
|
import type { Invoice, InvoiceList } from "@customer-portal/domain/billing";
|
||||||
import type { Subscription, SubscriptionList } from "@customer-portal/domain/subscriptions";
|
import type { Subscription, SubscriptionList } from "@customer-portal/domain/subscriptions";
|
||||||
import type { PaymentMethodList, PaymentGatewayList } from "@customer-portal/domain/payments";
|
import type { PaymentMethodList, PaymentGatewayList } from "@customer-portal/domain/payments";
|
||||||
import {
|
import { addressSchema, type Address, type WhmcsClient } from "@customer-portal/domain/customer";
|
||||||
Providers as CustomerProviders,
|
import * as CustomerProviders from "@customer-portal/domain/customer/providers";
|
||||||
addressSchema,
|
|
||||||
type Address,
|
|
||||||
type WhmcsClient,
|
|
||||||
} from "@customer-portal/domain/customer";
|
|
||||||
import { WhmcsConnectionOrchestratorService } from "./connection/services/whmcs-connection-orchestrator.service.js";
|
import { WhmcsConnectionOrchestratorService } from "./connection/services/whmcs-connection-orchestrator.service.js";
|
||||||
import { WhmcsInvoiceService } from "./services/whmcs-invoice.service.js";
|
import { WhmcsInvoiceService } from "./services/whmcs-invoice.service.js";
|
||||||
import type { InvoiceFilters } from "./services/whmcs-invoice.service.js";
|
import type { InvoiceFilters } from "./services/whmcs-invoice.service.js";
|
||||||
@ -17,10 +13,15 @@ import { WhmcsClientService } from "./services/whmcs-client.service.js";
|
|||||||
import { WhmcsPaymentService } from "./services/whmcs-payment.service.js";
|
import { WhmcsPaymentService } from "./services/whmcs-payment.service.js";
|
||||||
import { WhmcsSsoService } from "./services/whmcs-sso.service.js";
|
import { WhmcsSsoService } from "./services/whmcs-sso.service.js";
|
||||||
import { WhmcsOrderService } from "./services/whmcs-order.service.js";
|
import { WhmcsOrderService } from "./services/whmcs-order.service.js";
|
||||||
import type { WhmcsAddClientParams, WhmcsClientResponse } from "@customer-portal/domain/customer";
|
import type {
|
||||||
import type { WhmcsGetClientsProductsParams } from "@customer-portal/domain/subscriptions";
|
WhmcsAddClientParams,
|
||||||
import type { WhmcsProductListResponse } from "@customer-portal/domain/subscriptions";
|
WhmcsClientResponse,
|
||||||
import type { WhmcsCatalogProductNormalized } from "@customer-portal/domain/services";
|
} from "@customer-portal/domain/customer/providers";
|
||||||
|
import type {
|
||||||
|
WhmcsGetClientsProductsParams,
|
||||||
|
WhmcsProductListResponse,
|
||||||
|
} from "@customer-portal/domain/subscriptions/providers";
|
||||||
|
import type { WhmcsCatalogProductNormalized } from "@customer-portal/domain/services/providers";
|
||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import {
|
|||||||
type ValidateSignupRequest,
|
type ValidateSignupRequest,
|
||||||
} from "@customer-portal/domain/auth";
|
} from "@customer-portal/domain/auth";
|
||||||
import { ErrorCode } from "@customer-portal/domain/common";
|
import { ErrorCode } from "@customer-portal/domain/common";
|
||||||
import { Providers as CustomerProviders } from "@customer-portal/domain/customer";
|
import * as CustomerProviders from "@customer-portal/domain/customer/providers";
|
||||||
import { mapPrismaUserToDomain } from "@bff/infra/mappers/index.js";
|
import { mapPrismaUserToDomain } from "@bff/infra/mappers/index.js";
|
||||||
import type { User as PrismaUser } from "@prisma/client";
|
import type { User as PrismaUser } from "@prisma/client";
|
||||||
import { CacheService } from "@bff/infra/cache/cache.service.js";
|
import { CacheService } from "@bff/infra/cache/cache.service.js";
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { WhmcsAccountDiscoveryService } from "@bff/integrations/whmcs/services/w
|
|||||||
import { SalesforceService } from "@bff/integrations/salesforce/salesforce.service.js";
|
import { SalesforceService } from "@bff/integrations/salesforce/salesforce.service.js";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import { mapPrismaUserToDomain } from "@bff/infra/mappers/index.js";
|
import { mapPrismaUserToDomain } from "@bff/infra/mappers/index.js";
|
||||||
import { Providers as CustomerProviders } from "@customer-portal/domain/customer";
|
import * as CustomerProviders from "@customer-portal/domain/customer/providers";
|
||||||
import type { User } from "@customer-portal/domain/customer";
|
import type { User } from "@customer-portal/domain/customer";
|
||||||
import {
|
import {
|
||||||
PORTAL_SOURCE_MIGRATED,
|
PORTAL_SOURCE_MIGRATED,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Controller, Get } from "@nestjs/common";
|
import { Controller, Get } from "@nestjs/common";
|
||||||
import { Public } from "@bff/modules/auth/decorators/public.decorator.js";
|
import { Public } from "@bff/modules/auth/decorators/public.decorator.js";
|
||||||
import { WhmcsCurrencyService } from "../../integrations/whmcs/services/whmcs-currency.service.js";
|
import { WhmcsCurrencyService } from "../../integrations/whmcs/services/whmcs-currency.service.js";
|
||||||
import type { WhmcsCurrency } from "@customer-portal/domain/billing";
|
import type { Currency } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
@Controller("currency")
|
@Controller("currency")
|
||||||
export class CurrencyController {
|
export class CurrencyController {
|
||||||
@ -9,13 +9,13 @@ export class CurrencyController {
|
|||||||
|
|
||||||
@Public()
|
@Public()
|
||||||
@Get("default")
|
@Get("default")
|
||||||
getDefaultCurrency(): WhmcsCurrency {
|
getDefaultCurrency(): Currency {
|
||||||
return this.currencyService.getDefaultCurrency();
|
return this.currencyService.getDefaultCurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Public()
|
@Public()
|
||||||
@Get("all")
|
@Get("all")
|
||||||
getAllCurrencies(): WhmcsCurrency[] {
|
getAllCurrencies(): Currency[] {
|
||||||
return this.currencyService.getAllCurrencies();
|
return this.currencyService.getAllCurrencies();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import {
|
|||||||
defaultSalesforceOrderFieldMap,
|
defaultSalesforceOrderFieldMap,
|
||||||
type PartialSalesforceOrderFieldMap,
|
type PartialSalesforceOrderFieldMap,
|
||||||
type SalesforceOrderFieldMap,
|
type SalesforceOrderFieldMap,
|
||||||
} from "@customer-portal/domain/orders";
|
} from "@customer-portal/domain/orders/providers";
|
||||||
|
|
||||||
const unique = <T>(values: T[]): T[] => Array.from(new Set(values));
|
const unique = <T>(values: T[]): T[] => Array.from(new Set(values));
|
||||||
|
|
||||||
|
|||||||
@ -14,11 +14,9 @@ import { OrderEventsService } from "./order-events.service.js";
|
|||||||
import { OrdersCacheService } from "./orders-cache.service.js";
|
import { OrdersCacheService } from "./orders-cache.service.js";
|
||||||
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
||||||
import { NotificationService } from "@bff/modules/notifications/notifications.service.js";
|
import { NotificationService } from "@bff/modules/notifications/notifications.service.js";
|
||||||
import {
|
import type { OrderDetails } from "@customer-portal/domain/orders";
|
||||||
type OrderDetails,
|
import type { OrderFulfillmentValidationResult } from "@customer-portal/domain/orders/providers";
|
||||||
type OrderFulfillmentValidationResult,
|
import * as OrderProviders from "@customer-portal/domain/orders/providers";
|
||||||
Providers as OrderProviders,
|
|
||||||
} from "@customer-portal/domain/orders";
|
|
||||||
import { OPPORTUNITY_STAGE } from "@customer-portal/domain/opportunity";
|
import { OPPORTUNITY_STAGE } from "@customer-portal/domain/opportunity";
|
||||||
import { NOTIFICATION_SOURCE, NOTIFICATION_TYPE } from "@customer-portal/domain/notifications";
|
import { NOTIFICATION_SOURCE, NOTIFICATION_TYPE } from "@customer-portal/domain/notifications";
|
||||||
import { salesforceAccountIdSchema } from "@customer-portal/domain/common";
|
import { salesforceAccountIdSchema } from "@customer-portal/domain/common";
|
||||||
|
|||||||
@ -4,9 +4,9 @@ import { SalesforceService } from "@bff/integrations/salesforce/salesforce.servi
|
|||||||
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import { sfOrderIdParamSchema } from "@customer-portal/domain/orders";
|
import { sfOrderIdParamSchema } from "@customer-portal/domain/orders";
|
||||||
import type { OrderFulfillmentValidationResult } from "@customer-portal/domain/orders";
|
import type { OrderFulfillmentValidationResult } from "@customer-portal/domain/orders/providers";
|
||||||
import { salesforceAccountIdSchema } from "@customer-portal/domain/common";
|
import { salesforceAccountIdSchema } from "@customer-portal/domain/common";
|
||||||
import type { SalesforceOrderRecord } from "@customer-portal/domain/orders/providers/salesforce/raw.types";
|
import type { SalesforceOrderRecord } from "@customer-portal/domain/orders/providers";
|
||||||
import { PaymentValidatorService } from "./payment-validator.service.js";
|
import { PaymentValidatorService } from "./payment-validator.service.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import { SalesforceConnection } from "@bff/integrations/salesforce/services/sale
|
|||||||
import type {
|
import type {
|
||||||
SalesforceProduct2Record,
|
SalesforceProduct2Record,
|
||||||
SalesforcePricebookEntryRecord,
|
SalesforcePricebookEntryRecord,
|
||||||
} from "@customer-portal/domain/services";
|
} from "@customer-portal/domain/services/providers";
|
||||||
import type { SalesforceResponse } from "@customer-portal/domain/common";
|
import type { SalesforceResponse } from "@customer-portal/domain/common/providers";
|
||||||
import {
|
import {
|
||||||
assertSalesforceId,
|
assertSalesforceId,
|
||||||
buildInClause,
|
buildInClause,
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
type CreateOrderRequest,
|
type CreateOrderRequest,
|
||||||
type OrderBusinessValidation,
|
type OrderBusinessValidation,
|
||||||
} from "@customer-portal/domain/orders";
|
} from "@customer-portal/domain/orders";
|
||||||
import type { Providers } from "@customer-portal/domain/subscriptions";
|
import type * as Providers from "@customer-portal/domain/subscriptions/providers";
|
||||||
|
|
||||||
type WhmcsProduct = Providers.WhmcsRaw.WhmcsProductRaw;
|
type WhmcsProduct = Providers.WhmcsRaw.WhmcsProductRaw;
|
||||||
import { SimServicesService } from "@bff/modules/services/services/sim-services.service.js";
|
import { SimServicesService } from "@bff/modules/services/services/sim-services.service.js";
|
||||||
|
|||||||
@ -12,11 +12,11 @@ import {
|
|||||||
} from "@bff/integrations/salesforce/utils/services-query-builder.js";
|
} from "@bff/integrations/salesforce/utils/services-query-builder.js";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import type {
|
import type {
|
||||||
SalesforceProduct2WithPricebookEntries,
|
|
||||||
SalesforcePricebookEntryRecord,
|
SalesforcePricebookEntryRecord,
|
||||||
} from "@customer-portal/domain/services";
|
SalesforceProduct2WithPricebookEntries,
|
||||||
import { Providers as CatalogProviders } from "@customer-portal/domain/services";
|
} from "@customer-portal/domain/services/providers";
|
||||||
import type { SalesforceResponse } from "@customer-portal/domain/common";
|
import * as CatalogProviders from "@customer-portal/domain/services/providers";
|
||||||
|
import type { SalesforceResponse } from "@customer-portal/domain/common/providers";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BaseServicesService {
|
export class BaseServicesService {
|
||||||
|
|||||||
@ -3,20 +3,20 @@ import { ConfigService } from "@nestjs/config";
|
|||||||
import { BaseServicesService } from "./base-services.service.js";
|
import { BaseServicesService } from "./base-services.service.js";
|
||||||
import { ServicesCacheService } from "./services-cache.service.js";
|
import { ServicesCacheService } from "./services-cache.service.js";
|
||||||
import type {
|
import type {
|
||||||
SalesforceProduct2WithPricebookEntries,
|
|
||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
InternetAddonCatalogItem,
|
InternetAddonCatalogItem,
|
||||||
InternetEligibilityDetails,
|
InternetEligibilityDetails,
|
||||||
InternetEligibilityStatus,
|
InternetEligibilityStatus,
|
||||||
} from "@customer-portal/domain/services";
|
} from "@customer-portal/domain/services";
|
||||||
|
import type { SalesforceProduct2WithPricebookEntries } from "@customer-portal/domain/services/providers";
|
||||||
import {
|
import {
|
||||||
Providers as CatalogProviders,
|
|
||||||
enrichInternetPlanMetadata,
|
enrichInternetPlanMetadata,
|
||||||
inferAddonTypeFromSku,
|
inferAddonTypeFromSku,
|
||||||
inferInstallationTermFromSku,
|
inferInstallationTermFromSku,
|
||||||
internetEligibilityDetailsSchema,
|
internetEligibilityDetailsSchema,
|
||||||
} from "@customer-portal/domain/services";
|
} from "@customer-portal/domain/services";
|
||||||
|
import * as CatalogProviders from "@customer-portal/domain/services/providers";
|
||||||
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
||||||
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js";
|
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js";
|
||||||
import { OpportunityResolutionService } from "@bff/integrations/salesforce/services/opportunity-resolution.service.js";
|
import { OpportunityResolutionService } from "@bff/integrations/salesforce/services/opportunity-resolution.service.js";
|
||||||
@ -27,7 +27,7 @@ import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
|||||||
import { assertSalesforceId } from "@bff/integrations/salesforce/utils/soql.util.js";
|
import { assertSalesforceId } from "@bff/integrations/salesforce/utils/soql.util.js";
|
||||||
import { assertSoqlFieldName } from "@bff/integrations/salesforce/utils/soql.util.js";
|
import { assertSoqlFieldName } from "@bff/integrations/salesforce/utils/soql.util.js";
|
||||||
import type { InternetEligibilityCheckRequest } from "./internet-eligibility.types.js";
|
import type { InternetEligibilityCheckRequest } from "./internet-eligibility.types.js";
|
||||||
import type { SalesforceResponse } from "@customer-portal/domain/common";
|
import type { SalesforceResponse } from "@customer-portal/domain/common/providers";
|
||||||
// (removed unused opportunity constants import)
|
// (removed unused opportunity constants import)
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@ -3,11 +3,11 @@ import { ConfigService } from "@nestjs/config";
|
|||||||
import { BaseServicesService } from "./base-services.service.js";
|
import { BaseServicesService } from "./base-services.service.js";
|
||||||
import { ServicesCacheService } from "./services-cache.service.js";
|
import { ServicesCacheService } from "./services-cache.service.js";
|
||||||
import type {
|
import type {
|
||||||
SalesforceProduct2WithPricebookEntries,
|
|
||||||
SimCatalogProduct,
|
SimCatalogProduct,
|
||||||
SimActivationFeeCatalogItem,
|
SimActivationFeeCatalogItem,
|
||||||
} from "@customer-portal/domain/services";
|
} from "@customer-portal/domain/services";
|
||||||
import { Providers as CatalogProviders } from "@customer-portal/domain/services";
|
import type { SalesforceProduct2WithPricebookEntries } from "@customer-portal/domain/services/providers";
|
||||||
|
import * as CatalogProviders from "@customer-portal/domain/services/providers";
|
||||||
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
||||||
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js";
|
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js";
|
||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
|
|||||||
@ -4,11 +4,9 @@ import { Logger } from "nestjs-pino";
|
|||||||
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js";
|
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js";
|
||||||
import { BaseServicesService } from "./base-services.service.js";
|
import { BaseServicesService } from "./base-services.service.js";
|
||||||
import { ServicesCacheService } from "./services-cache.service.js";
|
import { ServicesCacheService } from "./services-cache.service.js";
|
||||||
import type {
|
import type { VpnCatalogProduct } from "@customer-portal/domain/services";
|
||||||
SalesforceProduct2WithPricebookEntries,
|
import type { SalesforceProduct2WithPricebookEntries } from "@customer-portal/domain/services/providers";
|
||||||
VpnCatalogProduct,
|
import * as CatalogProviders from "@customer-portal/domain/services/providers";
|
||||||
} from "@customer-portal/domain/services";
|
|
||||||
import { Providers as CatalogProviders } from "@customer-portal/domain/services";
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class VpnServicesService extends BaseServicesService {
|
export class VpnServicesService extends BaseServicesService {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { ConfigService } from "@nestjs/config";
|
|||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js";
|
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js";
|
||||||
import type { SimTopUpPricing, SimTopUpPricingPreviewResponse } from "@customer-portal/domain/sim";
|
import type { SimTopUpPricing, SimTopUpPricingPreviewResponse } from "@customer-portal/domain/sim";
|
||||||
import type { SalesforceResponse } from "@customer-portal/domain/common";
|
import type { SalesforceResponse } from "@customer-portal/domain/common/providers";
|
||||||
import { sanitizeSoqlLiteral } from "@bff/integrations/salesforce/utils/soql.util.js";
|
import { sanitizeSoqlLiteral } from "@bff/integrations/salesforce/utils/soql.util.js";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import type {
|
|||||||
SimPlanChangeResult,
|
SimPlanChangeResult,
|
||||||
} from "@customer-portal/domain/subscriptions";
|
} from "@customer-portal/domain/subscriptions";
|
||||||
import type { InvoiceList } from "@customer-portal/domain/billing";
|
import type { InvoiceList } from "@customer-portal/domain/billing";
|
||||||
import { createPaginationSchema } from "@customer-portal/domain/toolkit/validation/helpers";
|
import { Validation } from "@customer-portal/domain/toolkit";
|
||||||
import {
|
import {
|
||||||
simTopupRequestSchema,
|
simTopupRequestSchema,
|
||||||
simChangePlanRequestSchema,
|
simChangePlanRequestSchema,
|
||||||
@ -82,7 +82,7 @@ import {
|
|||||||
} from "@customer-portal/domain/subscriptions";
|
} from "@customer-portal/domain/subscriptions";
|
||||||
import { invoiceListSchema } from "@customer-portal/domain/billing";
|
import { invoiceListSchema } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
const subscriptionInvoiceQuerySchema = createPaginationSchema({
|
const subscriptionInvoiceQuerySchema = Validation.createPaginationSchema({
|
||||||
defaultLimit: 10,
|
defaultLimit: 10,
|
||||||
maxLimit: 100,
|
maxLimit: 100,
|
||||||
minLimit: 1,
|
minLimit: 1,
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { WhmcsService } from "@bff/integrations/whmcs/whmcs.service.js";
|
|||||||
import { WhmcsCacheService } from "@bff/integrations/whmcs/cache/whmcs-cache.service.js";
|
import { WhmcsCacheService } from "@bff/integrations/whmcs/cache/whmcs-cache.service.js";
|
||||||
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
|
||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import type { Providers } from "@customer-portal/domain/subscriptions";
|
import type * as Providers from "@customer-portal/domain/subscriptions/providers";
|
||||||
|
|
||||||
type WhmcsProduct = Providers.WhmcsRaw.WhmcsProductRaw;
|
type WhmcsProduct = Providers.WhmcsRaw.WhmcsProductRaw;
|
||||||
|
|
||||||
|
|||||||
@ -10,12 +10,12 @@ import { Logger } from "nestjs-pino";
|
|||||||
import type { User as PrismaUser } from "@prisma/client";
|
import type { User as PrismaUser } from "@prisma/client";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
import { getErrorMessage } from "@bff/core/utils/error.util.js";
|
||||||
import {
|
import {
|
||||||
Providers as CustomerProviders,
|
|
||||||
addressSchema,
|
addressSchema,
|
||||||
combineToUser,
|
combineToUser,
|
||||||
type Address,
|
type Address,
|
||||||
type User,
|
type User,
|
||||||
} from "@customer-portal/domain/customer";
|
} from "@customer-portal/domain/customer";
|
||||||
|
import * as CustomerProviders from "@customer-portal/domain/customer/providers";
|
||||||
import {
|
import {
|
||||||
updateCustomerProfileRequestSchema,
|
updateCustomerProfileRequestSchema,
|
||||||
type UpdateCustomerProfileRequest,
|
type UpdateCustomerProfileRequest,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
assertSalesforceId,
|
assertSalesforceId,
|
||||||
assertSoqlFieldName,
|
assertSoqlFieldName,
|
||||||
} from "@bff/integrations/salesforce/utils/soql.util.js";
|
} from "@bff/integrations/salesforce/utils/soql.util.js";
|
||||||
import type { SalesforceResponse } from "@customer-portal/domain/common";
|
import type { SalesforceResponse } from "@customer-portal/domain/common/providers";
|
||||||
import {
|
import {
|
||||||
residenceCardVerificationSchema,
|
residenceCardVerificationSchema,
|
||||||
type ResidenceCardVerification,
|
type ResidenceCardVerification,
|
||||||
|
|||||||
@ -206,17 +206,17 @@ The application uses Zod for type-safe form validation. Use the `useZodForm` hoo
|
|||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useZodForm } from "@/core/forms";
|
import { useZodForm } from "@/core/forms";
|
||||||
import { loginFormSchema, type LoginFormData } from "@customer-portal/domain";
|
import { loginRequestSchema, type LoginRequest } from "@customer-portal/domain/auth";
|
||||||
|
|
||||||
function MyForm() {
|
function MyForm() {
|
||||||
const { values, errors, touched, isSubmitting, setValue, setTouchedField, handleSubmit } =
|
const { values, errors, touched, isSubmitting, setValue, setTouchedField, handleSubmit } =
|
||||||
useZodForm({
|
useZodForm({
|
||||||
schema: loginFormSchema,
|
schema: loginRequestSchema,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
email: "",
|
email: "",
|
||||||
password: "",
|
password: "",
|
||||||
},
|
},
|
||||||
onSubmit: async data => {
|
onSubmit: async (data: LoginRequest) => {
|
||||||
// Handle form submission
|
// Handle form submission
|
||||||
await submitLogin(data);
|
await submitLogin(data);
|
||||||
},
|
},
|
||||||
@ -241,7 +241,7 @@ function MyForm() {
|
|||||||
|
|
||||||
**Available Zod schemas in `@customer-portal/domain`:**
|
**Available Zod schemas in `@customer-portal/domain`:**
|
||||||
|
|
||||||
- `loginFormSchema` - Login form validation
|
- `loginRequestSchema` - Login request validation (shared domain schema)
|
||||||
- `signupFormSchema` - User registration
|
- `signupFormSchema` - User registration
|
||||||
- `profileEditFormSchema` - Profile updates
|
- `profileEditFormSchema` - Profile updates
|
||||||
- `addressFormSchema` - Address validation
|
- `addressFormSchema` - Address validation
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
type QuickActionTask,
|
type QuickActionTask,
|
||||||
type DashboardTaskSummary,
|
type DashboardTaskSummary,
|
||||||
} from "@customer-portal/domain/dashboard";
|
} from "@customer-portal/domain/dashboard";
|
||||||
import { formatCurrency as formatCurrencyUtil } from "@customer-portal/domain/toolkit";
|
import { Formatting } from "@customer-portal/domain/toolkit";
|
||||||
|
|
||||||
// Re-export domain business logic for backward compatibility
|
// Re-export domain business logic for backward compatibility
|
||||||
export {
|
export {
|
||||||
@ -27,6 +27,8 @@ export {
|
|||||||
type DashboardTaskSummary,
|
type DashboardTaskSummary,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formatCurrencyUtil = Formatting.formatCurrency;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get navigation path for an activity
|
* Get navigation path for an activity
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -3,10 +3,10 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { queryKeys } from "@/lib/api";
|
import { queryKeys } from "@/lib/api";
|
||||||
import { currencyService } from "@/lib/services/currency.service";
|
import { currencyService } from "@/lib/services/currency.service";
|
||||||
import { FALLBACK_CURRENCY, type WhmcsCurrency } from "@customer-portal/domain/billing";
|
import { FALLBACK_CURRENCY, type Currency } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export function useCurrency() {
|
export function useCurrency() {
|
||||||
const { data, isLoading, isError, error } = useQuery<WhmcsCurrency>({
|
const { data, isLoading, isError, error } = useQuery<Currency>({
|
||||||
queryKey: queryKeys.currency.default(),
|
queryKey: queryKeys.currency.default(),
|
||||||
queryFn: () => currencyService.getDefaultCurrency(),
|
queryFn: () => currencyService.getDefaultCurrency(),
|
||||||
retry: 2,
|
retry: 2,
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useCurrency } from "@/lib/hooks/useCurrency";
|
import { useCurrency } from "@/lib/hooks/useCurrency";
|
||||||
import { FALLBACK_CURRENCY } from "@customer-portal/domain/billing";
|
import { FALLBACK_CURRENCY } from "@customer-portal/domain/billing";
|
||||||
import { formatCurrency as baseFormatCurrency } from "@customer-portal/domain/toolkit";
|
import { Formatting } from "@customer-portal/domain/toolkit";
|
||||||
|
|
||||||
export type FormatCurrencyOptions = {
|
export type FormatCurrencyOptions = {
|
||||||
currency?: string;
|
currency?: string;
|
||||||
@ -44,7 +44,7 @@ export function useFormatCurrency() {
|
|||||||
? currencyOrOptions.showSymbol
|
? currencyOrOptions.showSymbol
|
||||||
: undefined) ?? options?.showSymbol;
|
: undefined) ?? options?.showSymbol;
|
||||||
|
|
||||||
return baseFormatCurrency(amount, overrideCurrency ?? fallbackCurrency, {
|
return Formatting.formatCurrency(amount, overrideCurrency ?? fallbackCurrency, {
|
||||||
currencySymbol: overrideSymbol ?? fallbackSymbol,
|
currencySymbol: overrideSymbol ?? fallbackSymbol,
|
||||||
locale,
|
locale,
|
||||||
showSymbol,
|
showSymbol,
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
import { apiClient, getDataOrThrow } from "@/lib/api";
|
import { apiClient, getDataOrThrow } from "@/lib/api";
|
||||||
import { FALLBACK_CURRENCY, type WhmcsCurrency } from "@customer-portal/domain/billing";
|
import { FALLBACK_CURRENCY, type Currency } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export { FALLBACK_CURRENCY };
|
export { FALLBACK_CURRENCY };
|
||||||
|
|
||||||
export const currencyService = {
|
export const currencyService = {
|
||||||
async getDefaultCurrency(): Promise<WhmcsCurrency> {
|
async getDefaultCurrency(): Promise<Currency> {
|
||||||
const response = await apiClient.GET<WhmcsCurrency>("/api/currency/default");
|
const response = await apiClient.GET<Currency>("/api/currency/default");
|
||||||
return getDataOrThrow(response, "Failed to get default currency");
|
return getDataOrThrow(response, "Failed to get default currency");
|
||||||
},
|
},
|
||||||
|
|
||||||
async getAllCurrencies(): Promise<WhmcsCurrency[]> {
|
async getAllCurrencies(): Promise<Currency[]> {
|
||||||
const response = await apiClient.GET<WhmcsCurrency[]>("/api/currency/all");
|
const response = await apiClient.GET<Currency[]>("/api/currency/all");
|
||||||
return getDataOrThrow(response, "Failed to get currencies");
|
return getDataOrThrow(response, "Failed to get currencies");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -101,12 +101,11 @@ Feature guides explaining how the portal functions:
|
|||||||
|
|
||||||
### BFF (Backend for Frontend)
|
### BFF (Backend for Frontend)
|
||||||
|
|
||||||
| Document | Description |
|
| Document | Description |
|
||||||
| ----------------------------------------------------------------- | ---------------------------- |
|
| ----------------------------------------------------------------- | --------------------------- |
|
||||||
| [Integration Patterns](./development/bff/integration-patterns.md) | Clean architecture patterns |
|
| [Integration Patterns](./development/bff/integration-patterns.md) | Clean architecture patterns |
|
||||||
| [Validation Standard](./development/bff/validation.md) | DTO validation + global pipe |
|
| [DB Mappers](./development/bff/db-mappers.md) | Database mapping |
|
||||||
| [DB Mappers](./development/bff/db-mappers.md) | Database mapping |
|
| [Order Status Updates](./development/bff/order-status-updates.md) | Status update strategy |
|
||||||
| [Order Status Updates](./development/bff/order-status-updates.md) | Status update strategy |
|
|
||||||
|
|
||||||
### Portal (Frontend)
|
### Portal (Frontend)
|
||||||
|
|
||||||
|
|||||||
@ -140,11 +140,12 @@ packages/domain/
|
|||||||
|
|
||||||
#### **Usage**
|
#### **Usage**
|
||||||
|
|
||||||
Import via `@customer-portal/domain`:
|
Import via module entrypoints:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Invoice, SIM_LIFECYCLE_STAGE, OrderStatus } from "@customer-portal/domain";
|
import { invoiceSchema, type Invoice } from "@customer-portal/domain/billing";
|
||||||
import { invoiceSchema, orderSchema } from "@customer-portal/domain/validation";
|
import { orderSummarySchema, type OrderSummary } from "@customer-portal/domain/orders";
|
||||||
|
import { SIM_STATUS } from "@customer-portal/domain/sim";
|
||||||
```
|
```
|
||||||
|
|
||||||
#### **Integration with BFF**
|
#### **Integration with BFF**
|
||||||
|
|||||||
53
docs/development/domain/import-hygiene.md
Normal file
53
docs/development/domain/import-hygiene.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
## Import Hygiene Guide (Domain)
|
||||||
|
|
||||||
|
### Principles
|
||||||
|
|
||||||
|
- **No deep imports**: internal file layout is not part of the contract.
|
||||||
|
- **Barrels define the public API**: if it’s not exported from the entrypoint, it’s not public.
|
||||||
|
- **Providers are integration-only**: Portal must never import provider adapters/types.
|
||||||
|
|
||||||
|
### Allowed import levels
|
||||||
|
|
||||||
|
- **Default (Portal + BFF)**:
|
||||||
|
- `@customer-portal/domain/<module>`
|
||||||
|
- `@customer-portal/domain/toolkit`
|
||||||
|
- **BFF-only (integration/infrastructure)**:
|
||||||
|
- `@customer-portal/domain/<module>/providers`
|
||||||
|
|
||||||
|
### Never
|
||||||
|
|
||||||
|
- `@customer-portal/domain/<module>/**` (anything deeper than the module entrypoint)
|
||||||
|
- `@customer-portal/domain/<module>/providers/**` (anything deeper than `/providers`)
|
||||||
|
- `apps/portal/**` importing any `@customer-portal/domain/*/providers`
|
||||||
|
|
||||||
|
### Rule of thumb
|
||||||
|
|
||||||
|
Import from the **highest stable entrypoint** that contains what you need.
|
||||||
|
|
||||||
|
- If it exists in `@customer-portal/domain/<module>`, don’t import a deeper file.
|
||||||
|
- If it’s provider-specific, use `@customer-portal/domain/<module>/providers` (BFF-only).
|
||||||
|
- If it’s cross-domain utility, use `@customer-portal/domain/toolkit`.
|
||||||
|
|
||||||
|
### When to create a new explicit entrypoint (instead of deep-importing)
|
||||||
|
|
||||||
|
Create/adjust exports when:
|
||||||
|
|
||||||
|
- The symbol is used in 2+ apps (Portal + BFF), or many call sites.
|
||||||
|
- The symbol is part of a workflow that should remain stable (pagination, formatting, shared validation helpers).
|
||||||
|
|
||||||
|
Where to export it:
|
||||||
|
|
||||||
|
- **Module root** (`@customer-portal/domain/<module>`): normalized domain types/models, schemas, provider-agnostic helpers.
|
||||||
|
- **Providers entrypoint** (`.../<module>/providers`): provider adapters, mapper/query builder logic, raw provider shapes (if truly needed).
|
||||||
|
- **Toolkit** (`@customer-portal/domain/toolkit`): shared utilities (`Formatting`, `Validation`, `Typing` namespaces).
|
||||||
|
|
||||||
|
### Naming conventions
|
||||||
|
|
||||||
|
- **Module root**: `Invoice`, `invoiceSchema`, `validateOrderBusinessRules`
|
||||||
|
- **Providers**: `Whmcs`, `Salesforce`, `Freebit` namespaces; raw shapes should be obviously integration-only.
|
||||||
|
|
||||||
|
### PR checklist
|
||||||
|
|
||||||
|
- No `@customer-portal/domain/*/*` imports (except exact `.../<module>/providers` in BFF).
|
||||||
|
- Portal has **zero** `.../providers` imports.
|
||||||
|
- No wildcard subpath exports added to `packages/domain/package.json#exports`.
|
||||||
@ -20,6 +20,8 @@
|
|||||||
- Adding new providers = adding new folders (no refactoring)
|
- Adding new providers = adding new folders (no refactoring)
|
||||||
- Single package (`@customer-portal/domain`) for all types
|
- Single package (`@customer-portal/domain`) for all types
|
||||||
|
|
||||||
|
**Import rules**: See [`docs/development/domain/import-hygiene.md`](import-hygiene.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 Package Structure
|
## 📦 Package Structure
|
||||||
@ -130,9 +132,9 @@ const validated = invoiceSchema.parse(rawData);
|
|||||||
import { Invoice, invoiceSchema } from "@customer-portal/domain/billing";
|
import { Invoice, invoiceSchema } from "@customer-portal/domain/billing";
|
||||||
import {
|
import {
|
||||||
transformWhmcsInvoice,
|
transformWhmcsInvoice,
|
||||||
|
whmcsInvoiceRawSchema,
|
||||||
type WhmcsInvoiceRaw,
|
type WhmcsInvoiceRaw,
|
||||||
} from "@customer-portal/domain/billing/providers/whmcs/mapper";
|
} from "@customer-portal/domain/billing/providers";
|
||||||
import { whmcsInvoiceRawSchema } from "@customer-portal/domain/billing/providers/whmcs/raw.types";
|
|
||||||
|
|
||||||
// Transform raw API data
|
// Transform raw API data
|
||||||
const whmcsData: WhmcsInvoiceRaw = await whmcsApi.getInvoice(id);
|
const whmcsData: WhmcsInvoiceRaw = await whmcsApi.getInvoice(id);
|
||||||
@ -256,7 +258,7 @@ Raw types and mappers stay in `providers/`:
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ✅ GOOD - Isolated
|
// ✅ GOOD - Isolated
|
||||||
import { transformWhmcsInvoice } from "@customer-portal/domain/billing/providers/whmcs/mapper";
|
import { transformWhmcsInvoice } from "@customer-portal/domain/billing/providers";
|
||||||
|
|
||||||
// ❌ BAD - Would leak WHMCS details into app code
|
// ❌ BAD - Would leak WHMCS details into app code
|
||||||
import { WhmcsInvoiceRaw } from "@somewhere/global";
|
import { WhmcsInvoiceRaw } from "@somewhere/global";
|
||||||
@ -335,7 +337,7 @@ export function transformStripeInvoice(raw: unknown): Invoice {
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// No changes to domain contract needed!
|
// No changes to domain contract needed!
|
||||||
import { transformStripeInvoice } from "@customer-portal/domain/billing/providers/stripe/mapper";
|
import { transformStripeInvoice } from "@customer-portal/domain/billing/providers";
|
||||||
|
|
||||||
const invoice = transformStripeInvoice(stripeData);
|
const invoice = transformStripeInvoice(stripeData);
|
||||||
```
|
```
|
||||||
|
|||||||
@ -155,17 +155,79 @@ export default [
|
|||||||
"no-restricted-imports": [
|
"no-restricted-imports": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
|
paths: [
|
||||||
|
{
|
||||||
|
name: "@customer-portal/domain",
|
||||||
|
message:
|
||||||
|
"Do not import @customer-portal/domain (root). Use @customer-portal/domain/<module> instead.",
|
||||||
|
},
|
||||||
|
],
|
||||||
patterns: [
|
patterns: [
|
||||||
{
|
{
|
||||||
group: ["@customer-portal/domain/**/src/**"],
|
group: ["@customer-portal/domain/**/src/**"],
|
||||||
message: "Import from @customer-portal/domain/<module> instead of internals.",
|
message: "Import from @customer-portal/domain/<module> instead of internals.",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
group: ["@customer-portal/domain/*/*", "!@customer-portal/domain/*/providers"],
|
||||||
|
message:
|
||||||
|
"No deep @customer-portal/domain imports. Use @customer-portal/domain/<module> (or BFF-only: .../<module>/providers).",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ["@customer-portal/domain/*/providers/*"],
|
||||||
|
message:
|
||||||
|
"Do not deep-import provider internals. Import from @customer-portal/domain/<module>/providers only.",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Portal: hard boundary — must not import provider adapters/types
|
||||||
|
// =============================================================================
|
||||||
|
{
|
||||||
|
files: ["apps/portal/src/**/*.{ts,tsx}"],
|
||||||
|
rules: {
|
||||||
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
paths: [
|
||||||
|
{
|
||||||
|
name: "@customer-portal/domain",
|
||||||
|
message:
|
||||||
|
"Do not import @customer-portal/domain (root). Use @customer-portal/domain/<module> instead.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
group: ["@customer-portal/domain/**/src/**"],
|
||||||
|
message: "Import from @customer-portal/domain/<module> instead of internals.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ["@customer-portal/domain/*/providers"],
|
||||||
|
message:
|
||||||
|
"Portal must not import provider adapters/types. Import normalized domain models from @customer-portal/domain/<module> instead.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ["@customer-portal/domain/*/*", "!@customer-portal/domain/*/providers"],
|
||||||
|
message: "No deep @customer-portal/domain imports. Use @customer-portal/domain/<module> only.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ["@customer-portal/domain/*/providers/*"],
|
||||||
|
message:
|
||||||
|
"Do not deep-import provider internals. Import from @customer-portal/domain/<module>/providers only (BFF-only).",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ["apps/portal/src/app/(authenticated)/layout.tsx"],
|
||||||
|
rules: { "no-restricted-imports": "off" },
|
||||||
|
},
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// BFF: stricter type safety (type-aware)
|
// BFF: stricter type safety (type-aware)
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
* Domain constants for billing validation and business rules.
|
* Domain constants for billing validation and business rules.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { WhmcsCurrency } from "./providers/whmcs/raw.types.js";
|
import type { Currency } from "./schema.js";
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Currency Defaults
|
// Currency Defaults
|
||||||
@ -15,7 +15,7 @@ import type { WhmcsCurrency } from "./providers/whmcs/raw.types.js";
|
|||||||
* is unavailable. This ensures a single source of truth for default currency
|
* is unavailable. This ensures a single source of truth for default currency
|
||||||
* formatting behaviour.
|
* formatting behaviour.
|
||||||
*/
|
*/
|
||||||
export const FALLBACK_CURRENCY: WhmcsCurrency = {
|
export const FALLBACK_CURRENCY: Currency = {
|
||||||
id: 1,
|
id: 1,
|
||||||
code: "JPY",
|
code: "JPY",
|
||||||
prefix: "¥",
|
prefix: "¥",
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export * from "./schema.js";
|
|||||||
|
|
||||||
// Re-export types for convenience
|
// Re-export types for convenience
|
||||||
export type {
|
export type {
|
||||||
|
Currency,
|
||||||
InvoiceStatus,
|
InvoiceStatus,
|
||||||
InvoiceItem,
|
InvoiceItem,
|
||||||
Invoice,
|
Invoice,
|
||||||
@ -29,23 +30,3 @@ export type {
|
|||||||
InvoiceSsoQuery,
|
InvoiceSsoQuery,
|
||||||
InvoicePaymentLinkQuery,
|
InvoicePaymentLinkQuery,
|
||||||
} from "./schema.js";
|
} from "./schema.js";
|
||||||
|
|
||||||
// Provider adapters
|
|
||||||
export * as Providers from "./providers/index.js";
|
|
||||||
|
|
||||||
// Re-export provider raw types (request and response)
|
|
||||||
export type {
|
|
||||||
// Request params
|
|
||||||
WhmcsGetInvoicesParams,
|
|
||||||
WhmcsCreateInvoiceParams,
|
|
||||||
WhmcsUpdateInvoiceParams,
|
|
||||||
WhmcsCapturePaymentParams,
|
|
||||||
// Response types
|
|
||||||
WhmcsInvoiceListResponse,
|
|
||||||
WhmcsInvoiceResponse,
|
|
||||||
WhmcsCreateInvoiceResponse,
|
|
||||||
WhmcsUpdateInvoiceResponse,
|
|
||||||
WhmcsCapturePaymentResponse,
|
|
||||||
WhmcsCurrency,
|
|
||||||
WhmcsCurrenciesResponse,
|
|
||||||
} from "./providers/whmcs/raw.types.js";
|
|
||||||
|
|||||||
@ -7,6 +7,25 @@
|
|||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Currency (Domain Model)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalized currency model used across the Portal and BFF.
|
||||||
|
* This is intentionally provider-agnostic (even if sourced from WHMCS).
|
||||||
|
*/
|
||||||
|
export const currencySchema = z.object({
|
||||||
|
id: z.number().int().positive(),
|
||||||
|
code: z.string().min(1),
|
||||||
|
prefix: z.string(),
|
||||||
|
suffix: z.string().optional(),
|
||||||
|
format: z.string().optional(),
|
||||||
|
rate: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type Currency = z.infer<typeof currencySchema>;
|
||||||
|
|
||||||
// Invoice Status Schema
|
// Invoice Status Schema
|
||||||
export const invoiceStatusSchema = z.enum([
|
export const invoiceStatusSchema = z.enum([
|
||||||
"Draft",
|
"Draft",
|
||||||
|
|||||||
@ -8,10 +8,3 @@ export * from "./types.js";
|
|||||||
export * from "./schema.js";
|
export * from "./schema.js";
|
||||||
export * from "./validation.js";
|
export * from "./validation.js";
|
||||||
export * from "./errors.js";
|
export * from "./errors.js";
|
||||||
|
|
||||||
// Common provider types (generic wrappers used across domains)
|
|
||||||
export * as CommonProviders from "./providers/index.js";
|
|
||||||
|
|
||||||
// Re-export provider types for convenience
|
|
||||||
export type { WhmcsResponse, WhmcsErrorResponse } from "./providers/whmcs.js";
|
|
||||||
export type { SalesforceResponse } from "./providers/salesforce.js";
|
|
||||||
|
|||||||
@ -4,5 +4,11 @@
|
|||||||
* Generic provider-specific response structures used across multiple domains.
|
* Generic provider-specific response structures used across multiple domains.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * as Whmcs from "./whmcs.js";
|
export type { WhmcsResponse, WhmcsErrorResponse } from "./whmcs.js";
|
||||||
|
export { whmcsResponseSchema, whmcsErrorResponseSchema } from "./whmcs.js";
|
||||||
|
|
||||||
|
export type { SalesforceResponse } from "./salesforce.js";
|
||||||
|
export { salesforceResponseSchema } from "./salesforce.js";
|
||||||
|
|
||||||
|
// Salesforce raw types (integration-only utilities)
|
||||||
export * as Salesforce from "./salesforce/index.js";
|
export * as Salesforce from "./salesforce/index.js";
|
||||||
|
|||||||
@ -68,34 +68,6 @@ export {
|
|||||||
* - Providers.Whmcs.transformWhmcsClientResponse()
|
* - Providers.Whmcs.transformWhmcsClientResponse()
|
||||||
* - Providers.Portal.mapPrismaUserToUserAuth()
|
* - Providers.Portal.mapPrismaUserToUserAuth()
|
||||||
*/
|
*/
|
||||||
export * as Providers from "./providers/index.js";
|
// NOTE: Provider adapters and provider-specific types are intentionally not exported
|
||||||
|
// from the module root. Import BFF-only provider APIs from:
|
||||||
// ============================================================================
|
// @customer-portal/domain/customer/providers
|
||||||
// Provider Raw Response Types (Selective Exports)
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WHMCS API raw types (request and response)
|
|
||||||
* Only exported for BFF integration convenience
|
|
||||||
*/
|
|
||||||
export type {
|
|
||||||
// Request params
|
|
||||||
WhmcsAddClientParams,
|
|
||||||
WhmcsValidateLoginParams,
|
|
||||||
WhmcsCreateSsoTokenParams,
|
|
||||||
// Response types
|
|
||||||
WhmcsClientResponse,
|
|
||||||
WhmcsAddClientResponse,
|
|
||||||
WhmcsValidateLoginResponse,
|
|
||||||
WhmcsSsoResponse,
|
|
||||||
} from "./providers/whmcs/raw.types.js";
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Provider-Specific Types (For Integrations)
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Salesforce integration types
|
|
||||||
* Provider-specific, not validated at runtime
|
|
||||||
*/
|
|
||||||
export type { SalesforceAccountFieldMap, SalesforceAccountRecord } from "./contract.js";
|
|
||||||
|
|||||||
@ -8,3 +8,15 @@
|
|||||||
|
|
||||||
export * as Portal from "./portal/index.js";
|
export * as Portal from "./portal/index.js";
|
||||||
export * as Whmcs from "./whmcs/index.js";
|
export * as Whmcs from "./whmcs/index.js";
|
||||||
|
|
||||||
|
// Provider-specific integration types (BFF-only)
|
||||||
|
export type { SalesforceAccountFieldMap, SalesforceAccountRecord } from "../contract.js";
|
||||||
|
export type {
|
||||||
|
WhmcsAddClientParams,
|
||||||
|
WhmcsValidateLoginParams,
|
||||||
|
WhmcsCreateSsoTokenParams,
|
||||||
|
WhmcsClientResponse,
|
||||||
|
WhmcsAddClientResponse,
|
||||||
|
WhmcsValidateLoginResponse,
|
||||||
|
WhmcsSsoResponse,
|
||||||
|
} from "./whmcs/raw.types.js";
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { UserIdMapping } from "../mappings/contract.js";
|
import type { UserIdMapping } from "../mappings/contract.js";
|
||||||
import type { SalesforceOrderRecord } from "./providers/salesforce/raw.types.js";
|
|
||||||
import type { OrderConfigurations } from "./schema.js";
|
import type { OrderConfigurations } from "./schema.js";
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -178,12 +177,9 @@ export interface OrderCreateResponse {
|
|||||||
/**
|
/**
|
||||||
* Order fulfillment validation result
|
* Order fulfillment validation result
|
||||||
*/
|
*/
|
||||||
export interface OrderFulfillmentValidationResult {
|
// NOTE: Provider-specific fulfillment types are intentionally not part of the public orders contract.
|
||||||
sfOrder: SalesforceOrderRecord;
|
// BFF integration code should import them from:
|
||||||
clientId: number;
|
// @customer-portal/domain/orders/providers
|
||||||
isAlreadyProvisioned: boolean;
|
|
||||||
whmcsOrderId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Re-export Types from Schema (Schema-First Approach)
|
// Re-export Types from Schema (Schema-First Approach)
|
||||||
|
|||||||
@ -18,7 +18,6 @@ export {
|
|||||||
type CheckoutTotals,
|
type CheckoutTotals,
|
||||||
type CheckoutCart,
|
type CheckoutCart,
|
||||||
type OrderCreateResponse,
|
type OrderCreateResponse,
|
||||||
type OrderFulfillmentValidationResult,
|
|
||||||
// Constants
|
// Constants
|
||||||
ORDER_TYPE,
|
ORDER_TYPE,
|
||||||
ORDER_STATUS,
|
ORDER_STATUS,
|
||||||
@ -83,9 +82,6 @@ export type {
|
|||||||
} from "./schema.js";
|
} from "./schema.js";
|
||||||
|
|
||||||
// Provider adapters
|
// Provider adapters
|
||||||
export * as Providers from "./providers/index.js";
|
// NOTE: Provider adapters are intentionally not exported from the module root.
|
||||||
|
// Import BFF-only provider adapters from:
|
||||||
// Re-export provider types for convenience
|
// @customer-portal/domain/orders/providers
|
||||||
export * from "./providers/whmcs/raw.types.js";
|
|
||||||
export * from "./providers/salesforce/raw.types.js";
|
|
||||||
export * from "./providers/salesforce/field-map.js";
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import * as WhmcsRaw from "./whmcs/raw.types.js";
|
|||||||
import * as SalesforceFieldMap from "./salesforce/field-map.js";
|
import * as SalesforceFieldMap from "./salesforce/field-map.js";
|
||||||
import * as SalesforceMapper from "./salesforce/mapper.js";
|
import * as SalesforceMapper from "./salesforce/mapper.js";
|
||||||
import * as SalesforceRaw from "./salesforce/raw.types.js";
|
import * as SalesforceRaw from "./salesforce/raw.types.js";
|
||||||
|
export * from "./types.js";
|
||||||
|
|
||||||
export const Whmcs = {
|
export const Whmcs = {
|
||||||
...WhmcsMapper,
|
...WhmcsMapper,
|
||||||
|
|||||||
14
packages/domain/orders/providers/types.ts
Normal file
14
packages/domain/orders/providers/types.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import type { SalesforceOrderRecord } from "./salesforce/raw.types.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order fulfillment validation result (integration-only)
|
||||||
|
*
|
||||||
|
* This intentionally lives under the providers entrypoint to avoid leaking
|
||||||
|
* raw provider shapes into the public orders module API.
|
||||||
|
*/
|
||||||
|
export interface OrderFulfillmentValidationResult {
|
||||||
|
sfOrder: SalesforceOrderRecord;
|
||||||
|
clientId: number;
|
||||||
|
isAlreadyProvisioned: boolean;
|
||||||
|
whmcsOrderId?: string;
|
||||||
|
}
|
||||||
@ -11,157 +11,113 @@
|
|||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
|
||||||
"import": "./dist/index.js",
|
|
||||||
"types": "./dist/index.d.ts"
|
|
||||||
},
|
|
||||||
"./auth": {
|
"./auth": {
|
||||||
"import": "./dist/auth/index.js",
|
"import": "./dist/auth/index.js",
|
||||||
"types": "./dist/auth/index.d.ts"
|
"types": "./dist/auth/index.d.ts"
|
||||||
},
|
},
|
||||||
"./auth/*": {
|
|
||||||
"import": "./dist/auth/*.js",
|
|
||||||
"types": "./dist/auth/*.d.ts"
|
|
||||||
},
|
|
||||||
"./billing": {
|
"./billing": {
|
||||||
"import": "./dist/billing/index.js",
|
"import": "./dist/billing/index.js",
|
||||||
"types": "./dist/billing/index.d.ts"
|
"types": "./dist/billing/index.d.ts"
|
||||||
},
|
},
|
||||||
"./billing/*": {
|
"./billing/providers": {
|
||||||
"import": "./dist/billing/*.js",
|
"import": "./dist/billing/providers/index.js",
|
||||||
"types": "./dist/billing/*.d.ts"
|
"types": "./dist/billing/providers/index.d.ts"
|
||||||
},
|
},
|
||||||
"./services": {
|
"./services": {
|
||||||
"import": "./dist/services/index.js",
|
"import": "./dist/services/index.js",
|
||||||
"types": "./dist/services/index.d.ts"
|
"types": "./dist/services/index.d.ts"
|
||||||
},
|
},
|
||||||
"./services/*": {
|
"./services/providers": {
|
||||||
"import": "./dist/services/*.js",
|
"import": "./dist/services/providers/index.js",
|
||||||
"types": "./dist/services/*.d.ts"
|
"types": "./dist/services/providers/index.d.ts"
|
||||||
},
|
},
|
||||||
"./checkout": {
|
"./checkout": {
|
||||||
"import": "./dist/checkout/index.js",
|
"import": "./dist/checkout/index.js",
|
||||||
"types": "./dist/checkout/index.d.ts"
|
"types": "./dist/checkout/index.d.ts"
|
||||||
},
|
},
|
||||||
"./checkout/*": {
|
|
||||||
"import": "./dist/checkout/*.js",
|
|
||||||
"types": "./dist/checkout/*.d.ts"
|
|
||||||
},
|
|
||||||
"./common": {
|
"./common": {
|
||||||
"import": "./dist/common/index.js",
|
"import": "./dist/common/index.js",
|
||||||
"types": "./dist/common/index.d.ts"
|
"types": "./dist/common/index.d.ts"
|
||||||
},
|
},
|
||||||
"./common/*": {
|
"./common/providers": {
|
||||||
"import": "./dist/common/*.js",
|
"import": "./dist/common/providers/index.js",
|
||||||
"types": "./dist/common/*.d.ts"
|
"types": "./dist/common/providers/index.d.ts"
|
||||||
},
|
},
|
||||||
"./customer": {
|
"./customer": {
|
||||||
"import": "./dist/customer/index.js",
|
"import": "./dist/customer/index.js",
|
||||||
"types": "./dist/customer/index.d.ts"
|
"types": "./dist/customer/index.d.ts"
|
||||||
},
|
},
|
||||||
"./customer/*": {
|
"./customer/providers": {
|
||||||
"import": "./dist/customer/*.js",
|
"import": "./dist/customer/providers/index.js",
|
||||||
"types": "./dist/customer/*.d.ts"
|
"types": "./dist/customer/providers/index.d.ts"
|
||||||
},
|
},
|
||||||
"./dashboard": {
|
"./dashboard": {
|
||||||
"import": "./dist/dashboard/index.js",
|
"import": "./dist/dashboard/index.js",
|
||||||
"types": "./dist/dashboard/index.d.ts"
|
"types": "./dist/dashboard/index.d.ts"
|
||||||
},
|
},
|
||||||
"./dashboard/*": {
|
|
||||||
"import": "./dist/dashboard/*.js",
|
|
||||||
"types": "./dist/dashboard/*.d.ts"
|
|
||||||
},
|
|
||||||
"./mappings": {
|
"./mappings": {
|
||||||
"import": "./dist/mappings/index.js",
|
"import": "./dist/mappings/index.js",
|
||||||
"types": "./dist/mappings/index.d.ts"
|
"types": "./dist/mappings/index.d.ts"
|
||||||
},
|
},
|
||||||
"./mappings/*": {
|
|
||||||
"import": "./dist/mappings/*.js",
|
|
||||||
"types": "./dist/mappings/*.d.ts"
|
|
||||||
},
|
|
||||||
"./opportunity": {
|
"./opportunity": {
|
||||||
"import": "./dist/opportunity/index.js",
|
"import": "./dist/opportunity/index.js",
|
||||||
"types": "./dist/opportunity/index.d.ts"
|
"types": "./dist/opportunity/index.d.ts"
|
||||||
},
|
},
|
||||||
"./opportunity/*": {
|
|
||||||
"import": "./dist/opportunity/*.js",
|
|
||||||
"types": "./dist/opportunity/*.d.ts"
|
|
||||||
},
|
|
||||||
"./orders": {
|
"./orders": {
|
||||||
"import": "./dist/orders/index.js",
|
"import": "./dist/orders/index.js",
|
||||||
"types": "./dist/orders/index.d.ts"
|
"types": "./dist/orders/index.d.ts"
|
||||||
},
|
},
|
||||||
"./orders/*": {
|
"./orders/providers": {
|
||||||
"import": "./dist/orders/*.js",
|
"import": "./dist/orders/providers/index.js",
|
||||||
"types": "./dist/orders/*.d.ts"
|
"types": "./dist/orders/providers/index.d.ts"
|
||||||
},
|
},
|
||||||
"./payments": {
|
"./payments": {
|
||||||
"import": "./dist/payments/index.js",
|
"import": "./dist/payments/index.js",
|
||||||
"types": "./dist/payments/index.d.ts"
|
"types": "./dist/payments/index.d.ts"
|
||||||
},
|
},
|
||||||
"./payments/*": {
|
"./payments/providers": {
|
||||||
"import": "./dist/payments/*.js",
|
"import": "./dist/payments/providers/index.js",
|
||||||
"types": "./dist/payments/*.d.ts"
|
"types": "./dist/payments/providers/index.d.ts"
|
||||||
},
|
},
|
||||||
"./realtime": {
|
"./realtime": {
|
||||||
"import": "./dist/realtime/index.js",
|
"import": "./dist/realtime/index.js",
|
||||||
"types": "./dist/realtime/index.d.ts"
|
"types": "./dist/realtime/index.d.ts"
|
||||||
},
|
},
|
||||||
"./realtime/*": {
|
|
||||||
"import": "./dist/realtime/*.js",
|
|
||||||
"types": "./dist/realtime/*.d.ts"
|
|
||||||
},
|
|
||||||
"./sim": {
|
"./sim": {
|
||||||
"import": "./dist/sim/index.js",
|
"import": "./dist/sim/index.js",
|
||||||
"types": "./dist/sim/index.d.ts"
|
"types": "./dist/sim/index.d.ts"
|
||||||
},
|
},
|
||||||
"./sim/*": {
|
"./sim/providers": {
|
||||||
"import": "./dist/sim/*.js",
|
"import": "./dist/sim/providers/index.js",
|
||||||
"types": "./dist/sim/*.d.ts"
|
"types": "./dist/sim/providers/index.d.ts"
|
||||||
},
|
|
||||||
"./sim/providers/freebit": {
|
|
||||||
"import": "./dist/sim/providers/freebit/index.js",
|
|
||||||
"types": "./dist/sim/providers/freebit/index.d.ts"
|
|
||||||
},
|
},
|
||||||
"./subscriptions": {
|
"./subscriptions": {
|
||||||
"import": "./dist/subscriptions/index.js",
|
"import": "./dist/subscriptions/index.js",
|
||||||
"types": "./dist/subscriptions/index.d.ts"
|
"types": "./dist/subscriptions/index.d.ts"
|
||||||
},
|
},
|
||||||
"./subscriptions/*": {
|
"./subscriptions/providers": {
|
||||||
"import": "./dist/subscriptions/*.js",
|
"import": "./dist/subscriptions/providers/index.js",
|
||||||
"types": "./dist/subscriptions/*.d.ts"
|
"types": "./dist/subscriptions/providers/index.d.ts"
|
||||||
},
|
},
|
||||||
"./support": {
|
"./support": {
|
||||||
"import": "./dist/support/index.js",
|
"import": "./dist/support/index.js",
|
||||||
"types": "./dist/support/index.d.ts"
|
"types": "./dist/support/index.d.ts"
|
||||||
},
|
},
|
||||||
"./support/*": {
|
"./support/providers": {
|
||||||
"import": "./dist/support/*.js",
|
"import": "./dist/support/providers/index.js",
|
||||||
"types": "./dist/support/*.d.ts"
|
"types": "./dist/support/providers/index.d.ts"
|
||||||
},
|
},
|
||||||
"./toolkit": {
|
"./toolkit": {
|
||||||
"import": "./dist/toolkit/index.js",
|
"import": "./dist/toolkit/index.js",
|
||||||
"types": "./dist/toolkit/index.d.ts"
|
"types": "./dist/toolkit/index.d.ts"
|
||||||
},
|
},
|
||||||
"./toolkit/*": {
|
|
||||||
"import": "./dist/toolkit/*.js",
|
|
||||||
"types": "./dist/toolkit/*.d.ts"
|
|
||||||
},
|
|
||||||
"./notifications": {
|
"./notifications": {
|
||||||
"import": "./dist/notifications/index.js",
|
"import": "./dist/notifications/index.js",
|
||||||
"types": "./dist/notifications/index.d.ts"
|
"types": "./dist/notifications/index.d.ts"
|
||||||
},
|
},
|
||||||
"./notifications/*": {
|
|
||||||
"import": "./dist/notifications/*.js",
|
|
||||||
"types": "./dist/notifications/*.d.ts"
|
|
||||||
},
|
|
||||||
"./salesforce": {
|
"./salesforce": {
|
||||||
"import": "./dist/salesforce/index.js",
|
"import": "./dist/salesforce/index.js",
|
||||||
"types": "./dist/salesforce/index.d.ts"
|
"types": "./dist/salesforce/index.d.ts"
|
||||||
},
|
|
||||||
"./salesforce/*": {
|
|
||||||
"import": "./dist/salesforce/*.js",
|
|
||||||
"types": "./dist/salesforce/*.d.ts"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -21,17 +21,3 @@ export type {
|
|||||||
PaymentGateway,
|
PaymentGateway,
|
||||||
PaymentGatewayList,
|
PaymentGatewayList,
|
||||||
} from "./schema.js";
|
} from "./schema.js";
|
||||||
|
|
||||||
// Provider adapters
|
|
||||||
export * as Providers from "./providers/index.js";
|
|
||||||
|
|
||||||
// Re-export provider raw types (request and response)
|
|
||||||
export type {
|
|
||||||
// Request params
|
|
||||||
WhmcsGetPayMethodsParams,
|
|
||||||
// Response types
|
|
||||||
WhmcsPaymentMethod,
|
|
||||||
WhmcsPaymentMethodListResponse,
|
|
||||||
WhmcsPaymentGateway,
|
|
||||||
WhmcsPaymentGatewayListResponse,
|
|
||||||
} from "./providers/whmcs/raw.types.js";
|
|
||||||
|
|||||||
@ -6,13 +6,7 @@
|
|||||||
* Types are derived from Zod schemas (Schema-First Approach)
|
* Types are derived from Zod schemas (Schema-First Approach)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Provider-specific types
|
export { type PricingTier, type CatalogPriceInfo } from "./contract.js";
|
||||||
export {
|
|
||||||
type SalesforceProductFieldMap,
|
|
||||||
type PricingTier,
|
|
||||||
type CatalogFilter,
|
|
||||||
type CatalogPriceInfo,
|
|
||||||
} from "./contract.js";
|
|
||||||
|
|
||||||
// Schemas (includes derived types)
|
// Schemas (includes derived types)
|
||||||
export * from "./schema.js";
|
export * from "./schema.js";
|
||||||
@ -40,21 +34,5 @@ export type {
|
|||||||
CatalogProduct,
|
CatalogProduct,
|
||||||
} from "./schema.js";
|
} from "./schema.js";
|
||||||
|
|
||||||
// Provider adapters
|
|
||||||
export * as Providers from "./providers/index.js";
|
|
||||||
|
|
||||||
// Re-export provider raw types for convenience
|
|
||||||
export * from "./providers/salesforce/raw.types.js";
|
|
||||||
|
|
||||||
// Re-export WHMCS provider types
|
|
||||||
export type {
|
|
||||||
WhmcsCatalogProduct,
|
|
||||||
WhmcsCatalogProductListResponse,
|
|
||||||
} from "./providers/whmcs/raw.types.js";
|
|
||||||
export type {
|
|
||||||
WhmcsCatalogProductNormalized,
|
|
||||||
WhmcsCatalogPricing,
|
|
||||||
} from "./providers/whmcs/mapper.js";
|
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
export * from "./utils.js";
|
export * from "./utils.js";
|
||||||
|
|||||||
@ -84,6 +84,3 @@ export type {
|
|||||||
} from "./schema.js";
|
} from "./schema.js";
|
||||||
export type { SimPlanCode } from "./contract.js";
|
export type { SimPlanCode } from "./contract.js";
|
||||||
export type { SimPlanOption, SimFeatureToggleSnapshot } from "./helpers.js";
|
export type { SimPlanOption, SimFeatureToggleSnapshot } from "./helpers.js";
|
||||||
|
|
||||||
// Provider adapters
|
|
||||||
export * as Providers from "./providers/index.js";
|
|
||||||
|
|||||||
@ -37,16 +37,3 @@ export {
|
|||||||
internetCancellationPreviewSchema,
|
internetCancellationPreviewSchema,
|
||||||
internetCancelRequestSchema,
|
internetCancelRequestSchema,
|
||||||
} from "./schema.js";
|
} from "./schema.js";
|
||||||
|
|
||||||
// Provider adapters
|
|
||||||
export * as Providers from "./providers/index.js";
|
|
||||||
|
|
||||||
// Re-export provider raw types (request and response)
|
|
||||||
export type {
|
|
||||||
// Request params
|
|
||||||
WhmcsGetClientsProductsParams,
|
|
||||||
// Response types
|
|
||||||
WhmcsProductListResponse,
|
|
||||||
} from "./providers/whmcs/raw.types.js";
|
|
||||||
|
|
||||||
export { whmcsProductListResponseSchema } from "./providers/whmcs/raw.types.js";
|
|
||||||
|
|||||||
@ -16,10 +16,3 @@ export {
|
|||||||
|
|
||||||
// Schemas (includes derived types)
|
// Schemas (includes derived types)
|
||||||
export * from "./schema.js";
|
export * from "./schema.js";
|
||||||
|
|
||||||
// Provider adapters
|
|
||||||
export * as Providers from "./providers/index.js";
|
|
||||||
|
|
||||||
// Re-export provider types for convenience
|
|
||||||
export * from "./providers/salesforce/raw.types.js";
|
|
||||||
export * from "./providers/salesforce/mapper.js";
|
|
||||||
|
|||||||
@ -71,18 +71,18 @@ getHostname(url); // Extracts hostname
|
|||||||
### Formatting
|
### Formatting
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { formatCurrency, formatDate } from "@customer-portal/domain/toolkit/formatting";
|
import { Formatting } from "@customer-portal/domain/toolkit";
|
||||||
|
|
||||||
const price = formatCurrency(1000, "JPY"); // "¥1,000"
|
const price = Formatting.formatCurrency(1000, "JPY"); // "¥1,000"
|
||||||
const date = formatDate(new Date()); // "2025-10-08"
|
const date = Formatting.formatDate(new Date()); // "2025-10-08"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Type Guards
|
### Type Guards
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { isString, isNumber } from "@customer-portal/domain/toolkit/typing";
|
import { Typing } from "@customer-portal/domain/toolkit";
|
||||||
|
|
||||||
if (isString(value)) {
|
if (Typing.isString(value)) {
|
||||||
// TypeScript knows value is string here
|
// TypeScript knows value is string here
|
||||||
console.log(value.toUpperCase());
|
console.log(value.toUpperCase());
|
||||||
}
|
}
|
||||||
@ -91,31 +91,31 @@ if (isString(value)) {
|
|||||||
### URL Utilities
|
### URL Utilities
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { ensureProtocol, getHostname } from "@customer-portal/domain/toolkit/validation/url";
|
import { Validation } from "@customer-portal/domain/toolkit";
|
||||||
|
|
||||||
const fullUrl = ensureProtocol("example.com"); // "https://example.com"
|
const fullUrl = Validation.ensureProtocol("example.com"); // "https://example.com"
|
||||||
const host = getHostname("https://example.com/path"); // "example.com"
|
const host = Validation.getHostname("https://example.com/path"); // "example.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Email Utilities
|
### Email Utilities
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getEmailDomain, normalizeEmail } from "@customer-portal/domain/toolkit/validation/email";
|
import { Validation } from "@customer-portal/domain/toolkit";
|
||||||
|
|
||||||
const domain = getEmailDomain("user@example.com"); // "example.com"
|
const domain = Validation.getEmailDomain("user@example.com"); // "example.com"
|
||||||
const normalized = normalizeEmail(" User@Example.COM "); // "user@example.com"
|
const normalized = Validation.normalizeEmail(" User@Example.COM "); // "user@example.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
## When to Use What
|
## When to Use What
|
||||||
|
|
||||||
| Task | Use | Example |
|
| Task | Use | Example |
|
||||||
| --------------------- | -------------------------------- | ------------------------------- |
|
| --------------------- | ---------------------- | ------------------------------------------ |
|
||||||
| Validate email format | `common/validation.ts` | `isValidEmail(email)` |
|
| Validate email format | `common/validation.ts` | `isValidEmail(email)` |
|
||||||
| Extract email domain | `toolkit/validation/email.ts` | `getEmailDomain(email)` |
|
| Extract email domain | `toolkit` | `Validation.getEmailDomain(email)` |
|
||||||
| Validate URL format | `common/validation.ts` | `isValidUrl(url)` |
|
| Validate URL format | `common/validation.ts` | `isValidUrl(url)` |
|
||||||
| Add protocol to URL | `toolkit/validation/url.ts` | `ensureProtocol(url)` |
|
| Add protocol to URL | `toolkit` | `Validation.ensureProtocol(url)` |
|
||||||
| Format currency | `toolkit/formatting/currency.ts` | `formatCurrency(amount, "JPY")` |
|
| Format currency | `toolkit` | `Formatting.formatCurrency(amount, "JPY")` |
|
||||||
| Format date | `toolkit/formatting/date.ts` | `formatDate(date)` |
|
| Format date | `toolkit` | `Formatting.formatDate(date)` |
|
||||||
|
|
||||||
## Best Practices
|
## Best Practices
|
||||||
|
|
||||||
@ -134,8 +134,8 @@ const normalized = normalizeEmail(" User@Example.COM "); // "user@example.com"
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ✅ Good
|
// ✅ Good
|
||||||
import { normalizeEmail } from "@customer-portal/domain/toolkit/validation/email";
|
import { Validation } from "@customer-portal/domain/toolkit";
|
||||||
const clean = normalizeEmail(email);
|
const clean = Validation.normalizeEmail(email);
|
||||||
|
|
||||||
// ❌ Bad - don't duplicate utility logic
|
// ❌ Bad - don't duplicate utility logic
|
||||||
const clean = email.trim().toLowerCase();
|
const clean = email.trim().toLowerCase();
|
||||||
@ -152,11 +152,11 @@ const normalized = normalizeEmail(" User@Example.COM "); // "user@example.com"
|
|||||||
|
|
||||||
// ✅ Good - separate concerns
|
// ✅ Good - separate concerns
|
||||||
import { isValidEmail } from "@customer-portal/domain/common/validation";
|
import { isValidEmail } from "@customer-portal/domain/common/validation";
|
||||||
import { normalizeEmail } from "@customer-portal/domain/toolkit/validation/email";
|
import { Validation } from "@customer-portal/domain/toolkit";
|
||||||
|
|
||||||
function processEmail(email: string) {
|
function processEmail(email: string) {
|
||||||
if (!isValidEmail(email)) return null;
|
if (!isValidEmail(email)) return null;
|
||||||
return normalizeEmail(email);
|
return Validation.normalizeEmail(email);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -7,20 +7,3 @@
|
|||||||
export * as Formatting from "./formatting/index.js";
|
export * as Formatting from "./formatting/index.js";
|
||||||
export * as Validation from "./validation/index.js";
|
export * as Validation from "./validation/index.js";
|
||||||
export * as Typing from "./typing/index.js";
|
export * as Typing from "./typing/index.js";
|
||||||
|
|
||||||
// Re-export commonly used utilities for convenience
|
|
||||||
export { formatCurrency } from "./formatting/currency.js";
|
|
||||||
export type { SupportedCurrency } from "./formatting/currency.js";
|
|
||||||
|
|
||||||
// Re-export AsyncState types and helpers
|
|
||||||
export type { AsyncState } from "./typing/helpers.js";
|
|
||||||
export {
|
|
||||||
createIdleState,
|
|
||||||
createLoadingState,
|
|
||||||
createSuccessState,
|
|
||||||
createErrorState,
|
|
||||||
isIdle,
|
|
||||||
isLoading,
|
|
||||||
isSuccess,
|
|
||||||
isError,
|
|
||||||
} from "./typing/helpers.js";
|
|
||||||
|
|||||||
@ -10,6 +10,12 @@ cd "$ROOT_DIR"
|
|||||||
echo "[domain] Building @customer-portal/domain…"
|
echo "[domain] Building @customer-portal/domain…"
|
||||||
pnpm --filter @customer-portal/domain build >/dev/null
|
pnpm --filter @customer-portal/domain build >/dev/null
|
||||||
|
|
||||||
|
echo "[domain] Checking exports contract…"
|
||||||
|
node ./scripts/domain/check-exports.mjs
|
||||||
|
|
||||||
|
echo "[domain] Checking import contract…"
|
||||||
|
bash ./scripts/domain/check-import-contract.sh
|
||||||
|
|
||||||
if command -v git >/dev/null 2>&1; then
|
if command -v git >/dev/null 2>&1; then
|
||||||
if git diff --quiet -- packages/domain/dist; then
|
if git diff --quiet -- packages/domain/dist; then
|
||||||
echo "[domain] OK: packages/domain/dist is up to date."
|
echo "[domain] OK: packages/domain/dist is up to date."
|
||||||
|
|||||||
26
scripts/domain/check-exports.mjs
Normal file
26
scripts/domain/check-exports.mjs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
const ROOT = process.cwd();
|
||||||
|
const pkgPath = path.join(ROOT, "packages", "domain", "package.json");
|
||||||
|
|
||||||
|
const pkg = JSON.parse(await fs.readFile(pkgPath, "utf8"));
|
||||||
|
|
||||||
|
const exportsField = pkg.exports;
|
||||||
|
if (!exportsField || typeof exportsField !== "object") {
|
||||||
|
console.error("[domain] ERROR: package.json exports field is missing or invalid.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const keys = Object.keys(exportsField);
|
||||||
|
const wildcardKeys = keys.filter(k => k.includes("*"));
|
||||||
|
|
||||||
|
if (wildcardKeys.length > 0) {
|
||||||
|
console.error("[domain] ERROR: wildcard subpath exports are not allowed:");
|
||||||
|
for (const k of wildcardKeys) console.error(`- ${k}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("[domain] OK: package.json exports contains no wildcard keys.");
|
||||||
|
|
||||||
|
|
||||||
64
scripts/domain/check-import-contract.sh
Normal file
64
scripts/domain/check-import-contract.sh
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Guardrail: enforce the domain import contract.
|
||||||
|
#
|
||||||
|
# Allowed:
|
||||||
|
# - @customer-portal/domain/<module>
|
||||||
|
# - @customer-portal/domain/toolkit
|
||||||
|
# - BFF-only: @customer-portal/domain/<module>/providers
|
||||||
|
#
|
||||||
|
# Never:
|
||||||
|
# - @customer-portal/domain/<module>/<anything-else>
|
||||||
|
# - @customer-portal/domain/<module>/providers/<anything-else>
|
||||||
|
# - Portal importing any .../providers
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "[domain] ERROR: $1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "[domain] Checking for illegal deep imports in apps/…"
|
||||||
|
|
||||||
|
# Root import is forbidden (hard error). Only match actual import statements.
|
||||||
|
if grep -RInE --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.next \
|
||||||
|
--include='*.ts' --include='*.tsx' \
|
||||||
|
"(from[[:space:]]+[\"']@customer-portal/domain[\"'])|(import[[:space:]]+[\"']@customer-portal/domain[\"'])" \
|
||||||
|
apps >/dev/null; then
|
||||||
|
echo "[domain] Found forbidden root imports (@customer-portal/domain):"
|
||||||
|
grep -RInE --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.next \
|
||||||
|
--include='*.ts' --include='*.tsx' \
|
||||||
|
"(from[[:space:]]+[\"']@customer-portal/domain[\"'])|(import[[:space:]]+[\"']@customer-portal/domain[\"'])" \
|
||||||
|
apps | head -200
|
||||||
|
fail "Root import is forbidden. Use @customer-portal/domain/<module>."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Any 3+ segment import like @customer-portal/domain/a/b/c is illegal anywhere.
|
||||||
|
if grep -RInE --include='*.ts' --include='*.tsx' \
|
||||||
|
"@customer-portal/domain/[^\"'[:space:]]+/[^\"'[:space:]]+/[^\"'[:space:]]+" \
|
||||||
|
apps >/dev/null; then
|
||||||
|
echo "[domain] Found illegal deep imports (3+ segments):"
|
||||||
|
grep -RInE --include='*.ts' --include='*.tsx' \
|
||||||
|
"@customer-portal/domain/[^\"'[:space:]]+/[^\"'[:space:]]+/[^\"'[:space:]]+" \
|
||||||
|
apps | head -200
|
||||||
|
fail "Deep imports detected. Use @customer-portal/domain/<module> or .../<module>/providers."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[domain] Checking Portal boundary (no providers imports)…"
|
||||||
|
|
||||||
|
if grep -RInE --include='*.ts' --include='*.tsx' \
|
||||||
|
"@customer-portal/domain/[^\"'[:space:]]+/providers" \
|
||||||
|
apps/portal/src >/dev/null; then
|
||||||
|
echo "[domain] Found provider imports in Portal:"
|
||||||
|
grep -RInE --include='*.ts' --include='*.tsx' \
|
||||||
|
"@customer-portal/domain/[^\"'[:space:]]+/providers" \
|
||||||
|
apps/portal/src | head -200
|
||||||
|
fail "Portal must not import provider adapters/types."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[domain] OK: import contract checks passed."
|
||||||
|
|
||||||
|
|
||||||
129
scripts/domain/codemod-domain-imports.mjs
Normal file
129
scripts/domain/codemod-domain-imports.mjs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
const ROOT = process.cwd();
|
||||||
|
const TARGET_DIRS = [
|
||||||
|
path.join(ROOT, "apps", "bff", "src"),
|
||||||
|
path.join(ROOT, "apps", "portal", "src"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const FILE_EXTS = new Set([".ts", ".tsx"]);
|
||||||
|
|
||||||
|
async function* walk(dir) {
|
||||||
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
for (const e of entries) {
|
||||||
|
const p = path.join(dir, e.name);
|
||||||
|
if (e.isDirectory()) {
|
||||||
|
if (e.name === "node_modules" || e.name === "dist" || e.name.startsWith(".")) continue;
|
||||||
|
yield* walk(p);
|
||||||
|
} else if (e.isFile()) {
|
||||||
|
if (FILE_EXTS.has(path.extname(e.name))) yield p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceProvidersDeepImports(code) {
|
||||||
|
// "@customer-portal/domain/<module>/providers/<anything>" -> ".../<module>/providers"
|
||||||
|
return code
|
||||||
|
.replaceAll(
|
||||||
|
/from\s+"@customer-portal\/domain\/([a-z-]+)\/providers\/[^"]+"/g,
|
||||||
|
'from "@customer-portal/domain/$1/providers"'
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/from\s+'@customer-portal\/domain\/([a-z-]+)\/providers\/[^']+'/g,
|
||||||
|
"from '@customer-portal/domain/$1/providers'"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceCommonProviderTypes(code) {
|
||||||
|
// Move provider response wrapper types out of common root -> common/providers
|
||||||
|
// Only touches *type-only* imports to avoid moving runtime exports accidentally.
|
||||||
|
return code
|
||||||
|
.replaceAll(
|
||||||
|
/import\s+type\s+\{([^}]*)\}\s+from\s+"@customer-portal\/domain\/common";/g,
|
||||||
|
(m, spec) => {
|
||||||
|
const s = String(spec);
|
||||||
|
const needsMove =
|
||||||
|
s.includes("WhmcsResponse") || s.includes("WhmcsErrorResponse") || s.includes("SalesforceResponse");
|
||||||
|
if (!needsMove) return m;
|
||||||
|
return `import type {${spec}} from "@customer-portal/domain/common/providers";`;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/import\s+type\s+\{([^}]*)\}\s+from\s+'@customer-portal\/domain\/common';/g,
|
||||||
|
(m, spec) => {
|
||||||
|
const s = String(spec);
|
||||||
|
const needsMove =
|
||||||
|
s.includes("WhmcsResponse") || s.includes("WhmcsErrorResponse") || s.includes("SalesforceResponse");
|
||||||
|
if (!needsMove) return m;
|
||||||
|
return `import type {${spec}} from '@customer-portal/domain/common/providers';`;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceProvidersNamespaceImports(code) {
|
||||||
|
// import { Providers } from "@customer-portal/domain/<module>";
|
||||||
|
// import { Providers as Foo } from "@customer-portal/domain/<module>";
|
||||||
|
return code
|
||||||
|
.replaceAll(
|
||||||
|
/import\s+\{\s*Providers\s*\}\s+from\s+"@customer-portal\/domain\/([a-z-]+)";/g,
|
||||||
|
'import * as Providers from "@customer-portal/domain/$1/providers";'
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/import\s+\{\s*Providers\s+as\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*\}\s+from\s+"@customer-portal\/domain\/([a-z-]+)";/g,
|
||||||
|
'import * as $1 from "@customer-portal/domain/$2/providers";'
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/import\s+\{\s*Providers\s*\}\s+from\s+'@customer-portal\/domain\/([a-z-]+)';/g,
|
||||||
|
"import * as Providers from '@customer-portal/domain/$1/providers';"
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/import\s+\{\s*Providers\s+as\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*\}\s+from\s+'@customer-portal\/domain\/([a-z-]+)';/g,
|
||||||
|
"import * as $1 from '@customer-portal/domain/$2/providers';"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceToolkitPaginationHelper(code) {
|
||||||
|
if (!code.includes("@customer-portal/domain/toolkit/validation/helpers")) return code;
|
||||||
|
let next = code;
|
||||||
|
|
||||||
|
next = next
|
||||||
|
.replaceAll(
|
||||||
|
/import\s+\{\s*createPaginationSchema\s*\}\s+from\s+"@customer-portal\/domain\/toolkit\/validation\/helpers";/g,
|
||||||
|
'import { Validation } from "@customer-portal/domain/toolkit";'
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/import\s+\{\s*createPaginationSchema\s*\}\s+from\s+'@customer-portal\/domain\/toolkit\/validation\/helpers';/g,
|
||||||
|
"import { Validation } from '@customer-portal/domain/toolkit';"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update call sites
|
||||||
|
next = next.replaceAll(/\bcreatePaginationSchema\b/g, "Validation.createPaginationSchema");
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
function transform(code) {
|
||||||
|
let next = code;
|
||||||
|
next = replaceProvidersDeepImports(next);
|
||||||
|
next = replaceCommonProviderTypes(next);
|
||||||
|
next = replaceProvidersNamespaceImports(next);
|
||||||
|
next = replaceToolkitPaginationHelper(next);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
let changedFiles = 0;
|
||||||
|
for (const dir of TARGET_DIRS) {
|
||||||
|
for await (const file of walk(dir)) {
|
||||||
|
const before = await fs.readFile(file, "utf8");
|
||||||
|
const after = transform(before);
|
||||||
|
if (after !== before) {
|
||||||
|
await fs.writeFile(file, after, "utf8");
|
||||||
|
changedFiles += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`codemod-domain-imports: updated ${changedFiles} file(s)`);
|
||||||
|
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ migrate_directory() {
|
|||||||
-e 's|@customer-portal/contracts/sim|@customer-portal/domain/sim|g' \
|
-e 's|@customer-portal/contracts/sim|@customer-portal/domain/sim|g' \
|
||||||
-e 's|@customer-portal/schemas/business/sim|@customer-portal/domain/sim|g' \
|
-e 's|@customer-portal/schemas/business/sim|@customer-portal/domain/sim|g' \
|
||||||
-e 's|@customer-portal/integrations-freebit/mappers/sim|@customer-portal/domain/sim|g' \
|
-e 's|@customer-portal/integrations-freebit/mappers/sim|@customer-portal/domain/sim|g' \
|
||||||
-e 's|@customer-portal/schemas/integrations/freebit/requests|@customer-portal/domain/sim/providers/freebit|g' \
|
-e 's|@customer-portal/schemas/integrations/freebit/requests|@customer-portal/domain/sim/providers|g' \
|
||||||
{} +
|
{} +
|
||||||
|
|
||||||
# Orders domain
|
# Orders domain
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user