File size: 4,721 Bytes
950dcd2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"""DocForge routes β€” generate full documentation for any GitHub repo."""
import json
import os
from flask import (Blueprint, render_template, request, jsonify,
                   current_app, Response)
from .github_fetcher import (parse_repo_url, get_repo_info,
                                      get_file_tree, fetch_key_files)
from .doc_generator import (generate_readme, generate_architecture,
                                     generate_api_docs)
from .db import get_db, upsert_repo, upsert_doc, get_docs, list_recent

bp = Blueprint("doc_forge", __name__, template_folder="templates")


def _db():
    db_path = os.path.join(os.path.dirname(current_app.root_path), "docforge.db")
    return get_db(db_path)


# ── Pages ──────────────────────────────────────────────────────────────────────

@bp.route("/")
def index():
    db     = _db()
    recent = list_recent(db)
    return render_template("doc_forge/index.html", recent=recent)


@bp.route("/docs/<owner>/<repo>")
def docs_view(owner, repo):
    db   = _db()
    data = get_docs(db, owner, repo)
    if not data:
        return render_template("doc_forge/index.html", recent=list_recent(db),
                               error=f"No docs found for {owner}/{repo}. Generate them first.")
    return render_template("doc_forge/docs.html", owner=owner, repo=repo, data=data)


# ── API ────────────────────────────────────────────────────────────────────────

@bp.route("/api/analyze", methods=["POST"])
def analyze():
    """Step 1: fetch repo metadata + file tree. Returns info without generating docs."""
    body = request.get_json(silent=True) or {}
    url  = (body.get("url") or "").strip()
    if not url:
        return jsonify({"error": "repo_url is required"}), 400
    try:
        owner, repo = parse_repo_url(url)
        info        = get_repo_info(owner, repo)
        tree        = get_file_tree(owner, repo, info["default_branch"])
        return jsonify({
            "owner": owner, "repo": repo,
            "info": info, "file_count": len(tree),
            "tree_preview": tree[:20],
        })
    except Exception as exc:
        return jsonify({"error": str(exc)}), 400


@bp.route("/api/generate", methods=["POST"])
def generate():
    """Step 2: generate all docs for a repo."""
    body  = request.get_json(silent=True) or {}
    url   = (body.get("url") or "").strip()
    types = body.get("types", ["readme", "architecture", "api"])
    if not url:
        return jsonify({"error": "url is required"}), 400
    try:
        owner, repo = parse_repo_url(url)
        info        = get_repo_info(owner, repo)
        tree        = get_file_tree(owner, repo, info["default_branch"])
        files       = fetch_key_files(owner, repo, tree, info["default_branch"])
        db          = _db()
        repo_id     = upsert_repo(db, owner, repo, info, tree)
        results     = {}

        if "readme" in types:
            readme = generate_readme(info, tree, files)
            upsert_doc(db, repo_id, "readme", readme)
            results["readme"] = readme

        if "architecture" in types:
            arch = generate_architecture(info, tree, files)
            upsert_doc(db, repo_id, "architecture", arch)
            results["architecture"] = arch

        if "api" in types:
            api_docs = generate_api_docs(info, tree, files)
            upsert_doc(db, repo_id, "api", api_docs)
            results["api"] = api_docs

        return jsonify({"owner": owner, "repo": repo, "info": info, "docs": results})
    except Exception as exc:
        return jsonify({"error": str(exc)}), 500


@bp.route("/api/download/<owner>/<repo>/<doc_type>")
def download(owner, repo, doc_type):
    """Download a generated doc as a file."""
    db   = _db()
    data = get_docs(db, owner, repo)
    if not data or doc_type not in data:
        return jsonify({"error": "not found"}), 404
    content = data[doc_type]
    if doc_type == "readme":
        text     = content.get("readme", "")
        filename = "README.md"
        mime     = "text/markdown"
    else:
        text     = json.dumps(content, indent=2, ensure_ascii=False)
        filename = f"{doc_type}.json"
        mime     = "application/json"
    return Response(text, mimetype=mime,
                    headers={"Content-Disposition": f'attachment; filename="{filename}"'})


@bp.route("/api/recent")
def recent():
    db = _db()
    return jsonify(list_recent(db))