···11+# AGENTS.md
22+33+_Last updated: 2025-11-15_
44+55+## Purpose
66+77+- Replaces `CLAUDE.md` as the single source of truth for coding agents.
88+- Summarizes the guardrails that actually keep this MV3 extension healthy, plus the current review backlog.
99+1010+## Core Guardrails
1111+1212+- Never suppress lint/type errors (`eslint-disable`, `@ts-ignore`, etc. are banned). Fix root causes instead.
1313+- Keep changes scoped and well-explained; when work is non-trivial create a short plan (see Planning below) before editing code.
1414+- Communicate clearly and directly—no fluff, no praise.
1515+- Do not remove functionality or tests to “make things pass”. Prefer incremental, reversible changes.
1616+1717+## Required Validation Commands
1818+1919+Run **all** of these before handing work off:
2020+2121+1. `bun run format`
2222+2. `bun run lint`
2323+3. `bun run typecheck`
2424+4. `bun run test`
2525+5. `bun run build:dev`
2626+6. `npx --yes web-ext lint -s dist --output json` (run after the build step; Firefox store rejects bundles that fail this)
2727+2828+## Planning & Documentation
2929+3030+- For anything larger than a quick fix, sketch a numbered plan (multi-step, no single-item plans) and put it in `planning/` as `YYYY-MM-DD-feature.md`. Update progress there as you work.
3131+- Keep commit-sized work units; document tricky decisions inline with short comments when the code isn’t self-explanatory.
3232+3333+## Architecture Cheatsheet _(2025-11-15)_
3434+3535+- `src/shared/logging.ts` → tiny helper that no-ops in production; replaces the old `Debug` class.
3636+- `src/shared/parser.ts` ➜ parses raw input/URLs and now owns the service-specific parsing helpers (no cross-module hop).
3737+- `src/shared/canonicalizer.ts` ➜ normalizes fragments into `TransformInfo`.
3838+- `src/shared/resolver.ts` + `src/shared/cache.ts` ➜ handle↔DID resolution with a debounced `DidHandleCache` and inlined retry logic.
3939+- `src/shared/services.ts` ➜ service registry + destination builders; parsing helpers moved out.
4040+- `src/shared/options.ts` ➜ minimal options API (`showEmojis`, `strictMode`, `showCacheDebug`) with listener helpers.
4141+- `src/background/service-worker.ts` ➜ message router plus a lightweight `tabs.onUpdated` listener that precaches DID/handle pairs for any URL `parseInput` understands (all supported services).
4242+- `src/popup/*` ➜ DOM-only rendering (no `innerHTML`), Firefox theme via CSS variables, inline cache debug panel.
4343+- `src/options/*` ➜ simple UI with three toggles; errors revert to the last known good state.
4444+- Builds via Vite + `@crxjs/vite-plugin`; remember to run all validation commands listed above.
4545+4646+## Release / QA Backlog (from 2025-11-15 review)
4747+4848+Update this checklist as items ship; keep it honest.
4949+5050+- [x] **Popup DOM sanitization** (`src/popup/popup.ts:176-193`): Rendering flow writes unsanitized strings into `innerHTML`, which `web-ext lint` flags as `UNSAFE_VAR_ASSIGNMENT`. _Fixed 2025-11-15 by replacing all popup list/status rendering with DOM node creation._
5151+- [x] **Firefox policy metadata** (`public/manifest.json`): Add `browser_specific_settings.gecko.data_collection_permissions` so AMO accepts new uploads. _Fixed 2025-11-15 by declaring `"required": ["none"]`._
5252+- [x] **Options revert bug** (`src/options/options.ts:13-35`): Error handling always reverts to the _initial_ checkbox state, not the last successful save, because the captured `options` object never updates. _Fixed 2025-11-15 by tracking the last persisted values and reverting to those on failures._
5353+- [ ] **Tooling determinism** (`package.json`): Almost every devDependency is pinned to `"latest"`, which makes CI/CD non-reproducible and has already caused surprise build breaks.
5454+- [x] **Cache write amplification** (`src/shared/cache.ts:138-205`): Every cache hit triggers a full `chrome.storage.local.set`, risking quota overruns (120 writes/min) and throttled service-worker lifetimes. _Fixed 2025-11-15 by debouncing read-hit persistence while keeping writes synchronous._
5555+5656+_When you clear an item, document the fix (date + PR/commit) here before removing it so future agents see the history._
5757+5858+## Current Simplification State (2025-11-15)
5959+6060+- Debug infrastructure removed; the new `debugLog/logError` helpers are the only logging hooks.
6161+- Popup relies on static CSS + browser theme variables; all DOM updates are sanitized via `createElement`.
6262+- Service worker precaches DID/handle pairs again by parsing every completed tab URL and only acting when `parseInput` recognizes a supported service.
6363+- `retry.ts`, legacy options helpers, and `wormholeDebug` hooks are gone; parser owns service-specific parsing logic.
6464+- Options include a third “Show cache debug info” toggle; popup shows cache hit/miss status when enabled.
6565+- Remaining backlog: pin dependencies for deterministic builds.
-361
CLAUDE.md
···11-# CLAUDE.md
22-33-This file provides **MANDATORY** guidance to Claude Code when working with code in this repository.
44-55-## 🚨 CRITICAL ANTI-CHEAT RULES 🚨
66-77-**READ THIS FIRST - THESE ARE ABSOLUTE RULES:**
88-99-1. **ESLint/TypeScript errors MUST be fixed properly** - NEVER disabled
1010-2. **Using `// eslint-disable`, `// @ts-ignore`, `// @ts-expect-error` = IMMEDIATE FAILURE**
1111-3. **If you're tempted to disable a rule, STOP and fix the actual problem**
1212-4. **No exceptions. No excuses. No shortcuts.**
1313-1414-## MANDATORY PRE-FLIGHT ACKNOWLEDGMENT
1515-1616-Before ANY code work, you MUST type this acknowledgment:
1717-1818-```
1919-I acknowledge that I will:
2020-- Fix all linting errors properly without disabling rules
2121-- Run all validation commands after every change
2222-- Not take shortcuts or cheat the system
2323-```
2424-2525-## MANDATORY WORKFLOW CHECKLIST
2626-2727-**STOP AND READ**: You MUST complete this checklist for EVERY code change:
2828-2929-1. [ ] **START**: Print "Answered by: <model name>" before any work
3030-2. [ ] **ACKNOWLEDGE**: Type the pre-flight acknowledgment above
3131-3. [ ] **RE-READ**: Re-read this entire CLAUDE.md file
3232-4. [ ] **PLAN**: Explain what you will change and why BEFORE making changes
3333-5. [ ] **ASK BEFORE CODING**: Ask for explicit permission before you start coding
3434-6. [ ] **CODE**: Make minimal, focused changes only
3535-7. [ ] **VALIDATE**: Run ALL validation commands (see below)
3636-8. [ ] **VERIFY**: Confirm all tests pass before proceeding
3737-9. [ ] **DOCUMENT**: Update this file after completing each step with status
3838-10. [ ] **COMMIT**: Make git commits as needed (never push)
3939-4040-## WHEN YOU ENCOUNTER LINTING/TYPE ERRORS
4141-4242-**CORRECT APPROACH:**
4343-4444-- Understand WHY the error exists
4545-- Fix the root cause of the error
4646-- Research the proper solution if needed
4747-- Ask for help if genuinely stuck
4848-4949-**FORBIDDEN APPROACHES:**
5050-5151-- ❌ Adding `// eslint-disable-*` comments
5252-- ❌ Adding `// @ts-ignore` or `// @ts-expect-error`
5353-- ❌ Modifying `.eslintrc` or `tsconfig.json` to relax rules
5454-- ❌ Removing the code that causes the error
5555-- ❌ Skipping the validation step
5656-5757-## VALIDATION COMMANDS (MANDATORY AFTER EVERY CODE CHANGE)
5858-5959-**You MUST run ALL of these commands after ANY code change:**
6060-6161-```bash
6262-bun run format # Format code
6363-bun run lint # Check for linting errors (MUST PASS)
6464-bun run typecheck # Verify TypeScript types (MUST PASS)
6565-bun run test # Run all tests (add timeout wrapper if needed)
6666-bun run build:dev # Verify build works
6767-```
6868-6969-**FAILURE PROTOCOL**:
7070-7171-- If ANY command fails, you MUST fix the issue properly
7272-- DO NOT proceed until ALL commands pass
7373-- DO NOT disable rules to make them pass
7474-7575-## COMMON CHEAT SCENARIOS AND PROPER SOLUTIONS
7676-7777-### Scenario: "Unused variable" error
7878-7979-❌ WRONG: `// eslint-disable-next-line @typescript-eslint/no-unused-vars`
8080-✅ RIGHT: Remove the unused variable or use it properly
8181-8282-### Scenario: "Type error" on third-party library
8383-8484-❌ WRONG: `// @ts-ignore`
8585-✅ RIGHT: Add proper type definitions or use type assertions correctly
8686-8787-### Scenario: "Any type" warning
8888-8989-❌ WRONG: `// eslint-disable-next-line @typescript-eslint/no-explicit-any`
9090-✅ RIGHT: Define proper types
9191-9292-### Scenario: Complex type issue
9393-9494-❌ WRONG: Give up and disable the check
9595-✅ RIGHT: Ask for help with the specific type issue
9696-9797-## OTHER PROHIBITED ACTIONS
9898-9999-- **NEVER** skip running the validation commands
100100-- **NEVER** remove functionality to "fix" test failures
101101-- **NEVER** add features beyond the problem scope
102102-- **NEVER** refactor working code without explicit request
103103-- **NEVER** include non-code content in code artifacts
104104-- **NEVER** provide sycophantic praise or cheerleading
105105-106106-## CODE GENERATION RULES
107107-108108-### Quality Standards
109109-110110-- Write idiomatic, modern code with minimal dependencies
111111-- Prioritize long-term maintainability over speed
112112-- All code must pass ALL validation checks WITHOUT disabling any rules
113113-- Test coverage for all critical functionality
114114-115115-### When Writing Code
116116-117117-- Use artifacts for all code generation
118118-- Show only relevant snippets when updating (not entire files)
119119-- Explain what changed and why in your response
120120-- Avoid comments for self-documenting code
121121-- Keep explanations outside code artifacts
122122-123123-### Project Structure
124124-125125-- Request project structure before generating code (unless one-off script)
126126-- Stay within problem boundaries
127127-- Don't add unrequested features
128128-129129-## COMMUNICATION STYLE
130130-131131-- Skip ALL flattery and praise
132132-- Challenge assumptions and present counter-evidence
133133-- Disagree openly when appropriate
134134-- Be direct and professional
135135-136136-## Build Commands Reference
137137-138138-- `bun run build:dev` - Build development version of the extension
139139-- `bun run build:chrome` - Build Chrome extension
140140-- `bun run build:firefox` - Build Firefox extension
141141-- `bun run test:watch` - Run tests in watch mode
142142-143143-For Bun API documentation, see: `node_modules/bun-types/docs/**.md`
144144-145145----
146146-147147-**FINAL REMINDER**: Using `eslint-disable` or `@ts-ignore` is NEVER acceptable. Fix the actual problem.
148148-149149-# Problem Solving Approach
150150-151151-For small tasks (linter errors, minor tweaks) proceed directly with implementation when the scope and approach are clear. Ask clarifying questions if needed.
152152-153153-For Substantial Features and Changes:
154154-155155-- Act as a Socratic dialogue partner and rubber duck
156156-- Assume the user may not have complete clarity on their vision
157157-- Act as a product manager / senior designer who cares about the final user experience
158158-- Guide the conversation toward concrete, actionable requirements
159159-- **Before writing any implementation plans or code:**
160160- - Ask clarifying questions about the intended user experience
161161- - Only ask one focused question at a time
162162- - Clarify edge cases and expected behaviors
163163-164164-# Feature Implementation Plan Standards
165165-166166-When creating implementation plans for a single feature:
167167-168168-- Keep the plan scoped to only that feature.
169169-- Make sure you fully understand the feature before proceeding to write the plan.
170170-- Ask the user questions to clarify your understanding. The user often won't have figured out all the details of a feature before they begin to build it. You should act like an expert product manager and help them think through the user experience and technical implementation of each feature.
171171-- New plans should be markdown files stored inside the "planning" folder. Create this folder if it doesn't exist yet.
172172-173173-**IMPORTANT**: These rules apply to code reviews and bugfixes as well.
174174-175175-## Document Structure
176176-177177-- Maintain a task checklist with checkboxes (- [ ] or - [x])
178178-- Include "Current Phase" and "Overall Progress" summaries
179179-- Write in present tense for current work, past tense for completed work
180180-- Include specific file names and locations when mentioning code changes
181181-- Make notes on completed tasks at the bottom with full details
182182-- Use consistent formatting for task IDs (P1.1, P1.2, etc.)
183183-184184-## Phase Completion Workflow
185185-186186-After completing each phase of implementation:
187187-188188-- Ask the user to test the implementation and verify it looks correct
189189-- Update the planning document to mark completed tasks as done
190190-- Move detailed completion notes to the bottom of the document
191191-- Update the "Current Phase" and "Overall Progress" sections
192192-- Update the "Last Updated" timestamp using `npm run date` which will give you today's date
193193-194194-## Task Documentation
195195-196196-Each completed task should include:
197197-198198-- Files modified/created
199199-- Key features implemented
200200-- Technical improvements made
201201-- User experience enhancements
202202-- Any issues resolved
203203-204204----
205205-206206-# at-wormhole-webextension
207207-208208-## Architecture
209209-210210-This is a Manifest V3 browser extension that provides "wormhole" navigation between different AT Protocol/Bluesky services. The extension transforms URLs and identifiers from one service to equivalent URLs on other services.
211211-212212-### Core Components
213213-214214-**Transform System**:
215215-216216-- **Parser** (`src/shared/parser.ts`) - URL parsing with `parseInput()` that accepts URLs, handles, or DIDs
217217-- **Canonicalizer** (`src/shared/canonicalizer.ts`) - Pure transformation to standardized TransformInfo structure
218218-- **Resolver** (`src/shared/resolver.ts`) - Handle/DID resolution with AT Protocol API integration and retry logic
219219-- **Services** (`src/shared/services.ts`) - Service configuration and URL generation
220220-- **Cache** (`src/shared/cache.ts`) - BidirectionalMap and DidHandleCache for handle↔DID persistence
221221-- **Types** (`src/shared/types.ts`) - TypeScript interfaces and type definitions
222222-- **Constants** (`src/shared/constants.ts`) - Shared constants including NSID shortcuts
223223-- **Errors** (`src/shared/errors.ts`) - Discriminated union error types for neverthrow
224224-- **Retry** (`src/shared/retry.ts`) - Network retry logic with exponential backoff
225225-226226-**Service Worker** (`src/background/service-worker.ts`):
227227-228228-- Message handling for popup communication
229229-- Automatic tab URL monitoring with pre-caching
230230-- Proactive background resolution of handles/DIDs
231231-- Returns cache hit/miss metadata for debugging
232232-233233-**Popup** (`src/popup/popup.ts`):
234234-235235-- Main UI displaying destination links
236236-- Service worker communication for resolution
237237-- Cache management controls
238238-- Firefox theme integration via `theme.getCurrent()`
239239-- Development debug controls via `window.wormholeDebug`
240240-241241-### Build System
242242-243243-- **Framework**: Vite with @crxjs/vite-plugin
244244-- **Development**: Injects background.scripts for Firefox MV3 compatibility
245245-- **Firefox Build**: Strips service_worker, adds scripts array, creates zip
246246-- **Chrome Build**: Standard MV3 manifest with zip output
247247-248248-### Supported Services
249249-250250-The extension recognizes and transforms URLs from:
251251-252252-- **bsky.app**, **deer.social** - Native Bluesky clients
253253-- **cred.blue** - Social credit score service
254254-- **tangled.sh** - AT Protocol-native git hosting
255255-- **blue.mackuba.eu/skythread** - Thread viewer
256256-- **atp.tools**, **pdsls.dev** - Developer tools
257257-- **clearsky.app** - Block checking service
258258-- **plc.directory**, **boat.kelinci.net** - DID:PLC information tools
259259-- **toolify.blue** - Various AT Protocol utilities
260260-- **repoview.edavis.dev** - Repository viewer for AT Protocol
261261-- **astrolabe.at** - AT Protocol navigation tool
262262-263263-### Special Features
264264-265265-**Firefox Theme Integration**:
266266-267267-- Automatically adopts Firefox's active theme colors
268268-- Falls back to `prefers-color-scheme` on Chrome
269269-- Maintains readability across all theme variations
270270-271271-**Debug System** (`src/shared/debug.ts`):
272272-273273-- Categorized logging: 🎨 Theme, 💾 Cache, 📝 Parsing, 🔧 Popup, ⚙️ Service Worker, 🔄 Transform
274274-- Runtime control via `window.wormholeDebug` in popup console
275275-- Persistent settings in `chrome.storage.local`
276276-277277-**Cache System**:
278278-279279-- Bidirectional handle↔DID mapping with automatic cleanup
280280-- Write-through persistence with LRU eviction
281281-- Proactive background resolution for visited URLs
282282-- Visual cache hit/miss indicators in development builds
283283-284284-**Options System**:
285285-286286-- **Show Emojis**: Toggle emoji display (default: true)
287287-- **Strict Mode**: Content-aware service filtering (default: false)
288288-- Cross-device sync via `chrome.storage.sync`
289289-290290-### Error Handling
291291-292292-The extension uses **neverthrow** for comprehensive error handling:
293293-294294-- All network operations return `ResultAsync<T, WormholeError>`
295295-- Discriminated union error types (NetworkError, ParseError, ValidationError, CacheError)
296296-- Explicit error handling enforced by ESLint
297297-- Automatic retry with exponential backoff for network failures
298298-299299-### Testing
300300-301301-- **Framework**: Bun's built-in test runner
302302-- **Coverage**: URL parsing, handle resolution, URL generation, cache operations
303303-- **Mocking**: Simulated AT Protocol API responses
304304-- **Commands**: `bun run test` or `bun run test:watch`
305305-306306-## Implementation Status
307307-308308-### ✅ Completed
309309-310310-1. **Modular Architecture** - Transform system split into focused, single-responsibility modules
311311-2. **neverthrow Integration** - Comprehensive error handling with Result types
312312-3. **Retry Logic** - Network resilience with exponential backoff
313313-4. **Cache System** - Reliable bidirectional persistence with LRU eviction
314314-5. **Firefox Theme Support** - Dynamic theme adoption
315315-6. **Options System** - User preferences with cross-device sync
316316-7. **Debug System** - Categorized logging with runtime controls
317317-318318-### 📋 Remaining Tasks
319319-320320-- **Type Safety** - Replace remaining `any`/`unknown` types
321321-- **Popup Error UI** - User-friendly error messages
322322-- **Test Coverage** - Additional edge case scenarios
323323-324324-## Adding New Services
325325-326326-To add a new AT Protocol service, update `src/shared/services.ts`:
327327-328328-```typescript
329329-SERVICES.NEW_SERVICE = {
330330- emoji: '✨',
331331- name: 'example.com',
332332- contentSupport: 'full', // or 'profiles-and-posts', 'only-posts', 'only-profiles'
333333-334334- // Optional: URL parsing configuration
335335- parsing: {
336336- hostname: 'example.com',
337337- patterns: {
338338- profileIdentifier: /^\/profile\/([^/]+)/,
339339- // Additional pattern options available
340340- },
341341- },
342342-343343- // Required: URL generation
344344- buildUrl: (info) => {
345345- if (!info.handle) return null;
346346- if (info.rkey) {
347347- return `https://example.com/user/${info.handle}/post/${info.rkey}`;
348348- }
349349- return `https://example.com/user/${info.handle}`;
350350- },
351351-352352- // Optional: Input restrictions
353353- requiredFields: {
354354- handle: true,
355355- rkey: true,
356356- plcOnly: true,
357357- },
358358-};
359359-```
360360-361361-No other code changes required!
···33import type { TransformInfo } from './types';
44import type { WormholeError } from './errors';
55import { validationError } from './errors';
66-import { logError } from './debug';
66+import { logError } from './logging';
7788/**
99 * Canonicalizes an input fragment into a standard info object.
-149
src/shared/debug.ts
···11-/**
22- * Centralized debug logging utility for the extension
33- * Controls debug output by category with build-time and runtime flags
44- */
55-66-import type { DebugConfig } from './types';
77-import { isWormholeError, storageError, type StorageError } from './errors';
88-import { ResultAsync } from 'neverthrow';
99-1010-// eslint-disable-next-line @typescript-eslint/no-extraneous-class
1111-export default class Debug {
1212- private static getDefaultConfig(): DebugConfig {
1313- return {
1414- theme: import.meta.env.MODE === 'development' || import.meta.env.VITE_DEBUG_THEME === 'true',
1515- cache: import.meta.env.MODE === 'development' || import.meta.env.VITE_DEBUG_CACHE === 'true',
1616- parsing: import.meta.env.MODE === 'development' || import.meta.env.VITE_DEBUG_PARSING === 'true',
1717- popup: import.meta.env.MODE === 'development' || import.meta.env.VITE_DEBUG_POPUP === 'true',
1818- serviceWorker: import.meta.env.MODE === 'development' || import.meta.env.VITE_DEBUG_SW === 'true',
1919- transform: import.meta.env.MODE === 'development' || import.meta.env.VITE_DEBUG_TRANSFORM === 'true',
2020- };
2121- }
2222-2323- private static config: DebugConfig = this.getDefaultConfig();
2424-2525- /**
2626- * Load runtime debug overrides from chrome.storage
2727- * Call this in popup and service worker initialization
2828- */
2929- static loadRuntimeConfig(): ResultAsync<void, StorageError> {
3030- return ResultAsync.fromPromise(chrome.storage.local.get('debugConfig'), (error) =>
3131- storageError('Failed to load debug config', 'get', error),
3232- ).map((result) => {
3333- if (result.debugConfig && typeof result.debugConfig === 'object') {
3434- // Use stored config completely, with defaults as fallback
3535- this.config = { ...this.getDefaultConfig(), ...(result.debugConfig as Partial<DebugConfig>) };
3636- }
3737- return undefined;
3838- });
3939- }
4040-4141- /**
4242- * Save current debug config to storage for runtime persistence
4343- */
4444- static saveRuntimeConfig(): ResultAsync<void, StorageError> {
4545- return ResultAsync.fromPromise(chrome.storage.local.set({ debugConfig: this.config }), (error) =>
4646- storageError('Failed to save debug config', 'set', error),
4747- ).map(() => undefined);
4848- }
4949-5050- /**
5151- * Enable/disable debug category at runtime
5252- */
5353- static setCategory(category: keyof DebugConfig, enabled: boolean): void {
5454- this.config[category] = enabled;
5555- // Fire and forget - we don't need to wait for the save
5656- void this.saveRuntimeConfig().match(
5757- () => undefined, // Success - no action needed
5858- (error) => console.error('Failed to save debug config:', error),
5959- );
6060- }
6161-6262- /**
6363- * Get current debug configuration
6464- */
6565- static getConfig(): Readonly<DebugConfig> {
6666- return { ...this.config };
6767- }
6868-6969- // Category-specific debug methods
7070- static theme = (...args: unknown[]): void => {
7171- if (this.config.theme) console.log('🎨 [THEME]', ...args);
7272- };
7373-7474- static cache = (...args: unknown[]): void => {
7575- if (this.config.cache) console.log('💾 [CACHE]', ...args);
7676- };
7777-7878- static parsing = (...args: unknown[]): void => {
7979- if (this.config.parsing) console.log('📝 [PARSING]', ...args);
8080- };
8181-8282- static popup = (...args: unknown[]): void => {
8383- if (this.config.popup) console.log('🔧 [POPUP]', ...args);
8484- };
8585-8686- static serviceWorker = (...args: unknown[]): void => {
8787- if (this.config.serviceWorker) console.log('⚙️ [SW]', ...args);
8888- };
8989-9090- static transform = (...args: unknown[]): void => {
9191- if (this.config.transform) console.log('🔄 [TRANSFORM]', ...args);
9292- };
9393-9494- // Utility methods for common debugging patterns
9595- static error = (category: keyof DebugConfig, ...args: unknown[]): void => {
9696- if (this.config[category]) console.error(`❌ [${category.toUpperCase()}]`, ...args);
9797- };
9898-9999- static warn = (category: keyof DebugConfig, ...args: unknown[]): void => {
100100- if (this.config[category]) console.warn(`⚠️ [${category.toUpperCase()}]`, ...args);
101101- };
102102-103103- static time = (category: keyof DebugConfig, label: string): void => {
104104- if (this.config[category]) console.time(`⏱️ [${category.toUpperCase()}] ${label}`);
105105- };
106106-107107- static timeEnd = (category: keyof DebugConfig, label: string): void => {
108108- if (this.config[category]) console.timeEnd(`⏱️ [${category.toUpperCase()}] ${label}`);
109109- };
110110-}
111111-112112-/**
113113- * Debug log utility function that integrates with the Debug class
114114- * Used internally by logError and other functions
115115- */
116116-export const debugLog = (category: string, level: string, ...args: unknown[]): void => {
117117- const categoryKey = category.toLowerCase() as keyof DebugConfig;
118118- if (Debug.getConfig()[categoryKey]) {
119119- console.log(`🔍 [${category}] ${level}:`, ...args);
120120- }
121121-};
122122-123123-/**
124124- * Centralized error logging function that handles both WormholeError and unknown errors
125125- * Provides structured logging for typed errors and fallback for unexpected errors
126126- */
127127-export const logError = (category: string, error: unknown, context?: Record<string, unknown>): void => {
128128- const errorInfo = isWormholeError(error) ? error : { raw: String(error) };
129129-130130- // Format a readable error message
131131- let errorMessage = '';
132132- if (isWormholeError(error)) {
133133- errorMessage = `${error.type}: ${error.message}`;
134134- if ('url' in error && error.url) {
135135- errorMessage += ` (URL: ${error.url})`;
136136- }
137137- if ('status' in error && error.status) {
138138- errorMessage += ` [Status: ${error.status}]`;
139139- }
140140- } else {
141141- errorMessage = String(error);
142142- }
143143-144144- console.error(`❌ [${category}] ${errorMessage}`, context);
145145-146146- if (import.meta.env.DEV) {
147147- debugLog(category, 'ERROR', errorInfo, context);
148148- }
149149-};