|
1 | | -# Architecture Documentation |
| 1 | +# Architecture |
2 | 2 |
|
3 | | -Comprehensive architecture documentation for the Libby Downloader Chrome extension. |
4 | | - |
5 | | -## Overview |
6 | | - |
7 | | -Libby Downloader is a Chrome extension that enables downloading audiobooks from Libby (OverDrive's digital library app). The extension is built with TypeScript, uses Vite for building, and follows a modular architecture with clear separation of concerns. |
8 | | - |
9 | | -## Folder Structure |
10 | | - |
11 | | -```text |
12 | | -libby-downloader/ |
13 | | -├── src/ # TypeScript source code |
14 | | -│ ├── background/ # Service worker (background script) |
15 | | -│ │ ├── index.ts # Main service worker entry point |
16 | | -│ │ ├── download-service.ts # Chapter download orchestration |
17 | | -│ │ ├── download-tracker.ts # Download state management |
18 | | -│ │ └── metadata-writer.ts # metadata.json file creation |
19 | | -│ ├── content/ # Content script (runs on Libby pages) |
20 | | -│ │ ├── index.ts # Main content script entry point |
21 | | -│ │ ├── constants.ts # Content-specific constants |
22 | | -│ │ ├── ui-manager.ts # Button state and notifications |
23 | | -│ │ ├── message-handler.ts # Message routing and coordination |
24 | | -│ │ └── validators.ts # Re-exports shared validators |
25 | | -│ ├── iframe/ # Iframe scripts (run in audiobook player) |
26 | | -│ │ ├── extractor.ts # Book data extraction (MAIN world) |
27 | | -│ │ └── ui-injector.ts # Download button injection |
28 | | -│ ├── shared/ # Shared utilities |
29 | | -│ │ ├── constants.ts # DEBUG_MODE flag |
30 | | -│ │ ├── logger.ts # Centralized logging |
31 | | -│ │ ├── validators.ts # Origin/data validation |
32 | | -│ │ └── icon-loader.ts # SVG icon loading |
33 | | -│ ├── types/ # TypeScript type definitions |
34 | | -│ │ ├── extension-book.ts # BookData, Chapter, BookMetadata |
35 | | -│ │ ├── messages.ts # Message types and constants |
36 | | -│ │ ├── errors.ts # Custom error classes |
37 | | -│ │ └── chrome.ts # Chrome API extensions |
38 | | -│ ├── styles/ # CSS stylesheets |
39 | | -│ │ └── content.css # Content script styles |
40 | | -│ ├── assets/ # Static assets |
41 | | -│ │ └── icons/ # SVG icons |
42 | | -│ └── __tests__/ # Test files |
43 | | -│ ├── mocks/ # Test mocks (Chrome APIs) |
44 | | -│ ├── shared/ # Shared utility tests |
45 | | -│ ├── background/ # Background script tests |
46 | | -│ └── types/ # Type tests |
47 | | -├── chrome-extension/ # Built extension (output) |
48 | | -│ ├── manifest.json # Extension configuration |
49 | | -│ ├── background/ # Built background script |
50 | | -│ ├── content/ # Built content script |
51 | | -│ ├── iframe/ # Built iframe scripts |
52 | | -│ └── styles/ # Built CSS |
53 | | -├── scripts/ # Build and validation scripts |
54 | | -└── package.json |
55 | | -``` |
| 3 | +Chrome extension (Manifest V3) that downloads audiobooks from Libby, with an optional CLI for tagging and merging. |
56 | 4 |
|
57 | 5 | ## Component Responsibilities |
58 | 6 |
|
59 | 7 | ### Background Service Worker (`src/background/`) |
60 | 8 |
|
61 | | -The service worker runs in the background and handles the heavy lifting of downloading audiobook chapters. |
62 | | - |
63 | | -**Main Components:** |
64 | | - |
65 | | -- **index.ts**: Main entry point, sets up message listeners, coordinates download operations |
66 | | -- **download-service.ts**: Handles individual chapter downloads using Chrome downloads API, implements rate limiting (500ms delays), waits for download completion |
67 | | -- **download-tracker.ts**: Tracks download state (in-progress, completed chapters, failed chapters) |
68 | | -- **metadata-writer.ts**: Creates and saves metadata.json files alongside MP3s |
| 9 | +Handles chapter downloads in the background. |
69 | 10 |
|
70 | | -**Key Responsibilities:** |
71 | | - |
72 | | -- Listen for START_DOWNLOAD messages from content script |
73 | | -- Download chapters sequentially with rate limiting |
74 | | -- Send progress updates to content script |
75 | | -- Handle download failures gracefully |
76 | | -- Save metadata.json with book information |
| 11 | +- **index.ts**: Entry point, message listeners, coordinates download operations |
| 12 | +- **download-service.ts**: Chapter downloads via Chrome downloads API, rate limiting (500ms delays) |
| 13 | +- **download-tracker.ts**: Tracks download state (in-progress, completed, failed) |
| 14 | +- **metadata-writer.ts**: Creates metadata.json alongside MP3s |
77 | 15 |
|
78 | 16 | ### Content Script (`src/content/`) |
79 | 17 |
|
80 | | -The content script runs on `libbyapp.com/open/loan/*` pages and coordinates the UI and message flow. |
81 | | - |
82 | | -**Main Components:** |
| 18 | +Runs on `libbyapp.com/open/loan/*` pages, coordinates UI and message flow. |
83 | 19 |
|
84 | 20 | - **index.ts**: Initialization, creates UIManager and MessageHandler |
85 | | -- **ui-manager.ts**: Sends progress messages to iframe for UI updates, manages iframe reference |
86 | | -- **message-handler.ts**: Routes messages between iframe, content script, and background, handles button clicks, manages extraction timeout |
| 21 | +- **ui-manager.ts**: Sends progress messages to iframe for UI updates |
| 22 | +- **message-handler.ts**: Routes messages between iframe, content script, and background |
87 | 23 | - **constants.ts**: Button states, timeouts, UI configuration |
88 | | -- **validators.ts**: Re-exports shared validators for backward compatibility |
89 | | - |
90 | | -**Key Responsibilities:** |
91 | | - |
92 | | -- Listen for button clicks from iframe |
93 | | -- Request book extraction from iframe |
94 | | -- Validate extracted book data |
95 | | -- Start download in background script |
96 | | -- Display progress and status to user |
97 | | -- Handle errors with user-friendly messages |
98 | 24 |
|
99 | 25 | ### Iframe Scripts (`src/iframe/`) |
100 | 26 |
|
101 | | -Two separate scripts that run in the audiobook player iframe: |
| 27 | +Two scripts running in the audiobook player iframe: |
102 | 28 |
|
103 | 29 | **extractor.ts** (MAIN world): |
104 | 30 |
|
105 | | -- Runs in page context with access to window.BIF |
| 31 | +- Accesses window.BIF object for book metadata |
106 | 32 | - Hooks JSON.parse to capture crypto parameters |
107 | | -- Extracts book metadata (title, authors, narrators, cover) |
108 | | -- Builds chapter URLs with crypto params |
109 | | -- Sends extracted data to content script via postMessage |
| 33 | +- Builds chapter URLs and sends data to content script via postMessage |
110 | 34 |
|
111 | 35 | **ui-injector.ts** (ISOLATED world): |
112 | 36 |
|
113 | 37 | - Injects download button into Libby's native UI |
114 | | -- Listens for progress messages from content script |
115 | 38 | - Creates and updates progress bar below album artwork |
116 | | -- Shows download progress and completion status |
117 | 39 | - Sends button click events to content script via postMessage |
118 | 40 |
|
119 | 41 | ### Shared Utilities (`src/shared/`) |
120 | 42 |
|
121 | | -Utilities used across multiple components: |
122 | | - |
123 | | -- **logger.ts**: Centralized logging with DEBUG/INFO/WARN/ERROR levels, respects DEBUG_MODE flag, structured logging with context |
124 | | -- **validators.ts**: validateOrigin() - checks Libby domain origins, validateBookData() - validates extracted data structure, sanitizeFilename() - makes filenames filesystem-safe |
125 | | -- **icon-loader.ts**: Loads SVG icons as strings via Vite ?raw imports, type-safe icon names (download, spinner, checkmark, error) |
126 | | -- **constants.ts**: DEBUG_MODE flag (enables UI testing without real downloads) |
| 43 | +- **logger.ts**: Logging with DEBUG/INFO/WARN/ERROR levels, respects DEBUG_MODE |
| 44 | +- **validators.ts**: Origin validation, book data validation, filename sanitization |
| 45 | +- **icon-loader.ts**: SVG icons via Vite ?raw imports |
| 46 | +- **constants.ts**: DEBUG_MODE flag |
127 | 47 |
|
128 | 48 | ### Type Definitions (`src/types/`) |
129 | 49 |
|
130 | | -Comprehensive TypeScript types: |
131 | | - |
132 | | -- **extension-book.ts**: BookData, Chapter, BookMetadata - core data structures |
133 | | -- **messages.ts**: MessageTypes constants, Message payload interfaces, DownloadStatus and Timeouts |
134 | | -- **errors.ts**: Custom error classes (ExtractionError, ValidationError, DownloadError, etc.) |
| 50 | +- **extension-book.ts**: BookData, Chapter, BookMetadata |
| 51 | +- **messages.ts**: MessageTypes constants, Message payload interfaces |
| 52 | +- **errors.ts**: Custom error classes (ExtractionError, ValidationError, DownloadError, IframeError, TimeoutError) extending LibbyDownloaderError base class |
135 | 53 | - **chrome.ts**: Chrome API type extensions |
136 | 54 |
|
137 | 55 | ## Message Flow |
@@ -173,81 +91,9 @@ Comprehensive TypeScript types: |
173 | 91 | └─> Shows "Download complete!" with checkmark when finished |
174 | 92 | ``` |
175 | 93 |
|
176 | | -## Build System |
177 | | - |
178 | | -Built with Vite and custom build script for Chrome extension compatibility: |
179 | | - |
180 | | -**Configuration** (`scripts/build-extension.mjs`): |
181 | | - |
182 | | -- Multiple entry points built separately (background, content, iframe-extractor, iframe-ui) |
183 | | -- IIFE output format (required for content scripts - ES modules not supported) |
184 | | -- All dependencies inlined into self-contained bundles |
185 | | -- Minification with esbuild |
186 | | -- SVG ?raw imports for icons |
187 | | -- CSS extraction via Vite |
188 | | - |
189 | | -**Why IIFE?** Chrome content scripts declared in manifest.json cannot use ES module imports. The custom build script compiles each entry as an IIFE bundle with all dependencies included. |
190 | | - |
191 | | -**Build Commands:** |
192 | | - |
193 | | -- `npm run build:extension` - Production build |
194 | | -- `npm run dev:extension` - Watch mode for development |
195 | | -- `npm run typecheck` - TypeScript validation |
196 | | -- `npm run extension:validate` - Lint and validate extension |
197 | | - |
198 | | -## Debug Mode |
199 | | - |
200 | | -Set `DEBUG_MODE = true` in `src/shared/constants.ts` to: |
201 | | - |
202 | | -- Enable detailed logging (DEBUG level) |
203 | | -- Simulate downloads without making real requests |
204 | | -- Test UI states without hitting Libby servers |
205 | | -- Generate fake book data for testing |
206 | | - |
207 | | -In production, set `DEBUG_MODE = false` for INFO level logging only. |
208 | | - |
209 | | -## Error Handling |
210 | | - |
211 | | -Custom error classes provide context-specific error information: |
212 | | - |
213 | | -- **ExtractionError**: Book extraction failures, includes original cause |
214 | | -- **ValidationError**: Data validation failures, includes invalid data |
215 | | -- **DownloadError**: Chapter download failures, includes chapter index |
216 | | -- **IframeError**: Iframe communication failures, includes origin |
217 | | -- **TimeoutError**: Operation timeouts, includes timeout duration |
218 | | - |
219 | | -All errors extend `LibbyDownloaderError` base class with proper prototype chains. |
220 | | - |
221 | | -## Testing |
222 | | - |
223 | | -Jest-based testing with jsdom environment: |
224 | | - |
225 | | -- **Chrome API mocks**: Mock chrome.downloads, chrome.runtime, chrome.tabs |
226 | | -- **Unit tests**: Validators, logger, error classes, icon loader |
227 | | -- **Integration tests**: Download service, download tracker |
228 | | -- **186 total tests**: All passing, ~8.5s execution time |
229 | | - |
230 | | -Run tests: `npm test` |
231 | | - |
232 | | -## Security Considerations |
| 94 | +## Security |
233 | 95 |
|
234 | 96 | - Origin validation for all postMessage communications |
235 | 97 | - Sanitized filenames to prevent path traversal |
236 | | -- Chrome downloads API permission required |
237 | 98 | - No eval() or unsafe dynamic code execution |
238 | 99 | - Content Security Policy compliant |
239 | | - |
240 | | -## Performance |
241 | | - |
242 | | -- Lazy loading with ES modules |
243 | | -- Code splitting via Vite (shared chunks) |
244 | | -- Minified production builds |
245 | | -- 500ms delay between chapter downloads (rate limiting) |
246 | | -- Async/await for non-blocking operations |
247 | | - |
248 | | -## Browser Compatibility |
249 | | - |
250 | | -- Chrome Manifest V3 (modern Chrome/Edge) |
251 | | -- Service workers (no persistent background pages) |
252 | | -- ES2022 JavaScript features |
253 | | -- Requires Chrome extensions API support |
0 commit comments