- Modify the phoneCountryCode assignment in the WHMCS mapper to ensure it is always a string when present. - Change the phonecc type in the WHMCS raw types schema to use numberLike for improved type safety and validation consistency.
105 lines
3.1 KiB
TypeScript
105 lines
3.1 KiB
TypeScript
/**
|
|
* WHMCS Provider - Mapper
|
|
*
|
|
* Maps WHMCS API responses to domain types.
|
|
* Minimal transformation - validates and normalizes only address structure.
|
|
*/
|
|
|
|
import type { WhmcsClient, Address } from "../../schema.js";
|
|
import { whmcsClientSchema, addressSchema } from "../../schema.js";
|
|
import {
|
|
whmcsClientSchema as whmcsRawClientSchema,
|
|
whmcsClientResponseSchema,
|
|
type WhmcsClient as WhmcsRawClient,
|
|
type WhmcsClientResponse,
|
|
} from "./raw.types.js";
|
|
|
|
/**
|
|
* Parse and validate WHMCS client response
|
|
*/
|
|
export const parseWhmcsClientResponse = (raw: unknown): WhmcsClientResponse =>
|
|
whmcsClientResponseSchema.parse(raw);
|
|
|
|
/**
|
|
* Transform WHMCS client response to domain WhmcsClient
|
|
*/
|
|
export function transformWhmcsClientResponse(response: unknown): WhmcsClient {
|
|
const parsed = parseWhmcsClientResponse(response);
|
|
return transformWhmcsClient(parsed.client);
|
|
}
|
|
|
|
/**
|
|
* Transform raw WHMCS client to domain WhmcsClient
|
|
*
|
|
* Keeps raw WHMCS field names, only normalizes:
|
|
* - Address structure to domain Address type
|
|
* - Type coercions (strings to numbers/booleans)
|
|
*/
|
|
export function transformWhmcsClient(raw: WhmcsRawClient): WhmcsClient {
|
|
return whmcsClientSchema.parse({
|
|
...raw,
|
|
// Only normalize address to our domain structure
|
|
address: normalizeAddress(raw),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Normalize WHMCS address fields to domain Address structure
|
|
*/
|
|
function normalizeAddress(client: WhmcsRawClient): Address | undefined {
|
|
const address = addressSchema.parse({
|
|
address1: client.address1 ?? null,
|
|
address2: client.address2 ?? null,
|
|
city: client.city ?? null,
|
|
state: client.fullstate ?? client.state ?? null,
|
|
postcode: client.postcode ?? null,
|
|
country: client.country ?? null,
|
|
countryCode: client.countrycode ?? null,
|
|
phoneNumber: client.phonenumberformatted ?? client.phonenumber ?? null,
|
|
phoneCountryCode: client.phonecc == null ? null : String(client.phonecc),
|
|
});
|
|
|
|
const hasValues = Object.values(address).some(v => v !== undefined && v !== null && v !== "");
|
|
return hasValues ? address : undefined;
|
|
}
|
|
|
|
/**
|
|
* Transform WHMCS client address to domain Address
|
|
*/
|
|
export const transformWhmcsClientAddress = (raw: unknown): Address | undefined => {
|
|
const client = whmcsRawClientSchema.parse(raw);
|
|
return normalizeAddress(client);
|
|
};
|
|
|
|
/**
|
|
* Mapping from domain Address keys to WHMCS API field names
|
|
*/
|
|
const ADDRESS_FIELD_MAP: Record<keyof Address, string> = {
|
|
address1: "address1",
|
|
address2: "address2",
|
|
city: "city",
|
|
state: "state",
|
|
postcode: "postcode",
|
|
country: "country",
|
|
countryCode: "countrycode",
|
|
phoneNumber: "phonenumber",
|
|
phoneCountryCode: "phonecc",
|
|
};
|
|
|
|
/**
|
|
* Prepare address update for WHMCS API
|
|
* Converts domain Address to WHMCS field names
|
|
*/
|
|
export const prepareWhmcsClientAddressUpdate = (
|
|
address: Partial<Address>
|
|
): Record<string, unknown> => {
|
|
const update: Record<string, unknown> = {};
|
|
for (const [domainKey, whmcsKey] of Object.entries(ADDRESS_FIELD_MAP)) {
|
|
const value = address[domainKey as keyof Address];
|
|
if (value !== undefined) {
|
|
update[whmcsKey] = value ?? "";
|
|
}
|
|
}
|
|
return update;
|
|
};
|