flask-api-development

📁 findinfinitelabs/chuuk 📅 Today
0
总安装量
1
周安装量
安装命令
npx skills add https://github.com/findinfinitelabs/chuuk --skill flask-api-development

Agent 安装分布

amp 1
cline 1
opencode 1
cursor 1
continue 1
kimi-cli 1

Skill 文档

Flask API Development

Overview

The Chuuk Dictionary backend is a single-file monolith: app.py (~4150 lines) that contains all routes, auth logic, translation pipelines, OCR helpers, and database access. There is no Blueprint split.

Application Structure

chuuk/
├── app.py                          # All Flask routes and logic (~4150 lines)
├── src/
│   ├── core/jworg_lookup.py        # JW.org word lookup
│   ├── database/
│   │   ├── db_factory.py           # Connection helpers (module-level functions)
│   │   └── dictionary_db.py        # DictionaryDB class
│   ├── ocr/ocr_processor.py
│   ├── translation/
│   │   ├── helsinki_translator_v2.py
│   │   └── hybrid_translator.py
│   └── utils/nwt_epub_parser.py
├── config/
│   ├── users.json                  # Authorised users
│   └── bible_books.json            # Bible book metadata (66 books)
└── requirements.txt

Key Conventions

Module-level globals (not injected)

# app.py — initialised at startup (not inside routes)
dict_db = DictionaryDB()           # database handle — NOT app.db
training_status = {}               # background job state
training_status_lock = threading.Lock()  # guards training_status mutations

helsinki_translator = None         # loaded lazily via load_helsinki_translator()

CORS is disabled (flask_cors import is commented out). Add it back deliberately if needed.

Magic-link authentication (no passwords)

magic_links = {}        # {token: {'email': email, 'expires': datetime}}
active_sessions = {}    # {email: session_id}  — enforces single active session

@app.route('/api/auth/request-magic-link', methods=['POST'])
def request_magic_link():
    email = request.json.get('email', '').lower().strip()
    # ... validate email against users.json, generate token, send SMTP email ...

@app.route('/auth/magic/<token>')
def magic_link_login(token):
    # ... validate token, create session, redirect to frontend ...

Route return pattern

@app.route('/api/dictionary/search', methods=['GET'])
@login_required
def api_search():
    try:
        query = request.args.get('q', '')
        results = dict_db.search_entries(query)   # use dict_db, not app.db
        return jsonify({'results': results})
    except Exception as e:
        app.logger.error(f'Search error: {e}')
        return jsonify({'error': str(e)}), 500

Background training jobs

Mutate training_status only inside training_status_lock:

with training_status_lock:
    training_status['state'] = 'running'

Bible data

# Loaded from config/bible_books.json — do NOT hardcode inline
BIBLE_BOOKS = _load_bible_books()   # dict keyed by book name

Environment Variables

Variable Purpose Default
FLASK_SECRET_KEY Session signing key random (dev) / required (prod)
FLASK_ENV Environment tag —
COSMOS_DB_CONNECTION_STRING Cosmos DB URI —
SMTP_HOST/PORT/USER/PASSWORD Magic-link email stdout fallback
GOOGLE_VISION_API_KEY Cloud Vision OCR optional

Testing

See tests/conftest.py. Mock dict_db via patch('app.dict_db', mock_db).

Source Files

  • Backend entry point: app.py
  • Database layer: src/database/dictionary_db.py
  • Auth logic: app.py (magic-link sections, ~line 83–170)