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
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:
parent
8a676d27c8
commit
d5558caf9a
1 changed files with 41 additions and 32 deletions
|
|
@ -35,12 +35,19 @@ class DocmostSeed:
|
||||||
self.workspace_id: str | None = None
|
self.workspace_id: str | None = None
|
||||||
|
|
||||||
def _post(self, path: str, body: dict[str, Any] | None = None) -> dict[str, Any]:
|
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}"
|
url = f"{self.base_url}{path}"
|
||||||
r = self.session.post(url, json=body or {})
|
r = self.session.post(url, json=body or {})
|
||||||
if r.status_code >= 300:
|
if r.status_code >= 300:
|
||||||
print(f" [ERROR] POST {path} → {r.status_code}\n body={body}\n resp={r.text[:500]}")
|
print(f" [ERROR] POST {path} → {r.status_code}\n body={body}\n resp={r.text[:500]}")
|
||||||
r.raise_for_status()
|
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:
|
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).
|
"""POST /api/auth/setup — bootstrap workspace + admin (1ere fois seulement).
|
||||||
|
|
@ -72,7 +79,12 @@ class DocmostSeed:
|
||||||
def list_spaces(self) -> list[dict[str, Any]]:
|
def list_spaces(self) -> list[dict[str, Any]]:
|
||||||
try:
|
try:
|
||||||
data = self._post("/api/spaces/", {"page": 1, "limit": 100})
|
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:
|
except requests.HTTPError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
@ -97,8 +109,8 @@ class DocmostSeed:
|
||||||
print(f" [space] Created '{name}' id={sid}")
|
print(f" [space] Created '{name}' id={sid}")
|
||||||
return sid
|
return sid
|
||||||
|
|
||||||
def create_page(self, space_id: str, title: str, content: dict[str, Any] | None = None) -> str:
|
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}
|
body: dict[str, Any] = {"spaceId": space_id, "title": title, "format": fmt}
|
||||||
if content is not None:
|
if content is not None:
|
||||||
body["content"] = content
|
body["content"] = content
|
||||||
result = self._post("/api/pages/create", body)
|
result = self._post("/api/pages/create", body)
|
||||||
|
|
@ -118,34 +130,31 @@ class DocmostSeed:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def welcome_page_content() -> dict[str, Any]:
|
def welcome_page_content() -> str:
|
||||||
"""Tiptap doc JSON minimal pour la page Welcome."""
|
"""Page Welcome en markdown — Docmost le converti en Tiptap auto."""
|
||||||
return {
|
return """# Welcome formation-hub
|
||||||
"type": "doc",
|
|
||||||
"content": [
|
Wiki Docmost interne Acadenice — voir `docs/` du repo wiki pour la conception complete.
|
||||||
{"type": "heading", "attrs": {"level": 1}, "content": [
|
|
||||||
{"type": "text", "text": "Welcome formation-hub"}]},
|
## Stack
|
||||||
{"type": "paragraph", "content": [
|
|
||||||
{"type": "text", "text": "Wiki Docmost interne Acadenice — voir docs/ du repo wiki pour la conception complete."}]},
|
- **Docmost** : ce wiki (AGPL self-host)
|
||||||
{"type": "heading", "attrs": {"level": 2}, "content": [
|
- **Baserow** : DBs structurees (MIT self-host) — http://localhost:8080
|
||||||
{"type": "text", "text": "Stack"}]},
|
- **Bridge service** : Phase 2
|
||||||
{"type": "bulletList", "content": [
|
|
||||||
{"type": "listItem", "content": [
|
## Diagrammes natifs
|
||||||
{"type": "paragraph", "content": [
|
|
||||||
{"type": "text", "marks": [{"type": "bold"}], "text": "Docmost"},
|
Ajouter via le slash menu :
|
||||||
{"type": "text", "text": " : ce wiki (AGPL self-host)"}]}]},
|
- `/mermaid` pour les diagrammes Mermaid
|
||||||
{"type": "listItem", "content": [
|
- `/drawio` pour les diagrammes Draw.io
|
||||||
{"type": "paragraph", "content": [
|
- `/excalidraw` pour les whiteboards Excalidraw
|
||||||
{"type": "text", "marks": [{"type": "bold"}], "text": "Baserow"},
|
|
||||||
{"type": "text", "text": " : DBs structurees (MIT self-host)"}]}]},
|
## Liens utiles
|
||||||
{"type": "listItem", "content": [
|
|
||||||
{"type": "paragraph", "content": [
|
- Repo Forgejo : https://git.acadenice.com/AcadeNice/Wiki
|
||||||
{"type": "text", "marks": [{"type": "bold"}], "text": "Bridge service"},
|
- Stack locale : Docmost (3000) + Baserow (8080)
|
||||||
{"type": "text", "text": " : Phase 2"}]}]}]},
|
- Documentation projet : `docs/00-readme.md` du repo
|
||||||
{"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 main() -> int:
|
def main() -> int:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue