Use URL objects for API endpoint construction

Store baseUrl as URL and build endpoints with new URL(path, base).
Accept URL | string in fetchJSON to avoid unnecessary .href calls.

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-04-16 15:46:00 +04:00
parent ce77091e6c
commit f0b5a13f6f
2 changed files with 13 additions and 10 deletions

View File

@@ -64,7 +64,7 @@ export interface CookieBannerClientOptions {
}
export class CookieBannerClient {
private readonly baseUrl: string;
private readonly baseUrl: URL;
private readonly bannerId: string;
private readonly visitorId: string;
@@ -74,16 +74,16 @@ export class CookieBannerClient {
constructor(config: CookieBannerClientOptions) {
let base = config.baseUrl;
while (base.endsWith("/")) {
base = base.slice(0, -1);
if (!base.endsWith("/")) {
base += "/";
}
this.baseUrl = base;
this.baseUrl = new URL(base);
this.bannerId = config.bannerId;
this.visitorId = getOrCreateVisitorId(config.bannerId);
}
async load(): Promise<void> {
const configUrl = `${this.baseUrl}/${this.bannerId}/config`;
const configUrl = new URL(`${this.bannerId}/config`, this.baseUrl);
const config = await fetchJSON<BannerConfig>(configUrl);
this.bannerConfig = config;
@@ -101,7 +101,10 @@ export class CookieBannerClient {
return;
}
const consentUrl = `${this.baseUrl}/${this.bannerId}/consents/${this.visitorId}`;
const consentUrl = new URL(
`${this.bannerId}/consents/${this.visitorId}`,
this.baseUrl,
);
const apiConsent = await fetchJSON<VisitorConsent>(consentUrl).catch(
(err) => {
if (err instanceof NotFoundError) {
@@ -185,7 +188,7 @@ export class CookieBannerClient {
consentData: Record<string, boolean>,
): Promise<ConsentRecord> {
const cfg = this.config;
const url = `${this.baseUrl}/${this.bannerId}/consents`;
const url = new URL(`${this.bannerId}/consents`, this.baseUrl);
const body = {
visitor_id: this.visitorId,
version: cfg.version,
@@ -201,7 +204,7 @@ export class CookieBannerClient {
});
void flush(this.bannerId);
} catch {
enqueue(this.bannerId, url, body);
enqueue(this.bannerId, url.href, body);
}
this.consent = {

View File

@@ -76,7 +76,7 @@ async function parseErrorBody(response: Response): Promise<ApiErrorBody> {
}
async function fetchWithTimeout(
url: string,
url: URL | string,
init: RequestInit,
timeout: number,
): Promise<Response> {
@@ -109,7 +109,7 @@ async function fetchWithTimeout(
}
export async function fetchJSON<T>(
url: string,
url: URL | string,
options: RequestOptions = {},
): Promise<T> {
const { method = "GET", headers, body, timeout = DEFAULT_TIMEOUT_MS, signal } = options;