Skip to content

Integrate ReoDev#951

Merged
nortonandreev merged 5 commits intomasterfrom
add-reodev
Jan 20, 2026
Merged

Integrate ReoDev#951
nortonandreev merged 5 commits intomasterfrom
add-reodev

Conversation

@nortonandreev
Copy link
Copy Markdown
Contributor

@nortonandreev nortonandreev commented Jan 19, 2026

PR Type

Enhancement


Description

  • Integrate ReoDev analytics library with consent-based initialization

  • Extract consent logic into shared utility module

  • Implement ReoDev cleanup and state management

  • Add TypeScript type declarations for reodotdev package


Diagram Walkthrough

flowchart LR
  A["Client Config"] -->|imports| B["useReoDev Hook"]
  B -->|checks| C["Consent Module"]
  C -->|validates| D["Statistics Consent"]
  D -->|if true| E["Initialize ReoDev"]
  D -->|if false| F["Stop ReoDev"]
  B -->|manages| G["ReoDev Instance"]
  G -->|cleanup| H["Remove Scripts/Cookies"]
  B -->|listens to| I["Cookiebot Events"]
  I -->|triggers| J["Apply Consent State"]
Loading

File Walkthrough

Relevant files
Enhancement
client.ts
Integrate ReoDev initialization in client config                 

docs/.vuepress/client.ts

  • Import and initialize useReoDev hook in client config
  • Remove unused underscore parameter from enhance function
  • Call useReoDev() alongside existing PostHog initialization
+3/-1     
consent.ts
Extract consent checking into shared utility                         

docs/.vuepress/lib/consent.ts

  • Create new consent utility module with Cookiebot type declarations
  • Export hasStatisticsConsent() function for checking statistics cookie
    consent
  • Provide centralized consent checking logic for analytics tools
+24/-0   
usePosthog.ts
Refactor consent logic to shared module                                   

docs/.vuepress/lib/usePosthog.ts

  • Move hasStatisticsConsent() function to separate consent module
  • Import consent function from new consent utility
  • Remove Cookiebot type declarations (moved to consent module)
  • Maintain existing PostHog initialization logic
+1/-21   
useReoDev.ts
Implement ReoDev analytics integration with cleanup           

docs/.vuepress/lib/useReoDev.ts

  • Implement ReoDev initialization with consent-based loading
  • Add comprehensive cleanup function to remove ReoDev scripts, cookies,
    and localStorage
  • Setup Cookiebot event listeners for consent state changes
  • Manage ReoDev instance lifecycle with promise-based initialization
  • Export useReoDev() hook with initialization and consent checking
+111/-0 
reodotdev.d.ts
Add TypeScript type definitions for reodotdev                       

docs/.vuepress/types/reodotdev.d.ts

  • Create TypeScript module declaration for reodotdev package
  • Define ReoClient type with init method and dynamic properties
  • Export loadReoScript() function signature with configuration options
+13/-0   
Dependencies
package.json
Add reodotdev package dependency                                                 

package.json

  • Add reodotdev dependency version ^1.0.0
+1/-0     
pnpm-lock.yaml
Update lock file with reodotdev dependency                             

pnpm-lock.yaml

  • Lock reodotdev package at version 1.0.0
  • Update dependency resolution entries
+8/-0     
Configuration changes
tsconfig.json
Include reodotdev type declarations in TypeScript config 

tsconfig.json

  • Add reodotdev type declaration file to TypeScript compilation
  • Include docs/.vuepress/types/reodotdev.d.ts in files array
+1/-0     

@nortonandreev nortonandreev self-assigned this Jan 19, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Jan 19, 2026

Docs build

1 similar comment
@github-actions
Copy link
Copy Markdown

Docs build

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Jan 19, 2026

Deploying documentation with  Cloudflare Pages  Cloudflare Pages

Latest commit: 87e70cc
Status: ✅  Deploy successful!
Preview URL: https://e0508f57.documentation-21k.pages.dev
Branch Preview URL: https://add-reodev.documentation-21k.pages.dev

View logs

@nortonandreev nortonandreev marked this pull request as ready for review January 20, 2026 09:44
@nortonandreev nortonandreev requested a review from a team as a code owner January 20, 2026 09:44
@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review bot commented Jan 20, 2026

PR Compliance Guide 🔍

(Compliance updated until commit 4b866bd)

Below is a summary of compliance checks for this PR:

Security Compliance
Third-party script load

Description: The PR introduces a new third-party analytics dependency (reodotdev) and dynamically
loads/initializes its remote script via loadReoScript({ clientID: CLIENT_ID }), which can
create supply-chain and script-injection risk if the fetched script source is compromised
or not constrained by CSP/SRI/pinning (review reodotdev’s actual script URL behavior and
consider additional integrity/CSP controls).
useReoDev.ts [1-75]

Referred Code
import { loadReoScript } from "reodotdev";

let listenersRegistered = false;
let isInitialized = false;
let reoInstance: any | null = null;
let reoPromise: Promise<any> | null = null;

declare global {
  interface Window {
    Reo?: unknown;
  }
}

const CLIENT_ID = "f1c2b9fbebbf202";

function hasMarketingConsent(): boolean {
  if (typeof window === "undefined") return false;
  return window.Cookiebot?.consent?.marketing === true;
}

function stopReoDev(): void {


 ... (clipped 54 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Swallowed error context: Multiple catch blocks log generic messages without including the caught error, reducing
actionable context for production debugging and incident analysis.

Referred Code
} catch (_error) {
  console.error("Error clearing LocalStorage");
}

// Best-effort cleanup: expire any cookies whose name contains "reo".
try {
  const cookies = document.cookie.split(";");
  for (let i = 0; i < cookies.length; i++) {
    const cookie = cookies[i];
    const eqPos = cookie.indexOf("=");
    const name = eqPos > -1 ? cookie.slice(0, eqPos).trim() : cookie.trim();
    if (name.toLowerCase().includes("reo")) {
      document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
    }
  }
} catch (_error) {
  console.error("Error resetting Reo cookies expiry");
}

const Reo: any = (window.Reo ?? reoInstance) as any;
try {


 ... (clipped 29 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Unstructured console logs: New logging uses unstructured console.error strings (without structured fields), making
logs harder to parse/monitor and audit.

Referred Code
} catch (_error) {
  console.error("Error clearing LocalStorage");
}

// Best-effort cleanup: expire any cookies whose name contains "reo".
try {
  const cookies = document.cookie.split(";");
  for (let i = 0; i < cookies.length; i++) {
    const cookie = cookies[i];
    const eqPos = cookie.indexOf("=");
    const name = eqPos > -1 ? cookie.slice(0, eqPos).trim() : cookie.trim();
    if (name.toLowerCase().includes("reo")) {
      document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
    }
  }
} catch (_error) {
  console.error("Error resetting Reo cookies expiry");
}

const Reo: any = (window.Reo ?? reoInstance) as any;
try {


 ... (clipped 29 lines)

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

Previous compliance checks

Compliance check up to commit c70934a
Security Compliance
Third-party script loading

Description: The PR dynamically loads and initializes a third-party analytics script via
loadReoScript({ clientID: CLIENT_ID }) without any visible integrity pinning/CSP
guarantees, creating a potential supply-chain/script-injection risk if the dependency or
remote script source is compromised.
useReoDev.ts [61-71]

Referred Code
async function initializeReoDev(): Promise<void> {
  if (typeof window === "undefined") return;
  if (!hasMarketingConsent()) return;
  if (isInitialized || reoInstance || reoPromise) return;


  try {
    reoPromise = loadReoScript({ clientID: CLIENT_ID });
    reoInstance = await reoPromise;
    reoInstance.init({ clientID: CLIENT_ID });
    isInitialized = true;
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Swallowed exceptions: Errors from localStorage and cookie cleanup are silently ignored via empty catch blocks,
which can hide failures and complicate production debugging.

Referred Code
// Clear LocalStorage (if any – guesswork – it's not clear what keys are used by Reo, if any)
try {
  Object.keys(localStorage).forEach((key) => {
    if (key.toLowerCase().includes("reo")) localStorage.removeItem(key);
  });
} catch (_error) {}

// Clear cookies containing 'reo' (if any – guesswork – it's not clear what cookies are used by Reo, if any)
try {
  const cookies = document.cookie.split(";");
  for (let i = 0; i < cookies.length; i++) {
    const cookie = cookies[i];
    const eqPos = cookie.indexOf("=");
    const name = eqPos > -1 ? cookie.slice(0, eqPos).trim() : cookie.trim();
    if (name.toLowerCase().includes("reo")) {
      document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
    }
  }
} catch (_error) {}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Unstructured console logs: New console.error(...) statements emit unstructured logs and may print full error objects,
which can inadvertently include sensitive details from third-party failures.

Referred Code
  } catch (error) {
    console.error("Error stopping Reo: ", error);
  }

  window.Reo = undefined;
}

async function initializeReoDev(): Promise<void> {
  if (typeof window === "undefined") return;
  if (!hasMarketingConsent()) return;
  if (isInitialized || reoInstance || reoPromise) return;


  try {
    reoPromise = loadReoScript({ clientID: CLIENT_ID });
    reoInstance = await reoPromise;
    reoInstance.init({ clientID: CLIENT_ID });
    isInitialized = true;
  } catch (error) {
    console.error("Error loading Reo", error);
    reoInstance = null;


 ... (clipped 1 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
No audit logging: The new consent-driven analytics initialization/stopping behavior does not emit auditable
records (who/when/outcome), so it is unclear if required “critical actions” are being
captured elsewhere.

Referred Code
async function initializeReoDev(): Promise<void> {
  if (typeof window === "undefined") return;
  if (!hasMarketingConsent()) return;
  if (isInitialized || reoInstance || reoPromise) return;


  try {
    reoPromise = loadReoScript({ clientID: CLIENT_ID });
    reoInstance = await reoPromise;
    reoInstance.init({ clientID: CLIENT_ID });
    isInitialized = true;
  } catch (error) {
    console.error("Error loading Reo", error);
    reoInstance = null;
  } finally {
    reoPromise = null;
  }
}

function applyConsentState(): void {
  if (hasMarketingConsent()) void initializeReoDev();


 ... (clipped 2 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Raw error output: The code logs raw error objects to the browser console which may include internal details,
and it is unclear whether this output can be exposed to end-users in the deployed
environment.

Referred Code
} catch (error) {
  console.error("Error stopping Reo: ", error);
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Broad data deletion: The cleanup logic deletes any localStorage keys and cookies whose names include reo, which
may unintentionally remove unrelated data depending on the hosting page’s storage/cookie
namespace.

Referred Code
// Clear LocalStorage (if any – guesswork – it's not clear what keys are used by Reo, if any)
try {
  Object.keys(localStorage).forEach((key) => {
    if (key.toLowerCase().includes("reo")) localStorage.removeItem(key);
  });
} catch (_error) {}

// Clear cookies containing 'reo' (if any – guesswork – it's not clear what cookies are used by Reo, if any)
try {
  const cookies = document.cookie.split(";");
  for (let i = 0; i < cookies.length; i++) {
    const cookie = cookies[i];
    const eqPos = cookie.indexOf("=");
    const name = eqPos > -1 ? cookie.slice(0, eqPos).trim() : cookie.trim();
    if (name.toLowerCase().includes("reo")) {
      document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
    }
  }
} catch (_error) {}

Learn more about managing compliance generic rules or creating your own custom rules

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review bot commented Jan 20, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Rework cleanup logic to be deterministic
Suggestion Impact:The commit reworked stopReoDev away from broad/guessy matching (e.g., keys/cookies containing "reo") to more deterministic removal based on a specific "__sec__" prefix, and removed speculative Reo cookie-deletion method calls. However, it still performs manual LocalStorage/cookie clearing and does not switch to a single official/library-documented "destroy/cleanup" API as suggested.

code diff:

 function stopReoDev(): void {
   if (typeof window === "undefined" || typeof document === "undefined") return;
 
-  isInitialized = false;
-  reoInstance = null;
-  reoPromise = null;
+  try {
+    const reoPrefix = "__sec__"; 
+    Object.keys(localStorage).forEach((key) => {
+      if (key.startsWith(reoPrefix)) {
+        localStorage.removeItem(key);
+      }
+    });
+  } catch (_error) {
+    console.error("Error clearing Reo LocalStorage");
+  }
 
-  // Clear LocalStorage (if any – guesswork – it's not clear what keys are used by Reo, if any)
-  try {
-    Object.keys(localStorage).forEach((key) => {
-      if (key.toLowerCase().includes("reo")) localStorage.removeItem(key);
-    });
-  } catch (_error) {}
-
-  // Clear cookies containing 'reo' (if any – guesswork – it's not clear what cookies are used by Reo, if any)
   try {
     const cookies = document.cookie.split(";");
+    const expiry = "expires=Thu, 01 Jan 1970 00:00:00 GMT";
+    
+    const domainParts = window.location.hostname.split('.');
+    const mainDomain = domainParts.length > 2 ? `.${domainParts.slice(-2).join('.')}` : '';
+
     for (let i = 0; i < cookies.length; i++) {
-      const cookie = cookies[i];
-      const eqPos = cookie.indexOf("=");
-      const name = eqPos > -1 ? cookie.slice(0, eqPos).trim() : cookie.trim();
-      if (name.toLowerCase().includes("reo")) {
-        document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
+      const name = cookies[i].split("=")[0].trim();
+      
+      if (name.startsWith("__sec__")) {
+        document.cookie = `${name}=;${expiry};path=/;`;
+        if (mainDomain) {
+          document.cookie = `${name}=;${expiry};path=/;domain=${mainDomain};`;
+        }
       }
     }
-  } catch (_error) {}
+  } catch (_error) {
+    console.error("Error resetting Reo cookies");
+  }
 
   const Reo: any = (window.Reo ?? reoInstance) as any;
   try {
     Reo?.unload?.();
     Reo?.reset?.();
-    Reo?.deleteCookieReo?.();
-    Reo?.deleteCookie?.();
   } catch (error) {
-    console.error("Error stopping Reo: ", error);
+    console.error("Error stopping Reo instance");
   }
 
+  document.querySelectorAll('script[src*="reo.dev"]').forEach(el => el.remove());
+
+  isInitialized = false;
+  reoInstance = null;
+  reoPromise = null;
   window.Reo = undefined;
 }

The stopReoDev function uses unreliable string matching to clear user data,
which is a privacy risk. It should be replaced with the official, documented
cleanup methods from the ReoDev library for deterministic data removal.

Examples:

docs/.vuepress/lib/useReoDev.ts [21-59]
function stopReoDev(): void {
  if (typeof window === "undefined" || typeof document === "undefined") return;

  isInitialized = false;
  reoInstance = null;
  reoPromise = null;

  // Clear LocalStorage (if any – guesswork – it's not clear what keys are used by Reo, if any)
  try {
    Object.keys(localStorage).forEach((key) => {

 ... (clipped 29 lines)

Solution Walkthrough:

Before:

function stopReoDev(): void {
  // ... state reset ...

  // Guesswork: Clear LocalStorage for keys containing "reo"
  try {
    Object.keys(localStorage).forEach((key) => {
      if (key.toLowerCase().includes("reo")) localStorage.removeItem(key);
    });
  } catch (_error) {}

  // Guesswork: Clear cookies containing "reo"
  try {
    // ... loop through cookies and delete if name includes "reo"
  } catch (_error) {}

  // Speculative calls to potential cleanup methods
  Reo?.unload?.();
  Reo?.reset?.();
}

After:

function stopReoDev(): void {
  // ... state reset ...

  // Use the official, documented cleanup method from the library.
  // This method should handle all data removal internally.
  const Reo: any = (window.Reo ?? reoInstance) as any;
  try {
    // Assuming 'destroy' is the documented method for full cleanup.
    // This is just an example; the actual method should be verified.
    Reo?.destroy?.({ clearUserData: true });
  } catch (error) {
    console.error("Error stopping Reo: ", error);
  }

  window.Reo = undefined;
  reoInstance = null;
}
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical flaw in the data cleanup logic, which relies on guesswork and poses a significant privacy compliance risk, undermining the PR's core goal.

High
Possible issue
Fix race condition in cleanup logic
Suggestion Impact:The commit removed the early resets and instead performs the state resets near the end of stopReoDev (after cleanup actions), aligning with the suggestion’s intent to prevent cleanup from losing access to the instance/state prematurely.

code diff:

-  isInitialized = false;
-  reoInstance = null;
-  reoPromise = null;
-
-  // Clear LocalStorage (if any – guesswork – it's not clear what keys are used by Reo, if any)
+  // Best-effort cleanup: remove any localStorage keys that look Reo-related.
   try {
     Object.keys(localStorage).forEach((key) => {
       if (key.toLowerCase().includes("reo")) localStorage.removeItem(key);
     });
-  } catch (_error) {}
+  } catch (_error) {
+    console.error("Error clearing LocalStorage");
+  }
 
-  // Clear cookies containing 'reo' (if any – guesswork – it's not clear what cookies are used by Reo, if any)
+  // Best-effort cleanup: expire any cookies whose name contains "reo".
   try {
     const cookies = document.cookie.split(";");
     for (let i = 0; i < cookies.length; i++) {
@@ -43,7 +41,9 @@
         document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
       }
     }
-  } catch (_error) {}
+  } catch (_error) {
+    console.error("Error resetting Reo cookies expiry");
+  }
 
   const Reo: any = (window.Reo ?? reoInstance) as any;
   try {
@@ -52,9 +52,14 @@
     Reo?.deleteCookieReo?.();
     Reo?.deleteCookie?.();
   } catch (error) {
-    console.error("Error stopping Reo: ", error);
+    console.error("Error stopping Reo");
   }
 
+  document.querySelectorAll('script[src*="reo.dev"]').forEach(el => el.remove());
+
+  isInitialized = false;
+  reoInstance = null;
+  reoPromise = null;
   window.Reo = undefined;

To fix a race condition in stopReoDev, move the state variable resets
(isInitialized, reoInstance, reoPromise) to the end of the function. This
ensures cleanup logic can access the correct instance before it is nullified.

docs/.vuepress/lib/useReoDev.ts [21-59]

 function stopReoDev(): void {
   if (typeof window === "undefined" || typeof document === "undefined") return;
-
-  isInitialized = false;
-  reoInstance = null;
-  reoPromise = null;
 
   // Clear LocalStorage (if any – guesswork – it's not clear what keys are used by Reo, if any)
   try {
     Object.keys(localStorage).forEach((key) => {
       if (key.toLowerCase().includes("reo")) localStorage.removeItem(key);
     });
   } catch (_error) {}
 
   // Clear cookies containing 'reo' (if any – guesswork – it's not clear what cookies are used by Reo, if any)
   try {
     const cookies = document.cookie.split(";");
     for (let i = 0; i < cookies.length; i++) {
       const cookie = cookies[i];
       const eqPos = cookie.indexOf("=");
       const name = eqPos > -1 ? cookie.slice(0, eqPos).trim() : cookie.trim();
       if (name.toLowerCase().includes("reo")) {
         document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
       }
     }
   } catch (_error) {}
 
   const Reo: any = (window.Reo ?? reoInstance) as any;
   try {
     Reo?.unload?.();
     Reo?.reset?.();
     Reo?.deleteCookieReo?.();
     Reo?.deleteCookie?.();
   } catch (error) {
     console.error("Error stopping Reo: ", error);
   }
 
   window.Reo = undefined;
+  isInitialized = false;
+  reoInstance = null;
+  reoPromise = null;
 }

[Suggestion processed]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a race condition where state variables are nulled before they are used for cleanup, making the stopReoDev function unreliable. Moving the state reset to the end of the function is the correct fix to ensure cleanup operations use the state as it was before stopping.

Medium
Guard against duplicate initialization
Suggestion Impact:The initializeReoDev guard condition was updated to also check for an existing window.Reo (typeof window.Reo !== 'undefined'), matching the suggested robustness improvement to avoid redundant initialization.

code diff:

 async function initializeReoDev(): Promise<void> {
   if (typeof window === "undefined") return;
   if (!hasMarketingConsent()) return;
-  if (isInitialized || reoInstance || reoPromise) return;
-
+  if (isInitialized || reoInstance || reoPromise || typeof window.Reo !== 'undefined') return;
 

In initializeReoDev, update the initial guard condition to also check for the
existence of window.Reo to prevent redundant script loading.

docs/.vuepress/lib/useReoDev.ts [64]

-if (isInitialized || reoInstance || reoPromise) return;
+if (isInitialized || reoInstance || reoPromise || typeof window.Reo !== 'undefined') return;

[Suggestion processed]

Suggestion importance[1-10]: 4

__

Why: This suggestion improves the robustness of the initialization logic by checking for a pre-existing window.Reo object. While the current module's state variables should prevent re-initialization, this additional guard handles edge cases where the script might be loaded by other means, preventing redundant work.

Low
Organization
best practice
Standardize terminology in logs
Suggestion Impact:The commit modified the exact console.error messages referenced by the suggestion, changing their wording/punctuation (removing the trailing colon and dropping the error argument), but it did not implement the suggested format or terminology (“ReoDev:”).

code diff:

@@ -52,7 +56,7 @@
     Reo?.deleteCookieReo?.();
     Reo?.deleteCookie?.();
   } catch (error) {
-    console.error("Error stopping Reo: ", error);
+    console.error("Error stopping Reo");
   }
 
   window.Reo = undefined;
@@ -70,7 +74,7 @@
     reoInstance.init({ clientID: CLIENT_ID });
     isInitialized = true;
   } catch (error) {
-    console.error("Error loading Reo", error);
+    console.error("Error loading Reo");
     reoInstance = null;

Use consistent naming/casing (e.g., “ReoDev”) and consistent punctuation in
error messages to improve clarity when debugging.

docs/.vuepress/lib/useReoDev.ts [55-73]

-console.error("Error stopping Reo: ", error);
+console.error("Error stopping ReoDev:", error);
 ...
-console.error("Error loading Reo", error);
+console.error("Error loading ReoDev:", error);

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Normalize capitalization and terminology consistently across prose/log messages.

Low
Make comments specific and actionable
Suggestion Impact:The comments above the localStorage and cookie cleanup blocks were rewritten from vague/hedged language to explicit "best-effort cleanup" descriptions, matching the intent of the suggestion.

code diff:

-  // Clear LocalStorage (if any – guesswork – it's not clear what keys are used by Reo, if any)
+  // Best-effort cleanup: remove any localStorage keys that look Reo-related.
   try {
     Object.keys(localStorage).forEach((key) => {
       if (key.toLowerCase().includes("reo")) localStorage.removeItem(key);
     });
-  } catch (_error) {}
+  } catch (_error) {
+    console.error("Error clearing LocalStorage");
+  }
 
-  // Clear cookies containing 'reo' (if any – guesswork – it's not clear what cookies are used by Reo, if any)
+  // Best-effort cleanup: expire any cookies whose name contains "reo".
   try {
     const cookies = document.cookie.split(";");
     for (let i = 0; i < cookies.length; i++) {
@@ -43,7 +41,9 @@
         document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
       }
     }
-  } catch (_error) {}
+  } catch (_error) {
+    console.error("Error resetting Reo cookies expiry");
+  }

Replace “guesswork/if any/it’s not clear” with a precise description of the
best-effort cleanup behavior (and optionally why it’s best-effort) so readers
know exactly what the code does.

docs/.vuepress/lib/useReoDev.ts [28-46]

-// Clear LocalStorage (if any – guesswork – it's not clear what keys are used by Reo, if any)
+// Best-effort cleanup: remove any localStorage keys that look Reo-related.
 try {
   Object.keys(localStorage).forEach((key) => {
     if (key.toLowerCase().includes("reo")) localStorage.removeItem(key);
   });
 } catch (_error) {}
 
-// Clear cookies containing 'reo' (if any – guesswork – it's not clear what cookies are used by Reo, if any)
+// Best-effort cleanup: expire any cookies whose name contains "reo".
 try {
   const cookies = document.cookie.split(";");
   for (let i = 0; i < cookies.length; i++) {
     const cookie = cookies[i];
     const eqPos = cookie.indexOf("=");
     const name = eqPos > -1 ? cookie.slice(0, eqPos).trim() : cookie.trim();
     if (name.toLowerCase().includes("reo")) {
       document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
     }
   }
 } catch (_error) {}

[Suggestion processed]

Suggestion importance[1-10]: 5

__

Why:
Relevant best practice - Prefer precise, reader-focused language; avoid vague/hedged phrasing in docs/comments.

Low
General
Remove injected script tag on unload
Suggestion Impact:The commit added logic in stopReoDev to find and remove injected script tags via querySelectorAll(...).forEach(el => el.remove()), implementing the requested cleanup step (with a slightly different src substring match).

code diff:

+  document.querySelectorAll('script[src*="reo.dev"]').forEach(el => el.remove());
+
+  isInitialized = false;
+  reoInstance = null;
+  reoPromise = null;
   window.Reo = undefined;
 }

In the stopReoDev function, add logic to find and remove the injected ReoDev
script tag from the document to ensure a more complete unload.

docs/.vuepress/lib/useReoDev.ts [58]

+document.querySelectorAll('script[src*="reodotdev"]').forEach(el => el.remove());
 window.Reo = undefined;

[Suggestion processed]

Suggestion importance[1-10]: 5

__

Why: The suggestion correctly points out that the stopReoDev function does not remove the script tag added by loadReoScript. Adding this step would make the cleanup process more thorough and is a good practice for resource management.

Low
  • Update

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jan 20, 2026

Docs build

1 similar comment
@github-actions
Copy link
Copy Markdown

Docs build

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jan 20, 2026

Docs build

@nortonandreev
Copy link
Copy Markdown
Contributor Author

PR Code Suggestions ✨
Rework cleanup logic to be deterministic
The stopReoDev function uses unreliable string matching to clear user data, which is a privacy risk. It should be replaced with the official, documented cleanup methods from the ReoDev library for deterministic data removal.

Could not find anything in their documents about the SDK - and the wrapper they have for Node is very lightweight and doesn't provide much functionality, apart from loading the script.

@github-actions
Copy link
Copy Markdown

Docs build

@nortonandreev
Copy link
Copy Markdown
Contributor Author

I have made some changes – seems like we should be checking for analytics, instead of marketing cookies. Also, I found a table of the cookies that are being set – this is now reflected in the PR.

Reference

@nortonandreev
Copy link
Copy Markdown
Contributor Author

/describe

@qodo-code-review
Copy link
Copy Markdown
Contributor

PR Description updated to latest commit (87e70cc)

@nortonandreev nortonandreev merged commit 42d348e into master Jan 20, 2026
3 checks passed
@nortonandreev nortonandreev deleted the add-reodev branch January 20, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants