- Refactor various mappers in billing, payments, services, and subscriptions to ensure IDs are consistently converted to numbers. - Update raw types schemas to utilize whmcsNumberLike and whmcsString for improved validation and type safety. - Enhance the whmcs-utils to include schema exports for better modularity.
125 lines
3.4 KiB
TypeScript
125 lines
3.4 KiB
TypeScript
import { parseAmount } from "../../../common/providers/whmcs-utils/index.js";
|
|
import {
|
|
whmcsCatalogProductListResponseSchema,
|
|
type WhmcsCatalogProductListResponse,
|
|
} from "./raw.types.js";
|
|
|
|
export interface WhmcsCatalogPricing {
|
|
currency: string;
|
|
prefix?: string | undefined;
|
|
suffix?: string | undefined;
|
|
monthly?: number | undefined;
|
|
quarterly?: number | undefined;
|
|
semiannually?: number | undefined;
|
|
annually?: number | undefined;
|
|
biennially?: number | undefined;
|
|
triennially?: number | undefined;
|
|
setupFees: {
|
|
monthly?: number | undefined;
|
|
quarterly?: number | undefined;
|
|
semiannually?: number | undefined;
|
|
annually?: number | undefined;
|
|
biennially?: number | undefined;
|
|
triennially?: number | undefined;
|
|
};
|
|
}
|
|
|
|
export interface WhmcsCatalogProductNormalized {
|
|
id: string;
|
|
groupId: number;
|
|
name: string;
|
|
description: string;
|
|
module: string;
|
|
payType: string;
|
|
pricing: Record<string, WhmcsCatalogPricing>;
|
|
}
|
|
|
|
const cycles = [
|
|
"monthly",
|
|
"quarterly",
|
|
"semiannually",
|
|
"annually",
|
|
"biennially",
|
|
"triennially",
|
|
] as const;
|
|
|
|
const setupFeeKeys = [
|
|
"msetupfee",
|
|
"qsetupfee",
|
|
"ssetupfee",
|
|
"asetupfee",
|
|
"bsetupfee",
|
|
"tsetupfee",
|
|
] as const;
|
|
|
|
const normalizePrice = (value: string | undefined): number | undefined =>
|
|
value === undefined ? undefined : parseAmount(value);
|
|
|
|
export function parseWhmcsCatalogProductListResponse(
|
|
raw: unknown
|
|
): WhmcsCatalogProductListResponse {
|
|
return whmcsCatalogProductListResponseSchema.parse(raw);
|
|
}
|
|
|
|
export function transformWhmcsCatalogProductsResponse(
|
|
raw: unknown
|
|
): WhmcsCatalogProductNormalized[] {
|
|
const parsed = parseWhmcsCatalogProductListResponse(raw);
|
|
const products = parsed.products.product;
|
|
|
|
return products.map(product => {
|
|
const pricingEntries = Object.entries(product.pricing ?? {});
|
|
const pricing = pricingEntries.reduce<Record<string, WhmcsCatalogPricing>>(
|
|
(acc, [currency, cyclePricing]) => {
|
|
const normalizedCycles: Partial<WhmcsCatalogPricing> = {
|
|
currency,
|
|
prefix: cyclePricing.prefix,
|
|
suffix: cyclePricing.suffix,
|
|
};
|
|
|
|
for (const cycle of cycles) {
|
|
const value = cyclePricing[cycle];
|
|
if (value !== undefined) {
|
|
normalizedCycles[cycle] = normalizePrice(value);
|
|
}
|
|
}
|
|
|
|
const setupFees: WhmcsCatalogPricing["setupFees"] = {};
|
|
for (const [index, feeKey] of setupFeeKeys.entries()) {
|
|
const value = cyclePricing[feeKey];
|
|
const cycleKey = cycles[index];
|
|
if (value !== undefined && cycleKey !== undefined) {
|
|
setupFees[cycleKey] = normalizePrice(value);
|
|
}
|
|
}
|
|
|
|
acc[currency] = {
|
|
currency,
|
|
prefix: cyclePricing.prefix,
|
|
suffix: cyclePricing.suffix,
|
|
monthly: normalizedCycles.monthly,
|
|
quarterly: normalizedCycles.quarterly,
|
|
semiannually: normalizedCycles.semiannually,
|
|
annually: normalizedCycles.annually,
|
|
biennially: normalizedCycles.biennially,
|
|
triennially: normalizedCycles.triennially,
|
|
setupFees,
|
|
};
|
|
|
|
return acc;
|
|
},
|
|
{}
|
|
);
|
|
|
|
return {
|
|
id: String(product.pid),
|
|
groupId: Number(product.gid),
|
|
name: product.name,
|
|
description: product.description,
|
|
module: product.module,
|
|
payType: product.paytype,
|
|
pricing,
|
|
} satisfies WhmcsCatalogProductNormalized;
|
|
});
|
|
}
|