Fix review issues from automated code review

- Rename MAX_RETRIES to MAX_ATTEMPTS (3 total) to fix
  misleading naming
- Skip retry loop on caller-initiated aborts so explicit
  cancellations terminate immediately
- Preserve original script type via data-type attribute
  instead of always forcing text/javascript
- Recreate MutationObserver when consent changes so newly
  added elements use fresh consent data
- Fix package.json exports: point main at ESM bundle and
  add proper exports map with IIFE as separate entry

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-04-16 12:34:15 +04:00
parent 75996d2dd6
commit 7d05d43f85
4 changed files with 26 additions and 7 deletions

View File

@@ -3,9 +3,17 @@
"version": "0.0.0",
"description": "Probo cookie consent banner SDK",
"type": "module",
"main": "dist/cookie-banner.iife.js",
"main": "dist/cookie-banner.mjs",
"module": "dist/cookie-banner.mjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/cookie-banner.mjs",
"default": "./dist/cookie-banner.mjs"
},
"./iife": "./dist/cookie-banner.iife.js"
},
"scripts": {
"build": "node build.mjs && tsc --emitDeclarationOnly",
"check": "tsc --noEmit"

View File

@@ -30,9 +30,14 @@ const ACTIVATABLE_TAGS = new Set([
function activateScript(el: HTMLScriptElement): void {
const replacement = document.createElement("script");
const originalType = el.getAttribute("data-type");
for (const attr of el.attributes) {
if (attr.name === "type" || attr.name === ATTR_CATEGORY) {
if (
attr.name === "type" ||
attr.name === "data-type" ||
attr.name === ATTR_CATEGORY
) {
continue;
}
if (attr.name === ATTR_SRC) {
@@ -42,7 +47,9 @@ function activateScript(el: HTMLScriptElement): void {
replacement.setAttribute(attr.name, attr.value);
}
replacement.setAttribute("type", "text/javascript");
if (originalType) {
replacement.setAttribute("type", originalType);
}
replacement.setAttribute(ATTR_ACTIVATED, "");
if (el.textContent) {

View File

@@ -233,9 +233,10 @@ export class CookieBannerClient {
private activate(consentData: Record<string, boolean>): void {
activateElements(consentData);
if (!this.observer) {
this.observer = observeAndActivate(consentData);
if (this.observer) {
this.observer.disconnect();
}
this.observer = observeAndActivate(consentData);
}
destroy(): void {

View File

@@ -22,7 +22,7 @@ import {
} from "./errors";
const DEFAULT_TIMEOUT_MS = 5_000;
const MAX_RETRIES = 2;
const MAX_ATTEMPTS = 3;
const BASE_DELAY_MS = 500;
export interface RequestOptions {
@@ -129,7 +129,7 @@ export async function fetchJSON<T>(
let lastError: Error | undefined;
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
if (attempt > 0) {
await delay(jitteredBackoff(attempt - 1));
}
@@ -138,6 +138,9 @@ export async function fetchJSON<T>(
try {
response = await fetchWithTimeout(url, init, timeout);
} catch (err) {
if (signal?.aborted) {
throw err;
}
if (err instanceof TimeoutError || err instanceof NetworkError) {
lastError = err;
continue;