barsa f68fb50638 Update TypeScript configurations and improve module imports
- Changed TypeScript target and library settings in tsconfig files to align with ESNext standards.
- Updated pnpm version in GitHub workflows for better dependency management.
- Modified Dockerfile to reflect the updated pnpm version.
- Adjusted import statements across various domain modules to include file extensions for consistency and compatibility.
- Cleaned up TypeScript configuration files for improved clarity and organization.
2025-12-10 15:22:10 +09:00

214 lines
7.1 KiB
TypeScript

/**
* Freebit SIM Provider - Mapper
*/
import type { SimDetails, SimUsage, SimTopUpHistory, SimType, SimStatus } from "../../contract.js";
import { simDetailsSchema, simUsageSchema, simTopUpHistorySchema } from "../../schema.js";
import {
type FreebitAccountDetailsRaw,
type FreebitTrafficInfoRaw,
type FreebitQuotaHistoryRaw,
type FreebitAuthResponseRaw,
type FreebitTopUpRaw,
type FreebitAddSpecRaw,
type FreebitPlanChangeRaw,
type FreebitCancelPlanRaw,
type FreebitCancelAccountRaw,
type FreebitEsimReissueRaw,
type FreebitEsimAddAccountRaw,
freebitAccountDetailsRawSchema,
freebitTrafficInfoRawSchema,
freebitQuotaHistoryRawSchema,
freebitAuthResponseRawSchema,
freebitTopUpRawSchema,
freebitAddSpecRawSchema,
freebitPlanChangeRawSchema,
freebitCancelPlanRawSchema,
freebitCancelAccountRawSchema,
freebitEsimReissueRawSchema,
freebitEsimAddAccountRawSchema,
} from "./raw.types.js";
import { normalizeAccount } from "./utils.js";
function asString(value: unknown): string {
if (typeof value === "string") return value;
if (typeof value === "number") return String(value);
return "";
}
function asNumber(value: unknown): number {
if (typeof value === "number") return value;
if (typeof value === "string") {
const parsed = parseFloat(value);
return isNaN(parsed) ? 0 : parsed;
}
return 0;
}
function parseBooleanFlag(value: unknown): boolean {
if (typeof value === "boolean") return value;
if (typeof value === "number") return value === 10;
if (typeof value === "string") return value === "10" || value.toLowerCase() === "true";
return false;
}
function mapSimStatus(status: string | undefined): SimStatus {
if (!status) return "pending";
const normalized = status.toLowerCase();
if (normalized.includes("active") || normalized === "10") return "active";
if (normalized.includes("suspend")) return "suspended";
if (normalized.includes("cancel") || normalized.includes("terminate")) return "cancelled";
return "pending";
}
function deriveSimType(sizeValue: unknown, eid?: string | number | null): SimType {
const simSizeStr = typeof sizeValue === "number" ? String(sizeValue) : sizeValue;
const raw = typeof simSizeStr === "string" ? simSizeStr.toLowerCase() : undefined;
const eidStr = typeof eid === "number" ? String(eid) : eid;
if (eidStr && eidStr.length > 0) {
return "esim";
}
switch (raw) {
case "nano":
return "nano";
case "micro":
return "micro";
case "esim":
return "esim";
default:
return "standard";
}
}
export function transformFreebitAccountDetails(raw: unknown): SimDetails {
const response = freebitAccountDetailsRawSchema.parse(raw);
const account = response.responseDatas.at(0);
if (!account) {
throw new Error("Freebit account details missing response data");
}
const sanitizedAccount = asString(account.account);
const simSizeValue = account.simSize ?? (account as any).size;
const eidValue = account.eid;
const simType = deriveSimType(
typeof simSizeValue === 'number' ? String(simSizeValue) : simSizeValue,
typeof eidValue === 'number' ? String(eidValue) : eidValue
);
const voiceMailEnabled = parseBooleanFlag(account.voicemail ?? account.voiceMail);
const callWaitingEnabled = parseBooleanFlag(account.callwaiting ?? account.callWaiting);
const internationalRoamingEnabled = parseBooleanFlag(account.worldwing ?? account.worldWing);
const simDetails: SimDetails = {
account: sanitizedAccount,
status: mapSimStatus(account.status),
planCode: asString(account.planCode),
planName: asString(account.planName),
simType,
iccid: asString(account.iccid),
eid: asString(eidValue),
msisdn: asString(account.msisdn),
imsi: asString(account.imsi),
remainingQuotaMb: asNumber(account.quota),
remainingQuotaKb: asNumber(account.quotaKb),
voiceMailEnabled,
callWaitingEnabled,
internationalRoamingEnabled,
networkType: asString(account.contractLine),
activatedAt: asString(account.startDate) || undefined,
expiresAt: asString(account.expireDate) || undefined,
};
return simDetailsSchema.parse(simDetails);
}
export function transformFreebitTrafficInfo(raw: unknown): SimUsage {
const response = freebitTrafficInfoRawSchema.parse(raw);
const simUsage: SimUsage = {
account: asString(response.account),
todayUsageMb: response.traffic?.today ? asNumber(response.traffic.today) / 1024 : 0,
todayUsageKb: response.traffic?.today ? asNumber(response.traffic.today) : 0,
monthlyUsageMb: undefined,
monthlyUsageKb: undefined,
recentDaysUsage: [],
isBlacklisted: parseBooleanFlag(response.traffic?.blackList),
lastUpdated: new Date().toISOString(),
};
return simUsageSchema.parse(simUsage);
}
export function transformFreebitQuotaHistory(
raw: unknown,
accountOverride?: string
): SimTopUpHistory {
const response = freebitQuotaHistoryRawSchema.parse(raw);
const history: SimTopUpHistory = {
account: accountOverride ?? asString(response.account),
totalAdditions: asNumber(response.total),
additionCount: asNumber(response.count),
history: (response.quotaHistory || []).map(detail => ({
quotaKb: asNumber(detail.addQuotaKb),
quotaMb: asNumber(detail.addQuotaKb) / 1024,
addedDate: detail.addDate || "",
expiryDate: detail.expireDate || "",
campaignCode: detail.campaignCode || "",
})),
};
return simTopUpHistorySchema.parse(history);
}
export function transformFreebitTopUpResponse(raw: unknown) {
return freebitTopUpRawSchema.parse(raw);
}
export type FreebitTopUpResponse = ReturnType<typeof transformFreebitTopUpResponse>;
export function transformFreebitAddSpecResponse(raw: unknown) {
return freebitAddSpecRawSchema.parse(raw);
}
export type FreebitAddSpecResponse = ReturnType<typeof transformFreebitAddSpecResponse>;
export function transformFreebitPlanChangeResponse(raw: unknown) {
return freebitPlanChangeRawSchema.parse(raw);
}
export type FreebitPlanChangeResponse = ReturnType<typeof transformFreebitPlanChangeResponse>;
export function transformFreebitCancelPlanResponse(raw: unknown) {
return freebitCancelPlanRawSchema.parse(raw);
}
export type FreebitCancelPlanResponse = ReturnType<typeof transformFreebitCancelPlanResponse>;
export function transformFreebitCancelAccountResponse(raw: unknown) {
return freebitCancelAccountRawSchema.parse(raw);
}
export type FreebitCancelAccountResponse = ReturnType<typeof transformFreebitCancelAccountResponse>;
export function transformFreebitEsimReissueResponse(raw: unknown) {
return freebitEsimReissueRawSchema.parse(raw);
}
export type FreebitEsimReissueResponse = ReturnType<typeof transformFreebitEsimReissueResponse>;
export function transformFreebitEsimAddAccountResponse(raw: unknown) {
return freebitEsimAddAccountRawSchema.parse(raw);
}
export type FreebitEsimAddAccountResponse = ReturnType<typeof transformFreebitEsimAddAccountResponse>;
export function transformFreebitEsimActivationResponse(raw: unknown) {
return freebitEsimAddAccountRawSchema.parse(raw);
}
export function transformFreebitAuthResponse(raw: unknown): FreebitAuthResponseRaw {
return freebitAuthResponseRawSchema.parse(raw);
}