migrate to monorepo?
This commit is contained in:
8
packages/core/src/utils/delay.ts
Normal file
8
packages/core/src/utils/delay.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Delay execution for a specified number of milliseconds
|
||||
* @param ms - Milliseconds to delay
|
||||
* @returns A promise that resolves after the specified delay
|
||||
*/
|
||||
export function delay(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
21
packages/core/src/utils/format.ts
Normal file
21
packages/core/src/utils/format.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Format cents to a human-readable currency string
|
||||
* @param cents - Amount in cents (integer)
|
||||
* @param locale - Locale string for formatting (e.g., 'en-CA', 'en-US')
|
||||
* @returns Formatted currency string
|
||||
*/
|
||||
export function formatCentsToCurrency(cents: number, locale: string = "en-CA"): string {
|
||||
try {
|
||||
const formatter = new Intl.NumberFormat(locale, {
|
||||
style: "currency",
|
||||
currency: "CAD",
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
});
|
||||
return formatter.format(cents / 100);
|
||||
} catch (error) {
|
||||
// Fallback if locale is not supported
|
||||
const dollars = (cents / 100).toFixed(2);
|
||||
return `$${dollars}`;
|
||||
}
|
||||
}
|
||||
87
packages/core/src/utils/http.ts
Normal file
87
packages/core/src/utils/http.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
/** Custom error class for HTTP-related failures */
|
||||
export class HttpError extends Error {
|
||||
constructor(
|
||||
public statusCode: number,
|
||||
message: string
|
||||
) {
|
||||
super(message);
|
||||
this.name = "HttpError";
|
||||
}
|
||||
}
|
||||
|
||||
/** Type guard to check if a value is a record (object) */
|
||||
export function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch HTML content from a URL with automatic retries
|
||||
* @param url - The URL to fetch
|
||||
* @param delayMs - Delay in milliseconds between retries
|
||||
* @param opts - Optional fetch options
|
||||
* @returns The HTML content as a string
|
||||
* @throws HttpError if all retries are exhausted
|
||||
*/
|
||||
export async function fetchHtml(
|
||||
url: string,
|
||||
delayMs: number,
|
||||
opts?: RequestInit
|
||||
): Promise<string> {
|
||||
const maxAttempts = 3;
|
||||
let lastError: Error | null = null;
|
||||
|
||||
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||
try {
|
||||
const response = await fetch(url, opts);
|
||||
|
||||
// Check for rate limiting
|
||||
if (response.status === 429) {
|
||||
const retryAfter = response.headers.get("Retry-After");
|
||||
const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : delayMs * (attempt + 1);
|
||||
console.warn(
|
||||
`Rate limited. Retrying after ${waitTime}ms...`
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for server errors
|
||||
if (response.status >= 500) {
|
||||
lastError = new HttpError(
|
||||
response.status,
|
||||
`Server error: ${response.status}`
|
||||
);
|
||||
if (attempt < maxAttempts - 1) {
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, delayMs * (attempt + 1))
|
||||
);
|
||||
continue;
|
||||
}
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
// Check for successful response
|
||||
if (!response.ok) {
|
||||
throw new HttpError(
|
||||
response.status,
|
||||
`HTTP ${response.status}: ${response.statusText}`
|
||||
);
|
||||
}
|
||||
|
||||
return await response.text();
|
||||
} catch (error) {
|
||||
lastError =
|
||||
error instanceof Error
|
||||
? error
|
||||
: new Error("Unknown error during fetch");
|
||||
|
||||
if (attempt < maxAttempts - 1) {
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, delayMs * (attempt + 1))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError || new HttpError(0, "Failed to fetch after retries");
|
||||
}
|
||||
Reference in New Issue
Block a user