fix(docmost-seed): handle Docmost data envelope + add format field
Some checks are pending
CI / Lint bridge (Biome) (push) Waiting to run
CI / Type-check bridge (push) Blocked by required conditions
CI / Tests unit bridge (push) Blocked by required conditions
CI / Tests integration bridge (push) Blocked by required conditions
CI / Security scan (push) Waiting to run
CI / Docker build + healthcheck (push) Blocked by required conditions

Docmost API responses wrap : {data, success, status} (3 keys top-level).
- _post auto-unwrap si payload contient `data` dict|list
- create_page : ajout du field 'format' (markdown|json|html) requis
- welcome_page_content() : retourne markdown plain (Docmost convertit auto en Tiptap)

Iteration 3 BUILD validee en local :
  Workspace : Acadenice (id 019e034d-...)
  3 spaces  : CFA, Agence, Interne
  Page test : Welcome formation-hub dans CFA
  Share URL : http://localhost:3000/share/019e0352-7fc4-7639...

Endpoints reverse-engineered confirmes fonctionnels :
  /api/auth/setup, /api/auth/login, /api/workspace/info,
  /api/spaces/, /api/spaces/create, /api/pages/create, /api/shares/create
This commit is contained in:
Corentin JOGUET 2026-05-07 18:43:39 +02:00
parent 8a676d27c8
commit d5558caf9a

View file

@ -35,12 +35,19 @@ class DocmostSeed:
self.workspace_id: str | None = None
def _post(self, path: str, body: dict[str, Any] | None = None) -> dict[str, Any]:
"""POST + auto-unwrap `data` envelope (Docmost API wrap convention)."""
url = f"{self.base_url}{path}"
r = self.session.post(url, json=body or {})
if r.status_code >= 300:
print(f" [ERROR] POST {path}{r.status_code}\n body={body}\n resp={r.text[:500]}")
r.raise_for_status()
return r.json() if r.text else {}
if not r.text:
return {}
payload = r.json()
# Docmost wraps responses : {data: ..., success: bool, status: int}
if isinstance(payload, dict) and "data" in payload and isinstance(payload["data"], (dict, list)):
return payload["data"]
return payload
def setup_admin_and_workspace(self, name: str, email: str, password: str, workspace_name: str) -> bool:
"""POST /api/auth/setup — bootstrap workspace + admin (1ere fois seulement).
@ -72,7 +79,12 @@ class DocmostSeed:
def list_spaces(self) -> list[dict[str, Any]]:
try:
data = self._post("/api/spaces/", {"page": 1, "limit": 100})
return data.get("items") or data.get("data") or []
# Apres unwrap de data, on a { items: [...], meta: {...} }
if isinstance(data, dict):
return data.get("items") or []
if isinstance(data, list):
return data
return []
except requests.HTTPError:
return []
@ -97,8 +109,8 @@ class DocmostSeed:
print(f" [space] Created '{name}' id={sid}")
return sid
def create_page(self, space_id: str, title: str, content: dict[str, Any] | None = None) -> str:
body: dict[str, Any] = {"spaceId": space_id, "title": title}
def create_page(self, space_id: str, title: str, content: str | dict[str, Any] | None = None, fmt: str = "markdown") -> str:
body: dict[str, Any] = {"spaceId": space_id, "title": title, "format": fmt}
if content is not None:
body["content"] = content
result = self._post("/api/pages/create", body)
@ -118,34 +130,31 @@ class DocmostSeed:
return result
def welcome_page_content() -> dict[str, Any]:
"""Tiptap doc JSON minimal pour la page Welcome."""
return {
"type": "doc",
"content": [
{"type": "heading", "attrs": {"level": 1}, "content": [
{"type": "text", "text": "Welcome formation-hub"}]},
{"type": "paragraph", "content": [
{"type": "text", "text": "Wiki Docmost interne Acadenice — voir docs/ du repo wiki pour la conception complete."}]},
{"type": "heading", "attrs": {"level": 2}, "content": [
{"type": "text", "text": "Stack"}]},
{"type": "bulletList", "content": [
{"type": "listItem", "content": [
{"type": "paragraph", "content": [
{"type": "text", "marks": [{"type": "bold"}], "text": "Docmost"},
{"type": "text", "text": " : ce wiki (AGPL self-host)"}]}]},
{"type": "listItem", "content": [
{"type": "paragraph", "content": [
{"type": "text", "marks": [{"type": "bold"}], "text": "Baserow"},
{"type": "text", "text": " : DBs structurees (MIT self-host)"}]}]},
{"type": "listItem", "content": [
{"type": "paragraph", "content": [
{"type": "text", "marks": [{"type": "bold"}], "text": "Bridge service"},
{"type": "text", "text": " : Phase 2"}]}]}]},
{"type": "paragraph", "content": [
{"type": "text", "text": "Note : ajouter les blocks Mermaid / Drawio / Excalidraw via le slash menu une fois la page ouverte (ils ne sont pas pre-inserees par le seed)."}]},
],
}
def welcome_page_content() -> str:
"""Page Welcome en markdown — Docmost le converti en Tiptap auto."""
return """# Welcome formation-hub
Wiki Docmost interne Acadenice voir `docs/` du repo wiki pour la conception complete.
## Stack
- **Docmost** : ce wiki (AGPL self-host)
- **Baserow** : DBs structurees (MIT self-host) http://localhost:8080
- **Bridge service** : Phase 2
## Diagrammes natifs
Ajouter via le slash menu :
- `/mermaid` pour les diagrammes Mermaid
- `/drawio` pour les diagrammes Draw.io
- `/excalidraw` pour les whiteboards Excalidraw
## Liens utiles
- Repo Forgejo : https://git.acadenice.com/AcadeNice/Wiki
- Stack locale : Docmost (3000) + Baserow (8080)
- Documentation projet : `docs/00-readme.md` du repo
"""
def main() -> int: