forked from superdoc-dev/superdoc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
119 lines (96 loc) · 3.88 KB
/
Copy pathmain.py
File metadata and controls
119 lines (96 loc) · 3.88 KB
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
from __future__ import annotations
import logging
import os
from contextlib import asynccontextmanager
from importlib.metadata import PackageNotFoundError, version
from pathlib import Path
from fastapi import FastAPI, Query
from fastapi.responses import FileResponse, HTMLResponse
from superdoc import AsyncSuperDocClient
EXAMPLE_ROOT = Path(__file__).resolve().parent
# Hardcoded demo config.
DOC_PATH = EXAMPLE_ROOT / "assets" / "doc-template.docx"
MARKDOWN_PATH = EXAMPLE_ROOT / "assets" / "fake-nda.md"
DOWNLOAD_PATH = EXAMPLE_ROOT / ".superdoc-state" / "download.docx"
COLLAB_PROVIDER = "y-websocket"
COLLAB_URL = "ws://127.0.0.1:8081/v1/collaboration"
COLLAB_DOCUMENT_ID = "superdoc-dev-room"
COLLAB_TOKEN_ENV = "YHUB_AUTH_TOKEN"
COLLAB_TOKEN_DEFAULT = "YOUR_PRIVATE_TOKEN"
COLLAB_SYNC_TIMEOUT_MS = 60_000
# Keep open timeout above sync timeout, and watchdog above open timeout.
OPEN_TIMEOUT_MS = 90_000
WATCHDOG_TIMEOUT_MS = 120_000
logger = logging.getLogger("uvicorn.error")
try:
SUPERDOC_SDK_VERSION = version("superdoc-sdk")
except PackageNotFoundError:
SUPERDOC_SDK_VERSION = "not installed"
@asynccontextmanager
async def lifespan(app: FastAPI):
logger.info("superdoc-sdk version: %s", SUPERDOC_SDK_VERSION)
os.environ.setdefault(COLLAB_TOKEN_ENV, COLLAB_TOKEN_DEFAULT)
logger.info("collaboration token env: %s", COLLAB_TOKEN_ENV)
async with AsyncSuperDocClient(watchdog_timeout_ms=WATCHDOG_TIMEOUT_MS) as client:
doc = await client.open(
{
"doc": str(DOC_PATH),
"collaboration": {
"providerType": COLLAB_PROVIDER,
"url": COLLAB_URL,
"documentId": COLLAB_DOCUMENT_ID,
"tokenEnv": COLLAB_TOKEN_ENV,
"syncTimeoutMs": COLLAB_SYNC_TIMEOUT_MS,
},
},
timeout_ms=OPEN_TIMEOUT_MS,
)
markdown_content = MARKDOWN_PATH.read_text(encoding="utf-8")
await doc.insert({"value": markdown_content, "type": "markdown"})
app.state.doc = doc
app.state.open_result = doc.open_result
try:
yield
finally:
await doc.close({})
app = FastAPI(title="SuperDoc FastAPI Collaboration Demo", lifespan=lifespan)
@app.get("/")
def root() -> dict:
return {
"ok": True,
"openResult": app.state.open_result,
"collab": {
"providerType": COLLAB_PROVIDER,
"url": COLLAB_URL,
"documentId": COLLAB_DOCUMENT_ID,
"tokenEnv": COLLAB_TOKEN_ENV,
},
}
@app.get("/status")
async def status() -> dict:
return {"ok": True, "sessionId": app.state.doc.session_id}
@app.get("/insert")
async def insert(text: str = Query(...)) -> dict:
return await app.state.doc.insert({"value": text})
@app.get("/markdown")
async def markdown() -> HTMLResponse:
markdown_result = await app.state.doc.get_markdown()
md = markdown_result
if not isinstance(md, str):
md = str(md)
escaped = md.replace("&", "&").replace("<", "<").replace(">", ">")
html = f"""<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Document Markdown</title>
<style>body{{font-family:system-ui,sans-serif;max-width:48rem;margin:2rem auto;padding:0 1rem}}
pre{{background:#f5f5f5;padding:1rem;border-radius:6px;overflow-x:auto;white-space:pre-wrap;word-wrap:break-word}}</style>
</head><body><h1>Document as Markdown</h1><pre>{escaped}</pre></body></html>"""
return HTMLResponse(content=html)
@app.get("/download")
async def download() -> FileResponse:
DOWNLOAD_PATH.parent.mkdir(parents=True, exist_ok=True)
await app.state.doc.save({"out": str(DOWNLOAD_PATH), "force": True})
return FileResponse(
path=str(DOWNLOAD_PATH),
media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
filename=DOWNLOAD_PATH.name,
)