# Analisi del Progetto Bookish ## 1. Qualità del Codice ### Punti di Forza - **Architettura modulare**: blueprint Flask separati per convertitore, reader, API - **Servizi isolati**: converter, formatter, SSE manager, database come moduli indipendenti - **Pattern Factory**: `create_app()` con registrazione blueprint e init DB - **Responsabilità chiare**: ogni file ha uno scopo ben definito - **Thread safety**: lock `threading.Lock()` in SSE manager per accesso concorrente - **Frontend vanilla**: nessuna dipendenza framework pesante, codice lineare - **Path robust**: `os.path.basename()`, `secure_filename()`, sanity check su ogni path - **Error handling**: try/except in routes con fallback e messaggi d'errore ### Aree di Miglioramento - **Tipo**: usare mypy con typing anche per i parametri Flask - **Test**: nessuna suite di test (accettabile per single-user) - **Logging**: log minimale, potrebbe essere più strutturato - **Cleanup SSE**: il thread cleanup ogni 60s funziona ma non è elegante - **Race condition DB**: `allow_commit` come flag per SKIP/LOCKED è un workaround. In pratica SQLite gestisce bene le race con WAL mode — testato con debounce 1.5s e non dà problemi ## 2. Sicurezza - ✅ **Path traversal**: `secure_filename()` + `os.path.basename()` + sanity check - ✅ **Estensione validata**: controllo su SUPPORTED_FORMATS/OUTPUT_FORMATS_BY_INPUT - ✅ **MIME check**: al download per prevenire tipo sbagliato - ✅ **Cleanup automatico**: file temporanei eliminati dopo 1h - ✅ **SQLite parametriziato**: query con placeholder `?`, niente interpolazione stringhe - ✅ **Niente eval/exec**: zero codice dinamico pericoloso - ✅ **CSRF**: non rilevante per single-user con API REST semplici - ⚠️ **Secret key hardcoded**: default in `app.py`. Impostare `BOOKISH_SECRET` in produzione - ⚠️ **Upload estensione**: solo check estensione, non MIME reale (sufficiente per single-user) - ⚠️ **No rate limiting**: Upload illimitati (accettabile per uso personale) ## 3. Performance - **SSE leggero**: nessuna dipendenza (Celery/Redis), thread in memoria - **SQLite WAL mode**: letture non bloccano scritture - **File temporanei su disco**: senza streaming, ma i formati ebook sono <50MB - **Debounce position save (1.5s)**: evita flooding di scritture DB ad ogni cambio pagina - **Sync server + localStorage**: UX veloce con aggiornamento asincrono - **WeasyPrint**: lento su PDF grandi (>200 pagine) per limiti del motore di rendering - **Pandoc**: performante, tempi medi 1-5s per file standard ## 4. Manutenibilità - **Codice auto-documentante**: nomi di funzioni e variabili chiari - **Config centralizzata**: `config.py` con tutti i path e formati - **Servizi disaccoppiati**: modificare il converter non impatta reader o API - **Separazione API**: le rotte `/api/` sono in blueprint dedicato - **reader.js separato**: anche se lungo (800+ righe), è l'unico file JS del reader - **CSS strutturato**: sezioni per reader, converter, generiche - **Documentazione completa**: README, architecture, deploy, wiki ## 5. Affidabilità - **Porta libera automatica**: se 5000 occupata, `find_free_port()` scorre fino a trovare una libera - **Cleanup temp**: thread timer ogni 60 minuti elimina file scaduti - **Fallback localStorage**: se server API non risponde, bookmarks e posizioni funzionano comunque (solo in locale) - **Content hash come ID**: stesso file → stesso hash → stessi segnalibri, anche su PC diverso - **Auto-creazione DB**: database creato al primo avvio senza intervento manuale - **Gestione errori conversione**: errori Pandoc catturati e propagati come messaggio utente ## 6. Dipendenze ### Python (produzione) | Pacchetto | Versione | Ruolo | |---|---|---| | Flask | ≥3.0 | Web framework | | Flask-CORS | ≥4.0 | CORS per API | | pypandoc_binary | ≥2.0 | Pandoc binary + binding | | WeasyPrint | ≥62 | PDF da HTML | | python-docx | ≥1.0 | DOCX post-processing | | beautifulsoup4 | ≥4.0 | HTML/tabelle post-processing | | lxml | ≥5.0 | Parser XML per BeautifulSoup | | Werkzeug | ≥3.0 | Secure filename, HTTP utilities | | markdown | ≥3.0 | MD → HTML per anteprime | | pdfminer.six | ≥2022 | Testo base da PDF | ### Frontend (browser) | Libreria | Versione | Ruolo | |---|---|---| | epub.js | 0.3.93 | Render EPUB | | pdf.js | 3.x | Render PDF | | PDF.js | 3.x | Text layer PDF | | jszip | 3.x | ZIP per EPUB | ## 7. Architettura Componenti ``` ┌──────────────────────────────────────────────────┐ │ Flask App │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Convert │ │ Reader │ │ API │ │ │ │ /upload │ │ /reader │ │ /api/* │ │ │ │ /progress│ │ /reader/ │ │ │ │ │ │ /download│ │ │ │ bookmarks│ │ │ └─────┬────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ ┌─────▼─────────────▼─────────────▼──────┐ │ │ │ Services │ │ │ │ ┌──────────┐ ┌──────────┐ │ │ │ │ │converter │ │ database │─▶ SQLite │ │ │ │ │sse_mgr │ └──────────┘ │ │ │ │ │formatter │ │ │ │ │ └──────────┘ │ │ │ └──────────────────────────────────────────┘ │ │ │ │ Filesystem: uploads/ converted/ bookish.db │ └──────────────────────────────────────────────────┘ ``` ## 8. Conclusioni **Bookish è un'applicazione solida per il suo scopo**: self-hosted, single-user, conversione e lettura ebook. ### Cosa funziona bene - Il flusso conversione con SSE progress è semplice ma efficace - Il reader supporta EPUB, PDF e formati testo in un'unica interfaccia - La persistenza segnalibri con content_hash è robusta: funziona anche su PC diversi - Il fallback localStorage assicura che il reader non si rompa se il server API è giù - Slider larghezza e help modal completano l'UX del reader - La documentazione è completa e in italiano ### Cosa sarebbe migliorabile (ma non necessario per single-user) - Suite di test automatici - Pipeline CI/CD - HTTPS nativo (gestito da reverse proxy in produzione) - Gestione code block più sofisticata nel reader testo - Mobile optimization - Logging strutturato (può essere aggiunto con poche righe)