@cardql/core
Version:
CardQL core SDK for payment processing - cross-platform shared logic, auth and data access
95 lines (80 loc) • 2.41 kB
text/typescript
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));
}
}