initial for v1
This commit is contained in:
committed by
Carl-Gerhard Lindesvärd
parent
c770634e73
commit
15e997129a
85
packages/sdks/sdk/src/api.ts
Normal file
85
packages/sdks/sdk/src/api.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
interface ApiConfig {
|
||||
baseUrl: string;
|
||||
defaultHeaders?: Record<string, string | Promise<string | null>>;
|
||||
maxRetries?: number;
|
||||
initialRetryDelay?: number;
|
||||
}
|
||||
|
||||
interface FetchOptions extends RequestInit {
|
||||
retries?: number;
|
||||
}
|
||||
|
||||
export class Api {
|
||||
private baseUrl: string;
|
||||
private headers: Record<string, string | Promise<string | null>>;
|
||||
private maxRetries: number;
|
||||
private initialRetryDelay: number;
|
||||
|
||||
constructor(config: ApiConfig) {
|
||||
this.baseUrl = config.baseUrl;
|
||||
this.headers = {
|
||||
'Content-Type': 'application/json',
|
||||
...config.defaultHeaders,
|
||||
};
|
||||
this.maxRetries = config.maxRetries ?? 3;
|
||||
this.initialRetryDelay = config.initialRetryDelay ?? 500;
|
||||
}
|
||||
|
||||
private async resolveHeaders(): Promise<Record<string, string>> {
|
||||
const resolvedHeaders: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(this.headers)) {
|
||||
const resolvedValue = await value;
|
||||
if (resolvedValue !== null) {
|
||||
resolvedHeaders[key] = resolvedValue;
|
||||
}
|
||||
}
|
||||
return resolvedHeaders;
|
||||
}
|
||||
|
||||
public addHeader(key: string, value: string | Promise<string | null>) {
|
||||
this.headers[key] = value;
|
||||
}
|
||||
|
||||
private async post<ReqBody, ResBody>(
|
||||
url: string,
|
||||
data: ReqBody,
|
||||
options: FetchOptions,
|
||||
attempt: number
|
||||
): Promise<ResBody | null> {
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: await this.resolveHeaders(),
|
||||
body: JSON.stringify(data ?? {}),
|
||||
keepalive: true,
|
||||
...options,
|
||||
});
|
||||
|
||||
if (response.status === 401) return null;
|
||||
|
||||
if (response.status !== 200 && response.status !== 202) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const responseText = await response.text();
|
||||
return responseText ? JSON.parse(responseText) : null;
|
||||
} catch (error) {
|
||||
if (attempt < this.maxRetries) {
|
||||
const delay = this.initialRetryDelay * Math.pow(2, attempt);
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
return this.post<ReqBody, ResBody>(url, data, options, attempt + 1);
|
||||
}
|
||||
console.error('Max retries reached:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async fetch<ReqBody, ResBody>(
|
||||
path: string,
|
||||
data: ReqBody,
|
||||
options: FetchOptions = {}
|
||||
): Promise<ResBody | null> {
|
||||
const url = `${this.baseUrl}${path}`;
|
||||
return this.post<ReqBody, ResBody>(url, data, options, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user