Files
bookish/docs/analysis.md
T

7.1 KiB

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│  │  <file>  │  │ 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)