barsa 0f6bae840f feat: add eligibility check flow with form, OTP, and success steps
- Implemented FormStep component for user input (name, email, address).
- Created OtpStep component for OTP verification.
- Developed SuccessStep component to display success messages based on account creation.
- Introduced eligibility-check.store for managing state throughout the eligibility check process.
- Added commitlint configuration for standardized commit messages.
- Configured knip for workspace management and project structure.
2026-01-15 11:28:25 +09:00

93 lines
3.2 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,
});
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);
};
/**
* 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> = {};
if (address.address1 !== undefined) update["address1"] = address.address1 ?? "";
if (address.address2 !== undefined) update["address2"] = address.address2 ?? "";
if (address.city !== undefined) update["city"] = address.city ?? "";
if (address.state !== undefined) update["state"] = address.state ?? "";
if (address.postcode !== undefined) update["postcode"] = address.postcode ?? "";
if (address.country !== undefined) update["country"] = address.country ?? "";
if (address.countryCode !== undefined) update["countrycode"] = address.countryCode ?? "";
if (address.phoneNumber !== undefined) update["phonenumber"] = address.phoneNumber ?? "";
if (address.phoneCountryCode !== undefined) update["phonecc"] = address.phoneCountryCode ?? "";
return update;
};