|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## What is Proxyverse? |
| 6 | + |
| 7 | +A Manifest V3 browser extension (Chrome, Edge, Firefox) for proxy profile management with auto-switch rules and PAC script support. It is an alternative to Proxy SwitchyOmega. |
| 8 | + |
| 9 | +## Build and Test Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +npm run build # Type-check (vue-tsc) + build for Chrome/Edge |
| 13 | +npm run build:firefox # Type-check + build for Firefox (transforms manifest) |
| 14 | +npm run build:test # Build in test mode (no Sentry, no visualizer) |
| 15 | +npm run dev # Vite dev server |
| 16 | +npm test # Run vitest in watch mode |
| 17 | +npm run coverage # Single run with coverage report |
| 18 | +npx vitest run tests/services/proxy/profile2config.test.ts # Run a single test file |
| 19 | +``` |
| 20 | + |
| 21 | +CI runs `npm run coverage` on PRs to main/develop; `npm run build` + `npm run build:firefox` on pushes and tags. |
| 22 | + |
| 23 | +## Architecture |
| 24 | + |
| 25 | +### Three build entry points |
| 26 | + |
| 27 | +The Vite config defines three entry points that produce the extension bundle: |
| 28 | +- **`index.html`** / **`popup.html`** -- Both load `src/main.ts` (Vue app). The Vue router uses hash history: `#/popup` renders `PopupPage`, `#/` renders `ConfigPage` with nested profile/preference routes. |
| 29 | +- **`src/background.ts`** -- Service worker. Wires up proxy auth, request stats, and badge indicator. No Vue, no DOM. |
| 30 | + |
| 31 | +### Browser adapter layer (`src/adapters/`) |
| 32 | + |
| 33 | +`BaseAdapter` defines the abstract contract for all browser APIs (storage, proxy, webRequest, tabs, i18n). Concrete implementations: `Chrome`, `Firefox`, `WebBrowser` (dev stub). A singleton `Host` is auto-detected at import time and used everywhere. This is the only layer that touches `chrome.*` or `browser.*` APIs directly. |
| 34 | + |
| 35 | +### Proxy engine (`src/services/proxy/`) |
| 36 | + |
| 37 | +The core complexity lives here: |
| 38 | +- **`profile2config.ts`** -- `ProfileConverter` turns a `ProxyProfile` into a `ProxyConfig` (for `chrome.proxy.settings`). For non-PAC profiles and auto-switch profiles, it **generates PAC scripts via AST** using `escodegen`/`acorn` node builders in `scriptHelper.ts`. Auto-switch profiles compose multiple sub-profiles by generating `register()` calls that build a lookup table. |
| 39 | +- **`pacSimulator.ts`** -- JS reimplementations of PAC functions (`shExpMatch`, `isInNet`) used to simulate PAC evaluation in-extension (e.g., for tab badge resolution). `isInNet` returns `UNKNOWN` when given a hostname instead of an IP (can't do DNS in extension context). |
| 40 | +- **`auth.ts`** -- Resolves proxy auth credentials by walking the profile tree (auto-switch profiles delegate to sub-profiles). |
| 41 | + |
| 42 | +### Profile system (`src/services/profile.ts`) |
| 43 | + |
| 44 | +Profiles are stored in `chrome.storage.local` under key `"profiles"`. Types: `ProfileSimple` (proxy/pac), `ProfilePreset` (system/direct), `ProfileAutoSwitch` (rule-based routing). System profiles `DIRECT` and `SYSTEM` have fixed IDs `"direct"` and `"system"`. |
| 45 | + |
| 46 | +### Config import/export (`src/services/config/schema/`) |
| 47 | + |
| 48 | +Schema definitions for importing/exporting profile configurations using `io-ts` for runtime type validation. |
| 49 | + |
| 50 | +## Critical Gotcha: `deepClone()` must use JSON round-trip |
| 51 | + |
| 52 | +`deepClone()` in `src/services/utils.ts` uses `JSON.parse(JSON.stringify(obj))`. **Do not replace with `structuredClone()`** -- Vue's reactive Proxy objects throw `DataCloneError` under `structuredClone()`. The JSON round-trip serializes through Vue's Proxy traps and produces plain objects safe for `chrome.storage`. |
| 53 | + |
| 54 | +## Firefox build differences |
| 55 | + |
| 56 | +The `vite.config.ts` `TRANSFORMER_CONFIG` rewrites `manifest.json` at build time for Firefox: |
| 57 | +- Replaces `background.service_worker` with `background.scripts` array |
| 58 | +- Removes `version_name` |
| 59 | +- Adds `browser_specific_settings.gecko` |
| 60 | + |
| 61 | +## Path alias |
| 62 | + |
| 63 | +`@/` maps to `src/` (configured in both `vite.config.ts` and `tsconfig.json`). |
| 64 | + |
| 65 | +## i18n |
| 66 | + |
| 67 | +Translation strings live in `public/_locales/{locale}/messages.json`. Translations are managed via Transifex. |
0 commit comments