Files
personotes/API.md

945 lines
22 KiB
Markdown

# PersoNotes REST API Documentation
Version: **v1**
Base URL: `http://localhost:8080/api/v1`
## Table des matières
- [Vue d'ensemble](#vue-densemble)
- [Commandes CLI](#commandes-cli)
- [Authentification](#authentification)
- [Formats de données](#formats-de-données)
- [Endpoints](#endpoints)
- [Lister les notes](#lister-les-notes)
- [Récupérer une note](#récupérer-une-note)
- [Créer/Mettre à jour une note](#créermettre-à-jour-une-note)
- [Supprimer une note](#supprimer-une-note)
- [Lister les notes publiques](#lister-les-notes-publiques)
- [Basculer le statut public d'une note](#basculer-le-statut-public-dune-note)
- [Notes publiques](#notes-publiques)
- [Codes de statut HTTP](#codes-de-statut-http)
- [Exemples d'utilisation](#exemples-dutilisation)
---
## Vue d'ensemble
L'API REST de PersoNotes permet de gérer vos notes Markdown via HTTP. Elle supporte :
- **Listage** : Récupérer la liste de toutes les notes avec métadonnées
- **Lecture** : Télécharger une note en JSON ou Markdown brut
- **Écriture** : Créer ou mettre à jour une note
- **Suppression** : Supprimer une note définitivement
### Caractéristiques
-**Versionnée** : `/api/v1` pour assurer la compatibilité future
-**Content Negotiation** : Support JSON et Markdown selon le header `Accept`
-**Idempotence** : PUT crée ou met à jour (idempotent)
-**Automatisation** : Front matter géré automatiquement
-**Ré-indexation** : Recherche mise à jour automatiquement après chaque modification
-**Support sous-dossiers** : Organisation hiérarchique native
---
## Commandes CLI
Le serveur inclut des commandes CLI intégrées pour gérer les notes publiques sans avoir à lancer le serveur HTTP.
### Lister les notes publiques
Affiche toutes les notes qui ont été exportées en HTML public.
**Commande** :
```bash
./server list-public [notes-dir]
```
**Arguments** :
- `notes-dir` (optionnel) : Chemin vers le répertoire des notes (défaut: `./notes`)
**Exemple de sortie** :
```
📚 Notes publiques (4):
• 2025 Learning Goals
Source: personal/learning-goals.md
Public: public/learning-goals.html
Date: 2025-11-13 20:06:21
• AI Writing Assistant
Source: archive/ai-assistant.md
Public: public/ai-assistant.html
Date: 2025-11-13 19:43:28
• API Endpoints Reference
Source: documentation/api/endpoints.md
Public: public/endpoints.html
Date: 2025-11-13 19:36:57
• Product Backlog
Source: tasks/backlog.md
Public: public/backlog.html
Date: 2025-11-13 20:13:05
```
**Cas particuliers** :
- Si aucune note n'est publique : affiche "Aucune note publique."
- Si le fichier `.public.json` n'existe pas : affiche "Aucune note publique trouvée."
- Erreur si le répertoire n'existe pas
**Utilisation typique** :
```bash
# Lister les notes publiques
./server list-public
# Avec un répertoire personnalisé
./server list-public /path/to/notes
# Compter les notes publiques (Linux/macOS)
./server list-public | grep -c "^•"
# Exporter la liste dans un fichier
./server list-public > public-notes-list.txt
```
---
## Authentification
**Version actuelle : Aucune authentification requise**
⚠️ **IMPORTANT** : L'API n'a pas d'authentification. Si vous exposez le serveur publiquement :
1. Utilisez un reverse proxy (nginx, Caddy) avec authentification
2. Implémentez Basic Auth ou API Key
3. Utilisez un VPN ou tunnel SSH
---
## Formats de données
### Note complète (NoteResponse)
```json
{
"path": "projet/backend.md",
"title": "Backend API",
"content": "---\ntitle: Backend API\n...\n---\n\n# Content",
"body": "\n# Content",
"frontMatter": {
"title": "Backend API",
"date": "10-11-2025",
"last_modified": "10-11-2025:14:30",
"tags": ["projet", "backend"]
},
"lastModified": "10-11-2025:14:30",
"size": 1024
}
```
### Métadonnées de note (NoteMetadata)
```json
{
"path": "projet/backend.md",
"title": "Backend API",
"tags": ["projet", "backend"],
"lastModified": "10-11-2025:14:30",
"date": "10-11-2025",
"size": 1024
}
```
### Requête de création/modification (NoteRequest)
Deux options :
**Option 1 : Content complet** (recommandé pour migration)
```json
{
"content": "---\ntitle: Ma note\ntags: [test]\n---\n\n# Contenu"
}
```
**Option 2 : Body + FrontMatter séparés** (recommandé pour création)
```json
{
"body": "\n# Mon contenu\n\nTexte ici...",
"frontMatter": {
"title": "Ma note",
"tags": ["test", "exemple"]
}
}
```
### Erreur (ErrorResponse)
```json
{
"error": "Bad Request",
"message": "Invalid path",
"code": 400
}
```
---
## Endpoints
### Lister les notes
Récupère la liste de toutes les notes avec leurs métadonnées.
**Endpoint** : `GET /api/v1/notes`
**Paramètres** : Aucun
**Réponse** : `200 OK`
```json
{
"notes": [
{
"path": "projet/backend.md",
"title": "Backend API",
"tags": ["projet", "backend"],
"lastModified": "10-11-2025:14:30",
"date": "10-11-2025",
"size": 1024
},
{
"path": "daily/2025-11-10.md",
"title": "Notes du 10 novembre",
"tags": ["daily"],
"lastModified": "10-11-2025:09:15",
"date": "10-11-2025",
"size": 2048
}
],
"total": 2
}
```
**Exemple curl** :
```bash
curl http://localhost:8080/api/v1/notes
```
---
### Récupérer une note
Télécharge une note spécifique. Le format dépend du header `Accept`.
**Endpoint** : `GET /api/v1/notes/{path}`
**Paramètres** :
- `{path}` : Chemin relatif de la note (ex: `projet/backend.md`)
**Headers** :
- `Accept: application/json` (défaut) : Retourne JSON avec métadonnées
- `Accept: text/markdown` : Retourne Markdown brut
- `Accept: text/plain` : Retourne Markdown brut
**Réponse JSON** : `200 OK`
```json
{
"path": "projet/backend.md",
"title": "Backend API",
"content": "---\ntitle: Backend API\ndate: 10-11-2025\nlast_modified: 10-11-2025:14:30\ntags:\n - projet\n - backend\n---\n\n# Backend API\n\nContenu de la note...",
"body": "\n# Backend API\n\nContenu de la note...",
"frontMatter": {
"title": "Backend API",
"date": "10-11-2025",
"last_modified": "10-11-2025:14:30",
"tags": ["projet", "backend"]
},
"lastModified": "10-11-2025:14:30",
"size": 1024
}
```
**Réponse Markdown** : `200 OK`
```markdown
---
title: Backend API
date: 10-11-2025
last_modified: 10-11-2025:14:30
tags:
- projet
- backend
---
# Backend API
Contenu de la note...
```
**Erreurs** :
- `404 Not Found` : Note inexistante
**Exemples curl** :
```bash
# Récupérer en JSON
curl http://localhost:8080/api/v1/notes/projet/backend.md \
-H "Accept: application/json"
# Récupérer en Markdown brut
curl http://localhost:8080/api/v1/notes/projet/backend.md \
-H "Accept: text/markdown"
# Sauvegarder dans un fichier
curl http://localhost:8080/api/v1/notes/projet/backend.md \
-H "Accept: text/markdown" \
-o backend.md
```
---
### Créer/Mettre à jour une note
Crée une nouvelle note ou met à jour une note existante (idempotent).
**Endpoint** : `PUT /api/v1/notes/{path}`
**Paramètres** :
- `{path}` : Chemin relatif de la note (ex: `projet/nouvelle-note.md`)
**Headers** :
- `Content-Type: application/json` : Envoyer du JSON
- `Content-Type: text/markdown` : Envoyer du Markdown brut
**Body JSON** :
```json
{
"body": "\n# Ma nouvelle note\n\nContenu ici...",
"frontMatter": {
"title": "Ma nouvelle note",
"tags": ["test", "exemple"]
}
}
```
Ou avec `content` complet :
```json
{
"content": "---\ntitle: Ma note\ntags: [test]\n---\n\n# Contenu"
}
```
**Body Markdown brut** :
```markdown
# Ma nouvelle note
Contenu ici...
```
**Réponse** : `201 Created` (nouvelle note) ou `200 OK` (mise à jour)
```json
{
"path": "projet/nouvelle-note.md",
"title": "Ma nouvelle note",
"content": "---\ntitle: Ma nouvelle note\n...",
"body": "\n# Ma nouvelle note\n\nContenu ici...",
"frontMatter": {
"title": "Ma nouvelle note",
"date": "10-11-2025",
"last_modified": "10-11-2025:14:35",
"tags": ["test", "exemple"]
},
"lastModified": "10-11-2025:14:35",
"size": 256
}
```
**Comportement** :
- ✅ Crée automatiquement les dossiers parents
- ✅ Génère le front matter si absent
- ✅ Met à jour `last_modified` automatiquement
- ✅ Préserve `date` pour notes existantes
- ✅ Ré-indexe automatiquement pour la recherche
**Erreurs** :
- `400 Bad Request` : Chemin invalide ou JSON malformé
- `415 Unsupported Media Type` : Content-Type non supporté
- `500 Internal Server Error` : Erreur d'écriture
**Exemples curl** :
```bash
# Créer avec JSON
curl -X PUT http://localhost:8080/api/v1/notes/projet/test.md \
-H "Content-Type: application/json" \
-d '{
"body": "\n# Test\n\nCeci est un test.",
"frontMatter": {
"title": "Note de test",
"tags": ["test"]
}
}'
# Créer avec Markdown brut
curl -X PUT http://localhost:8080/api/v1/notes/projet/simple.md \
-H "Content-Type: text/markdown" \
-d "# Simple note
Contenu simple sans front matter."
# Upload depuis un fichier
curl -X PUT http://localhost:8080/api/v1/notes/projet/from-file.md \
-H "Content-Type: text/markdown" \
--data-binary @local-file.md
```
---
### Supprimer une note
Supprime définitivement une note.
**Endpoint** : `DELETE /api/v1/notes/{path}`
**Paramètres** :
- `{path}` : Chemin relatif de la note (ex: `projet/old-note.md`)
**Réponse** : `200 OK`
```json
{
"message": "Note deleted successfully",
"path": "projet/old-note.md"
}
```
**Erreurs** :
- `404 Not Found` : Note inexistante
- `500 Internal Server Error` : Erreur de suppression
**Exemple curl** :
```bash
curl -X DELETE http://localhost:8080/api/v1/notes/projet/old-note.md
```
---
### Lister les notes publiques
Récupère la liste des notes qui ont été publiées dans l'espace public.
**Endpoint** : `GET /api/public/list`
**Paramètres** : Aucun
**Réponse** : `200 OK`
```json
{
"notes": [
{
"path": "projet/backend.md",
"title": "Backend API",
"published_at": "2025-11-13T14:30:00Z"
},
{
"path": "personal/guide.md",
"title": "Guide d'utilisation",
"published_at": "2025-11-13T10:15:00Z"
}
]
}
```
**Champs retournés** :
- `path` : Chemin relatif de la note source
- `title` : Titre de la note
- `published_at` : Date/heure de publication (format ISO 8601)
**Notes** :
- Les notes sont triées par date de publication (plus récentes d'abord)
- Les fichiers HTML générés se trouvent dans `public/{nom-de-la-note}.html`
- Liste vide si aucune note n'est publique
**Exemple curl** :
```bash
# Lister toutes les notes publiques
curl http://localhost:8080/api/public/list
# Avec formatage jq
curl -s http://localhost:8080/api/public/list | jq '.notes[] | "\(.title) -> public/\(.path | split("/")[-1] | sub(".md$"; ".html"))"'
```
**Exemple de sortie formatée** :
```bash
$ curl -s http://localhost:8080/api/public/list | jq '.notes[] | .title'
"Backend API"
"Guide d'utilisation"
"Documentation projet"
```
**Compter les notes publiques** :
```bash
curl -s http://localhost:8080/api/public/list | jq '.notes | length'
```
---
### Basculer le statut public d'une note
Publie ou retire une note de l'espace public. Génère automatiquement un fichier HTML statique exportable.
**Endpoint** : `POST /api/public/toggle`
**Content-Type** : `application/x-www-form-urlencoded`
**Paramètres** :
- `path` (form) : Chemin relatif de la note (ex: `projet/backend.md`)
**Réponse** : `200 OK`
```json
{
"status": "public",
"path": "projet/backend.md"
}
```
Valeurs possibles pour `status` :
- `"public"` : La note est maintenant publique (HTML généré)
- `"private"` : La note est maintenant privée (HTML supprimé)
**Comportement** :
-**Génère du HTML statique** dans `public/nom-de-la-note.html`
-**Copie les CSS** nécessaires dans `public/static/`
-**Met à jour l'index** dans `public/index.html`
-**Structure plate** : Tous les fichiers dans `public/`, pas de sous-dossiers
-**Portable** : Les fichiers HTML peuvent être copiés sur n'importe quel serveur web
**Fichiers générés** :
```
public/
├── index.html # Liste de toutes les notes publiques
├── backend.md.html # Note convertie en HTML standalone
├── autre-note.html
└── static/
├── theme.css # Styles copiés
└── themes.css
```
**Erreurs** :
- `400 Bad Request` : Chemin manquant ou invalide
- `404 Not Found` : Note inexistante
- `405 Method Not Allowed` : Méthode autre que POST
- `500 Internal Server Error` : Erreur de génération HTML
**Exemple curl** :
```bash
# Publier une note
curl -X POST http://localhost:8080/api/public/toggle \
-d "path=projet/backend.md"
# La note est maintenant accessible à :
# http://localhost:8080/public/backend.html
```
**Exemple JavaScript** :
```javascript
// Publier une note
const response = await fetch('/api/public/toggle', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ path: 'projet/backend.md' }),
});
const data = await response.json();
console.log(data.status); // "public" ou "private"
```
**Scripts utiles** :
```bash
#!/bin/bash
# Lister les notes publiques avec leurs URLs
echo "📚 Notes publiques:"
curl -s http://localhost:8080/api/public/list | jq -r '.notes[] | "• \(.title)\n → http://localhost:8080/public/\(.path | split("/")[-1] | sub(".md$"; ".html"))\n"'
```
```bash
#!/bin/bash
# Exporter toutes les notes en HTML public
echo "Exporting all notes to public HTML..."
curl -s http://localhost:8080/api/v1/notes | jq -r '.notes[].path' | while read path; do
curl -X POST http://localhost:8080/api/public/toggle -d "path=$path" > /dev/null 2>&1
echo "✓ Published: $path"
done
echo ""
echo "✅ Export terminé!"
echo "📊 Total: $(curl -s http://localhost:8080/api/public/list | jq '.notes | length') notes publiques"
```
```bash
#!/bin/bash
# Retirer toutes les notes du public
echo "Unpublishing all public notes..."
curl -s http://localhost:8080/api/public/list | jq -r '.notes[].path' | while read path; do
curl -X POST http://localhost:8080/api/public/toggle -d "path=$path" > /dev/null 2>&1
echo "✓ Unpublished: $path"
done
echo "✅ Toutes les notes sont maintenant privées"
```
---
## Notes publiques
Le système de notes publiques génère des fichiers HTML statiques exportables. Cette section explique comment utiliser ces fichiers.
### Accès aux notes publiques
**Sur le serveur Personotes** :
```
http://localhost:8080/public/
```
**Fichiers générés** :
- `public/index.html` : Liste de toutes les notes publiques
- `public/*.html` : Notes converties en HTML standalone
- `public/static/` : CSS et assets
### Déploiement
Les fichiers HTML sont complètement autonomes et peuvent être déployés sur :
#### 1. Serveur web classique
```bash
# Copier sur un serveur Apache/Nginx
scp -r public/ user@server.com:/var/www/html/notes/
# Ou avec rsync
rsync -av public/ user@server.com:/var/www/html/notes/
```
**Configuration Nginx** :
```nginx
server {
listen 80;
server_name notes.example.com;
root /var/www/html/notes;
index index.html;
}
```
**Configuration Apache** :
```apache
<VirtualHost *:80>
ServerName notes.example.com
DocumentRoot /var/www/html/notes
</VirtualHost>
```
#### 2. GitHub Pages (gratuit)
```bash
cd public/
git init
git add .
git commit -m "Public notes"
git remote add origin https://github.com/username/notes-public.git
git push -u origin main
# Activer GitHub Pages dans Settings → Pages → main branch
# Vos notes seront accessibles à :
# https://username.github.io/notes-public/
```
#### 3. Netlify Drop
1. Allez sur https://app.netlify.com/drop
2. Glissez-déposez le dossier `public/`
3. Netlify génère automatiquement une URL
#### 4. Vercel
```bash
cd public/
npx vercel
```
### Automatisation de l'export
**Script de synchronisation** :
```bash
#!/bin/bash
# sync-public.sh - Synchroniser les notes publiques vers un serveur
REMOTE_USER="user"
REMOTE_HOST="server.com"
REMOTE_PATH="/var/www/html/notes"
rsync -av --delete public/ ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}
echo "✅ Notes publiques synchronisées !"
```
**Git Hook automatique** :
```bash
# .git/hooks/post-commit
#!/bin/bash
# Si le dossier public/ a changé, synchroniser
if git diff --name-only HEAD~1 | grep -q "^public/"; then
./sync-public.sh
fi
```
### Avantages
-**Performance** : HTML pré-généré = chargement instantané
-**Sécurité** : Fichiers statiques = surface d'attaque minimale
-**Portabilité** : Fonctionne sur n'importe quel serveur web
-**Gratuit** : Hébergement possible sur GitHub Pages, Netlify
-**SEO** : HTML pré-rendu = indexation optimale par Google
-**Pas de backend** : Pas besoin de Go sur le serveur de destination
### Limitations
- ⚠️ **Noms uniques** : Si deux notes dans différents dossiers ont le même nom (ex: `personal/test.md` et `work/test.md`), elles s'écraseront car la structure est plate
- ⚠️ **Republication manuelle** : Si vous modifiez une note déjà publique, vous devez la republier pour régénérer le HTML
- ⚠️ **Pas de recherche** : Les fichiers HTML n'incluent pas de fonction de recherche (uniquement consultables)
### Documentation complète
Pour plus d'informations sur l'export des notes publiques :
- **QUICK_START_PUBLIC.md** : Guide de démarrage rapide
- **EXPORT_GUIDE.md** : Guide complet de déploiement
---
## Codes de statut HTTP
| Code | Signification | Description |
|------|---------------|-------------|
| `200` | OK | Requête réussie |
| `201` | Created | Note créée avec succès |
| `400` | Bad Request | Requête invalide (chemin, JSON, etc.) |
| `404` | Not Found | Note inexistante |
| `405` | Method Not Allowed | Méthode HTTP non supportée |
| `415` | Unsupported Media Type | Content-Type non supporté |
| `500` | Internal Server Error | Erreur serveur |
---
## Exemples d'utilisation
### Synchronisation de notes
**Télécharger toutes les notes** :
```bash
#!/bin/bash
# Télécharger toutes les notes localement
mkdir -p notes-backup
# Récupérer la liste
curl -s http://localhost:8080/api/v1/notes | jq -r '.notes[].path' | while read path; do
# Créer les dossiers parents
mkdir -p "notes-backup/$(dirname "$path")"
# Télécharger la note
curl -s http://localhost:8080/api/v1/notes/"$path" \
-H "Accept: text/markdown" \
-o "notes-backup/$path"
echo "✓ Downloaded: $path"
done
echo "Backup terminé!"
```
**Uploader un dossier de notes** :
```bash
#!/bin/bash
# Uploader toutes les notes .md d'un dossier
find ./my-notes -name "*.md" | while read file; do
# Calculer le chemin relatif
relpath="${file#./my-notes/}"
# Upload
curl -X PUT http://localhost:8080/api/v1/notes/"$relpath" \
-H "Content-Type: text/markdown" \
--data-binary @"$file"
echo "✓ Uploaded: $relpath"
done
echo "Upload terminé!"
```
### Recherche et filtrage
**Lister toutes les notes avec un tag spécifique** :
```bash
curl -s http://localhost:8080/api/v1/notes | \
jq '.notes[] | select(.tags | contains(["projet"])) | .path'
```
**Compter les notes par dossier** :
```bash
curl -s http://localhost:8080/api/v1/notes | \
jq -r '.notes[].path' | \
xargs -n1 dirname | \
sort | uniq -c
```
### Création automatique de notes
**Note quotidienne** :
```bash
#!/bin/bash
# Créer une note quotidienne
TODAY=$(date +%Y-%m-%d)
TITLE="Notes du $(date +%d/%m/%Y)"
curl -X PUT http://localhost:8080/api/v1/notes/daily/${TODAY}.md \
-H "Content-Type: application/json" \
-d "{
\"body\": \"\\n# ${TITLE}\\n\\n## Tasks\\n- [ ] TODO\\n\\n## Notes\\n\",
\"frontMatter\": {
\"title\": \"${TITLE}\",
\"tags\": [\"daily\"]
}
}"
echo "Note quotidienne créée: daily/${TODAY}.md"
```
### Intégration avec d'autres outils
**Exporter en HTML avec Pandoc** :
```bash
curl -s http://localhost:8080/api/v1/notes/projet/doc.md \
-H "Accept: text/markdown" | \
pandoc -f markdown -t html -o doc.html
echo "Exporté en HTML: doc.html"
```
**Recherche full-text avec jq** :
```bash
# Chercher "API" dans tous les titres
curl -s http://localhost:8080/api/v1/notes | \
jq '.notes[] | select(.title | contains("API"))'
```
### Script de maintenance
**Vérifier les notes sans tags** :
```bash
curl -s http://localhost:8080/api/v1/notes | \
jq -r '.notes[] | select(.tags | length == 0) | .path'
```
**Statistiques** :
```bash
#!/bin/bash
# Afficher des statistiques sur les notes
STATS=$(curl -s http://localhost:8080/api/v1/notes)
TOTAL=$(echo "$STATS" | jq '.total')
TOTAL_SIZE=$(echo "$STATS" | jq '[.notes[].size] | add')
AVG_SIZE=$(echo "$STATS" | jq '[.notes[].size] | add / length | floor')
echo "📊 Statistiques des notes"
echo "========================"
echo "Total de notes: $TOTAL"
echo "Taille totale: $(numfmt --to=iec-i --suffix=B $TOTAL_SIZE)"
echo "Taille moyenne: $(numfmt --to=iec-i --suffix=B $AVG_SIZE)"
echo ""
echo "Top 5 tags:"
echo "$STATS" | jq -r '.notes[].tags[]' | sort | uniq -c | sort -rn | head -5
```
---
## Bonnes pratiques
### Sécurité
1. **Ne pas exposer publiquement sans authentification**
2. **Utiliser HTTPS en production**
3. **Valider les chemins côté client** (éviter `../` malveillants)
4. **Limiter la taille des uploads** (si nécessaire, ajouter un middleware)
### Performance
1. **Pagination** : L'API liste ne pagine pas actuellement (toutes les notes en une requête). Pour beaucoup de notes (>1000), envisager d'ajouter `?limit=` et `?offset=`
2. **Cache** : Utiliser un proxy cache (Varnish, nginx) pour GET
3. **Compression** : Activer gzip sur le reverse proxy
### Workflow recommandé
1. **Backup régulier** : Script cron qui télécharge toutes les notes
2. **Versioning Git** : Synchroniser le dossier de notes avec Git
3. **CI/CD** : Valider le format Markdown avec des linters
4. **Monitoring** : Logger les accès API pour audit
---
## Support et contribution
- **Issues** : Rapporter les bugs sur GitHub
- **Documentation** : Ce fichier (`API.md`)
- **Code source** : `internal/api/rest_handler.go`
---
## Changelog
### v1 (2025-11-13)
- ✨ Première version de l'API REST
- ✅ Endpoints: LIST, GET, PUT, DELETE
- ✅ Content negotiation JSON/Markdown
- ✅ Support sous-dossiers
- ✅ Gestion automatique du front matter
- ✅ Ré-indexation automatique
- ✅ Export de notes publiques en HTML statique (POST /api/public/toggle)
---
**Note** : Cette API coexiste avec l'interface web HTML. Les deux peuvent être utilisées simultanément sans conflit.