UNPKG

@cardql/core

Version:

CardQL core SDK for payment processing - cross-platform shared logic, auth and data access

95 lines (80 loc) 2.41 kB
import { GraphQLClient } from "graphql-request"; import type { CardQLConfig, CardQLError } from "./types"; export class CardQLClient { private client: GraphQLClient; private config: CardQLConfig; constructor(config: CardQLConfig) { this.config = { timeout: 30000, retries: 3, ...config, }; this.client = new GraphQLClient(this.config.endpoint, { headers: { Authorization: `Bearer ${this.config.apiKey}`, "Content-Type": "application/json", "User-Agent": "CardQL-SDK/1.0.0", }, }); } async request<T = any>(query: string, variables?: any): Promise<T> { try { const result = await this.client.request<T>(query, variables); return result; } catch (error: any) { throw this.normalizeError(error); } } async requestWithRetry<T = any>( query: string, variables?: any, retries = this.config.retries ): Promise<T> { let lastError: Error; for (let attempt = 0; attempt <= retries!; attempt++) { try { return await this.request<T>(query, variables); } catch (error: any) { lastError = error; // Don't retry on client errors (4xx) if (error.response?.status >= 400 && error.response?.status < 500) { throw error; } // Wait before retrying (exponential backoff) if (attempt < retries!) { await this.delay(Math.pow(2, attempt) * 1000); } } } throw lastError!; } setApiKey(apiKey: string): void { this.config.apiKey = apiKey; this.client.setHeader("Authorization", `Bearer ${apiKey}`); } private normalizeError(error: any): CardQLError { if (error.response?.errors?.length > 0) { const gqlError = error.response.errors[0]; return { message: gqlError.message, code: gqlError.extensions?.code, details: gqlError.extensions, }; } if (error.response?.status) { return { message: `HTTP ${error.response.status}: ${error.response.statusText}`, code: "HTTP_ERROR", details: { status: error.response.status }, }; } return { message: error.message || "Unknown error occurred", code: "UNKNOWN_ERROR", details: error, }; } private delay(ms: number): Promise<void> { return new Promise((resolve) => setTimeout(resolve, ms)); } }