diff --git a/API_ENDPOINTS_FR.md b/API_ENDPOINTS_FR.md new file mode 100644 index 0000000000..95f5c000d5 --- /dev/null +++ b/API_ENDPOINTS_FR.md @@ -0,0 +1,1486 @@ +# Documentation API Teable - Endpoints et Exemples + +**Version**: 1.0 +**Date**: FΓ©vrier 2025 +**Base URL**: `http://localhost:3000/api/v1` + +--- + +## πŸ“‹ Table des matiΓ¨res + +1. [Authentification](#1-authentification) +2. [Espaces (Spaces)](#2-espaces-spaces) +3. [Bases (Bases)](#3-bases-bases) +4. [Tables](#4-tables) +5. [Champs (Fields)](#5-champs-fields) +6. [Vues (Views)](#6-vues-views) +7. [Enregistrements (Records)](#7-enregistrements-records) +8. [Commentaires](#8-commentaires) +9. [Partages](#9-partages) +10. [PiΓ¨ces jointes](#10-piΓ¨ces-jointes) +11. [Recherche et Filtrage](#11-recherche-et-filtrage) +12. [Codes d'erreur](#12-codes-derreur) + +--- + +## 1. Authentification + +### 1.1 Login avec email/password + +**Endpoint**: `POST /auth/login` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/auth/login \ + -H "Content-Type: application/json" \ + -d '{ + "email": "user@example.com", + "password": "password123" + }' +``` + +**Response** (200 OK): +```json +{ + "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "refreshToken": "refresh_token_here", + "user": { + "id": "user-123", + "email": "user@example.com", + "name": "John Doe", + "avatar": "https://..." + } +} +``` + +### 1.2 Register + +**Endpoint**: `POST /auth/register` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/auth/register \ + -H "Content-Type: application/json" \ + -d '{ + "email": "newuser@example.com", + "password": "password123", + "name": "New User" + }' +``` + +**Response** (201 Created): +```json +{ + "id": "user-456", + "email": "newuser@example.com", + "name": "New User", + "createdAt": "2025-02-05T10:00:00Z" +} +``` + +### 1.3 Refresh Token + +**Endpoint**: `POST /auth/refresh` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/auth/refresh \ + -H "Content-Type: application/json" \ + -d '{ + "refreshToken": "refresh_token_here" + }' +``` + +**Response** (200 OK): +```json +{ + "accessToken": "new_access_token...", + "refreshToken": "new_refresh_token..." +} +``` + +### 1.4 Logout + +**Endpoint**: `POST /auth/logout` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/auth/logout \ + -H "Authorization: Bearer YOUR_ACCESS_TOKEN" +``` + +**Response** (200 OK): +```json +{ + "message": "Logged out successfully" +} +``` + +### 1.5 OAuth Login (GitHub) + +**Endpoint**: `GET /auth/github` + +**Redirection Flow**: +``` +1. Client β†’ GET /auth/github +2. Backend β†’ Redirect to GitHub login page +3. GitHub β†’ User authorizes app +4. GitHub β†’ Redirect to /auth/github/callback +5. Backend β†’ Create/update user, issue tokens +6. Backend β†’ Redirect to frontend with tokens in URL +``` + +--- + +## 2. Espaces (Spaces) + +### 2.1 CrΓ©er un espace + +**Endpoint**: `POST /spaces` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/spaces \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "My Workspace", + "description": "A collaborative workspace" + }' +``` + +**Response** (201 Created): +```json +{ + "id": "space-123", + "name": "My Workspace", + "description": "A collaborative workspace", + "ownerId": "user-123", + "createdTime": "2025-02-05T10:00:00Z", + "updatedTime": "2025-02-05T10:00:00Z" +} +``` + +### 2.2 Lister les espaces + +**Endpoint**: `GET /spaces` + +**Request**: +```bash +curl http://localhost:3000/api/v1/spaces \ + -H "Authorization: Bearer TOKEN" +``` + +**Query Parameters**: +``` +?skip=0&limit=20&search=workspace +``` + +**Response** (200 OK): +```json +{ + "data": [ + { + "id": "space-123", + "name": "My Workspace", + "description": "...", + "ownerId": "user-123", + "baseCount": 5, + "collaborators": 3 + } + ], + "pagination": { + "total": 10, + "skip": 0, + "limit": 20 + } +} +``` + +### 2.3 RΓ©cupΓ©rer un espace + +**Endpoint**: `GET /spaces/:spaceId` + +**Request**: +```bash +curl http://localhost:3000/api/v1/spaces/space-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "id": "space-123", + "name": "My Workspace", + "description": "...", + "owner": { "id": "user-123", "name": "John" }, + "bases": [ + { "id": "base-1", "name": "CRM" }, + { "id": "base-2", "name": "Inventory" } + ], + "collaborators": [ + { "id": "user-456", "name": "Jane", "role": "editor" } + ] +} +``` + +### 2.4 Mettre Γ  jour un espace + +**Endpoint**: `PATCH /spaces/:spaceId` + +**Request**: +```bash +curl -X PATCH http://localhost:3000/api/v1/spaces/space-123 \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Updated Workspace", + "description": "New description" + }' +``` + +**Response** (200 OK): +```json +{ + "id": "space-123", + "name": "Updated Workspace", + "description": "New description", + "updatedTime": "2025-02-05T11:00:00Z" +} +``` + +### 2.5 Supprimer un espace + +**Endpoint**: `DELETE /spaces/:spaceId` + +**Request**: +```bash +curl -X DELETE http://localhost:3000/api/v1/spaces/space-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (204 No Content): +``` +(empty body) +``` + +### 2.6 Inviter un collaborateur + +**Endpoint**: `POST /spaces/:spaceId/invite` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/spaces/space-123/invite \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "email": "newuser@example.com", + "role": "editor" + }' +``` + +**Response** (200 OK): +```json +{ + "invitationId": "inv-123", + "email": "newuser@example.com", + "role": "editor", + "expiresAt": "2025-02-12T10:00:00Z" +} +``` + +--- + +## 3. Bases (Bases) + +### 3.1 CrΓ©er une base + +**Endpoint**: `POST /spaces/:spaceId/bases` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/spaces/space-123/bases \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Customer CRM", + "description": "Customer relationship management" + }' +``` + +**Response** (201 Created): +```json +{ + "id": "base-456", + "spaceId": "space-123", + "name": "Customer CRM", + "description": "Customer relationship management", + "createdTime": "2025-02-05T10:00:00Z" +} +``` + +### 3.2 Lister les bases d'un espace + +**Endpoint**: `GET /spaces/:spaceId/bases` + +**Request**: +```bash +curl http://localhost:3000/api/v1/spaces/space-123/bases \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "data": [ + { + "id": "base-1", + "name": "CRM", + "tableCount": 3, + "updatedTime": "2025-02-05T10:00:00Z" + } + ] +} +``` + +### 3.3 RΓ©cupΓ©rer une base + +**Endpoint**: `GET /bases/:baseId` + +**Request**: +```bash +curl http://localhost:3000/api/v1/bases/base-456 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "id": "base-456", + "name": "Customer CRM", + "tables": [ + { "id": "tbl-1", "name": "Customers" }, + { "id": "tbl-2", "name": "Orders" } + ], + "owner": { "id": "user-123" }, + "collaborators": [] +} +``` + +### 3.4 Mettre Γ  jour une base + +**Endpoint**: `PATCH /bases/:baseId` + +**Request**: +```bash +curl -X PATCH http://localhost:3000/api/v1/bases/base-456 \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Updated CRM", + "description": "Updated description" + }' +``` + +**Response** (200 OK): +```json +{ + "id": "base-456", + "name": "Updated CRM", + "description": "Updated description" +} +``` + +### 3.5 Supprimer une base + +**Endpoint**: `DELETE /bases/:baseId` + +**Request**: +```bash +curl -X DELETE http://localhost:3000/api/v1/bases/base-456 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (204 No Content): +``` +(empty body) +``` + +--- + +## 4. Tables + +### 4.1 CrΓ©er une table + +**Endpoint**: `POST /bases/:baseId/tables` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Customers", + "description": "Customer records" + }' +``` + +**Response** (201 Created): +```json +{ + "id": "tbl-123", + "baseId": "base-456", + "name": "Customers", + "description": "Customer records", + "fields": [], + "views": [], + "createdTime": "2025-02-05T10:00:00Z" +} +``` + +### 4.2 Lister les tables + +**Endpoint**: `GET /bases/:baseId/tables` + +**Request**: +```bash +curl http://localhost:3000/api/v1/bases/base-456/tables \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "data": [ + { + "id": "tbl-1", + "name": "Customers", + "fieldCount": 5, + "recordCount": 150 + } + ] +} +``` + +### 4.3 RΓ©cupΓ©rer une table + +**Endpoint**: `GET /bases/:baseId/tables/:tableId` + +**Request**: +```bash +curl http://localhost:3000/api/v1/bases/base-456/tables/tbl-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "id": "tbl-123", + "name": "Customers", + "fields": [ + { + "id": "fld-1", + "name": "Email", + "type": "email", + "required": true + } + ], + "views": [ + { "id": "view-1", "name": "All Customers", "type": "grid" } + ], + "recordCount": 150 +} +``` + +### 4.4 Supprimer une table + +**Endpoint**: `DELETE /bases/:baseId/tables/:tableId` + +**Request**: +```bash +curl -X DELETE http://localhost:3000/api/v1/bases/base-456/tables/tbl-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (204 No Content): +``` +(empty body) +``` + +--- + +## 5. Champs (Fields) + +### 5.1 CrΓ©er un champ + +**Endpoint**: `POST /bases/:baseId/tables/:tableId/fields` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/fields \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Email", + "type": "email", + "description": "Customer email", + "required": true, + "defaultValue": null + }' +``` + +**Response** (201 Created): +```json +{ + "id": "fld-123", + "tableId": "tbl-123", + "name": "Email", + "type": "email", + "required": true, + "createdTime": "2025-02-05T10:00:00Z" +} +``` + +### 5.2 Types de champs supportΓ©s + +| Type | Description | Options | +|------|-------------|---------| +| `text` | Texte simple | maxLength, defaultValue | +| `email` | Adresse email | defaultValue | +| `number` | Nombre entier ou dΓ©cimal | precision, scale, defaultValue | +| `date` | Date | format (YYYY-MM-DD) | +| `datetime` | Date et heure | format (YYYY-MM-DD HH:mm:ss) | +| `checkbox` | BoolΓ©en | defaultValue | +| `select` | SΓ©lection simple | options: [{label, value, color}] | +| `multiSelect` | SΓ©lection multiple | options: [{label, value, color}] | +| `attachment` | Fichiers | maxCount | +| `lookup` | RΓ©fΓ©rence | linkedTableId, linkedFieldId | +| `formula` | Champ calculΓ© | expression, resultType | +| `link` | Lien hypertexte | defaultValue | +| `phone` | NumΓ©ro de tΓ©lΓ©phone | defaultValue | +| `url` | URL | defaultValue | +| `richText` | Texte formatΓ© | defaultValue | +| `rating` | Notation | max (1-5) | + +### 5.3 Lister les champs + +**Endpoint**: `GET /bases/:baseId/tables/:tableId/fields` + +**Request**: +```bash +curl http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/fields \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "data": [ + { + "id": "fld-1", + "name": "Email", + "type": "email", + "required": true + }, + { + "id": "fld-2", + "name": "Name", + "type": "text", + "required": true + } + ] +} +``` + +### 5.4 Mettre Γ  jour un champ + +**Endpoint**: `PATCH /bases/:baseId/tables/:tableId/fields/:fieldId` + +**Request**: +```bash +curl -X PATCH http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/fields/fld-123 \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Primary Email", + "required": false + }' +``` + +**Response** (200 OK): +```json +{ + "id": "fld-123", + "name": "Primary Email", + "type": "email", + "required": false +} +``` + +### 5.5 Supprimer un champ + +**Endpoint**: `DELETE /bases/:baseId/tables/:tableId/fields/:fieldId` + +**Request**: +```bash +curl -X DELETE http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/fields/fld-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (204 No Content): +``` +(empty body) +``` + +--- + +## 6. Vues (Views) + +### 6.1 CrΓ©er une vue + +**Endpoint**: `POST /bases/:baseId/tables/:tableId/views` + +**Request - Grid View**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/views \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "All Customers", + "type": "grid", + "options": { + "freezeColumns": 1, + "rowHeight": "auto" + } + }' +``` + +**Request - Form View**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/views \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Add Customer", + "type": "form", + "options": { + "layout": "single-column", + "submitText": "Save Customer" + } + }' +``` + +**Request - Kanban View**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/views \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Pipeline", + "type": "kanban", + "options": { + "groupByField": "status", + "cardFieldIds": ["fld-1", "fld-2"] + } + }' +``` + +**Request - Calendar View**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/views \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Events", + "type": "calendar", + "options": { + "dateFieldId": "fld-date", + "colorFieldId": "fld-category" + } + }' +``` + +**Response** (201 Created): +```json +{ + "id": "view-123", + "tableId": "tbl-123", + "name": "All Customers", + "type": "grid", + "createdTime": "2025-02-05T10:00:00Z" +} +``` + +### 6.2 Lister les vues + +**Endpoint**: `GET /bases/:baseId/tables/:tableId/views` + +**Request**: +```bash +curl http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/views \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "data": [ + { + "id": "view-1", + "name": "All Customers", + "type": "grid" + }, + { + "id": "view-2", + "name": "Pipeline", + "type": "kanban" + } + ] +} +``` + +### 6.3 Mettre Γ  jour une vue + +**Endpoint**: `PATCH /bases/:baseId/tables/:tableId/views/:viewId` + +**Request**: +```bash +curl -X PATCH http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/views/view-123 \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Updated View Name", + "options": { + "rowHeight": "tall" + } + }' +``` + +**Response** (200 OK): +```json +{ + "id": "view-123", + "name": "Updated View Name", + "type": "grid" +} +``` + +### 6.4 Appliquer un filtre Γ  une vue + +**Endpoint**: `POST /bases/:baseId/tables/:tableId/views/:viewId/filters` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/views/view-123/filters \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "fieldId": "fld-email", + "operator": "contains", + "value": "example.com" + }' +``` + +**OpΓ©rateurs de filtre supportΓ©s**: +- `equals` - Γ‰gal Γ  +- `notEquals` - Pas Γ©gal Γ  +- `contains` - Contient +- `notContains` - Ne contient pas +- `startsWith` - Commence par +- `endsWith` - Se termine par +- `gt` - Plus grand que +- `gte` - Plus grand ou Γ©gal Γ  +- `lt` - Moins que +- `lte` - Moins ou Γ©gal Γ  +- `isEmpty` - Vide +- `isNotEmpty` - Pas vide + +**Response** (201 Created): +```json +{ + "id": "filter-123", + "viewId": "view-123", + "fieldId": "fld-email", + "operator": "contains", + "value": "example.com" +} +``` + +### 6.5 Appliquer un tri Γ  une vue + +**Endpoint**: `POST /bases/:baseId/tables/:tableId/views/:viewId/sorts` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/views/view-123/sorts \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "fieldId": "fld-name", + "direction": "ascending", + "priority": 1 + }' +``` + +**Response** (201 Created): +```json +{ + "id": "sort-123", + "viewId": "view-123", + "fieldId": "fld-name", + "direction": "ascending", + "priority": 1 +} +``` + +--- + +## 7. Enregistrements (Records) + +### 7.1 CrΓ©er un enregistrement + +**Endpoint**: `POST /bases/:baseId/tables/:tableId/records` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "fields": { + "fld-name": "John Doe", + "fld-email": "john@example.com", + "fld-phone": "+33123456789", + "fld-country": "France" + } + }' +``` + +**Response** (201 Created): +```json +{ + "id": "rec-123", + "tableId": "tbl-123", + "fields": { + "fld-name": "John Doe", + "fld-email": "john@example.com", + "fld-phone": "+33123456789", + "fld-country": "France" + }, + "createdBy": "user-123", + "createdTime": "2025-02-05T10:00:00Z" +} +``` + +### 7.2 RΓ©cupΓ©rer les enregistrements + +**Endpoint**: `GET /bases/:baseId/tables/:tableId/records` + +**Request**: +```bash +curl "http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records?skip=0&limit=50" \ + -H "Authorization: Bearer TOKEN" +``` + +**Query Parameters**: +``` +?skip=0&limit=50&search=john&fieldIds=fld-1,fld-2 +``` + +**Response** (200 OK): +```json +{ + "data": [ + { + "id": "rec-1", + "fields": { + "fld-name": "John Doe", + "fld-email": "john@example.com" + }, + "createdTime": "2025-02-05T10:00:00Z" + } + ], + "pagination": { + "total": 150, + "skip": 0, + "limit": 50 + } +} +``` + +### 7.3 RΓ©cupΓ©rer un enregistrement + +**Endpoint**: `GET /bases/:baseId/tables/:tableId/records/:recordId` + +**Request**: +```bash +curl http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "id": "rec-123", + "tableId": "tbl-123", + "fields": { + "fld-name": "John Doe", + "fld-email": "john@example.com", + "fld-phone": "+33123456789" + }, + "createdBy": "user-123", + "updatedBy": "user-123", + "createdTime": "2025-02-05T10:00:00Z", + "updatedTime": "2025-02-05T11:00:00Z" +} +``` + +### 7.4 Mettre Γ  jour un enregistrement + +**Endpoint**: `PATCH /bases/:baseId/tables/:tableId/records/:recordId` + +**Request**: +```bash +curl -X PATCH http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123 \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "fields": { + "fld-email": "newemail@example.com", + "fld-phone": "+33987654321" + } + }' +``` + +**Response** (200 OK): +```json +{ + "id": "rec-123", + "fields": { + "fld-name": "John Doe", + "fld-email": "newemail@example.com", + "fld-phone": "+33987654321" + }, + "updatedTime": "2025-02-05T11:30:00Z" +} +``` + +### 7.5 Supprimer un enregistrement + +**Endpoint**: `DELETE /bases/:baseId/tables/:tableId/records/:recordId` + +**Request**: +```bash +curl -X DELETE http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (204 No Content): +``` +(empty body) +``` + +### 7.6 OpΓ©rations en batch + +**Endpoint**: `POST /bases/:baseId/tables/:tableId/records/batch` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/batch \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "operations": [ + { + "type": "create", + "fields": { "fld-name": "Jane Doe" } + }, + { + "type": "update", + "recordId": "rec-456", + "fields": { "fld-status": "active" } + }, + { + "type": "delete", + "recordId": "rec-789" + } + ] + }' +``` + +**Response** (200 OK): +```json +{ + "results": [ + { "type": "create", "recordId": "rec-999" }, + { "type": "update", "recordId": "rec-456" }, + { "type": "delete", "recordId": "rec-789" } + ] +} +``` + +--- + +## 8. Commentaires + +### 8.1 CrΓ©er un commentaire + +**Endpoint**: `POST /bases/:baseId/tables/:tableId/records/:recordId/comments` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123/comments \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "text": "This customer needs follow-up", + "mentions": ["user-456"] + }' +``` + +**Response** (201 Created): +```json +{ + "id": "comment-123", + "recordId": "rec-123", + "text": "This customer needs follow-up", + "author": { + "id": "user-123", + "name": "John", + "avatar": "https://..." + }, + "createdTime": "2025-02-05T10:00:00Z" +} +``` + +### 8.2 Lister les commentaires + +**Endpoint**: `GET /bases/:baseId/tables/:tableId/records/:recordId/comments` + +**Request**: +```bash +curl http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123/comments \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "data": [ + { + "id": "comment-1", + "text": "Follow up needed", + "author": { "id": "user-123", "name": "John" }, + "createdTime": "2025-02-05T10:00:00Z" + } + ] +} +``` + +### 8.3 Mettre Γ  jour un commentaire + +**Endpoint**: `PATCH /bases/:baseId/tables/:tableId/records/:recordId/comments/:commentId` + +**Request**: +```bash +curl -X PATCH http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123/comments/comment-123 \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "text": "Updated comment text" + }' +``` + +**Response** (200 OK): +```json +{ + "id": "comment-123", + "text": "Updated comment text", + "updatedTime": "2025-02-05T11:00:00Z" +} +``` + +### 8.4 Supprimer un commentaire + +**Endpoint**: `DELETE /bases/:baseId/tables/:tableId/records/:recordId/comments/:commentId` + +**Request**: +```bash +curl -X DELETE http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123/comments/comment-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (204 No Content): +``` +(empty body) +``` + +--- + +## 9. Partages + +### 9.1 CrΓ©er un partage public + +**Endpoint**: `POST /bases/:baseId/shares` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/shares \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "type": "view", + "viewId": "view-123", + "permissions": { + "canRead": true, + "canCreate": false, + "canUpdate": false, + "canDelete": false + }, + "password": "optional-password" + }' +``` + +**Response** (201 Created): +```json +{ + "id": "share-123", + "baseId": "base-456", + "token": "shareable-token-here", + "url": "https://teable.io/share/shareable-token-here", + "createdTime": "2025-02-05T10:00:00Z" +} +``` + +### 9.2 Lister les partages + +**Endpoint**: `GET /bases/:baseId/shares` + +**Request**: +```bash +curl http://localhost:3000/api/v1/bases/base-456/shares \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "data": [ + { + "id": "share-1", + "token": "token-123", + "type": "view", + "permissions": { "canRead": true }, + "createdTime": "2025-02-05T10:00:00Z" + } + ] +} +``` + +### 9.3 RΓ©voquer un partage + +**Endpoint**: `DELETE /bases/:baseId/shares/:shareId` + +**Request**: +```bash +curl -X DELETE http://localhost:3000/api/v1/bases/base-456/shares/share-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (204 No Content): +``` +(empty body) +``` + +--- + +## 10. PiΓ¨ces jointes + +### 10.1 Upload de fichier + +**Endpoint**: `POST /bases/:baseId/tables/:tableId/records/:recordId/attachments` + +**Request**: +```bash +curl -X POST http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123/attachments \ + -H "Authorization: Bearer TOKEN" \ + -F "file=@/path/to/file.pdf" +``` + +**Response** (201 Created): +```json +{ + "id": "att-123", + "recordId": "rec-123", + "filename": "document.pdf", + "url": "https://storage.example.com/files/document.pdf", + "size": 2048576, + "mimeType": "application/pdf", + "uploadedAt": "2025-02-05T10:00:00Z" +} +``` + +### 10.2 Lister les piΓ¨ces jointes + +**Endpoint**: `GET /bases/:baseId/tables/:tableId/records/:recordId/attachments` + +**Request**: +```bash +curl http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123/attachments \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (200 OK): +```json +{ + "data": [ + { + "id": "att-1", + "filename": "invoice.pdf", + "url": "https://storage.example.com/files/invoice.pdf", + "size": 1024000 + } + ] +} +``` + +### 10.3 Supprimer une piΓ¨ce jointe + +**Endpoint**: `DELETE /bases/:baseId/tables/:tableId/records/:recordId/attachments/:attachmentId` + +**Request**: +```bash +curl -X DELETE http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/rec-123/attachments/att-123 \ + -H "Authorization: Bearer TOKEN" +``` + +**Response** (204 No Content): +``` +(empty body) +``` + +--- + +## 11. Recherche et Filtrage + +### 11.1 Recherche textuelle + +**Endpoint**: `GET /bases/:baseId/tables/:tableId/records?search=john` + +**Request**: +```bash +curl "http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records?search=john" \ + -H "Authorization: Bearer TOKEN" +``` + +### 11.2 Filtrage avancΓ© + +**Endpoint**: `GET /bases/:baseId/tables/:tableId/records` + +**Query Parameters**: +``` +?filters=[ + { + "fieldId": "fld-email", + "operator": "contains", + "value": "example.com" + }, + { + "fieldId": "fld-status", + "operator": "equals", + "value": "active" + } +]&filterLogic=AND +``` + +### 11.3 AgrΓ©gations + +**Endpoint**: `GET /bases/:baseId/tables/:tableId/records/aggregate` + +**Request**: +```bash +curl -X GET "http://localhost:3000/api/v1/bases/base-456/tables/tbl-123/records/aggregate" \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "aggregations": [ + { + "fieldId": "fld-price", + "operation": "SUM" + }, + { + "fieldId": "fld-category", + "operation": "COUNT" + } + ], + "groupBy": ["fld-category"] + }' +``` + +**OpΓ©rations d'agrΓ©gation supportΓ©es**: +- `COUNT` - Nombre d'enregistrements +- `SUM` - Somme des valeurs +- `AVG` - Moyenne +- `MIN` - Valeur minimale +- `MAX` - Valeur maximale +- `DISTINCT_COUNT` - Nombre distinct + +**Response** (200 OK): +```json +{ + "data": [ + { + "group": { "fld-category": "Electronics" }, + "aggregations": { + "price_sum": 50000, + "count": 25 + } + } + ] +} +``` + +--- + +## 12. Codes d'erreur + +### 12.1 Erreurs HTTP courantes + +| Code | Message | Signification | +|------|---------|---------------| +| 200 | OK | RequΓͺte rΓ©ussie | +| 201 | Created | Ressource créée | +| 204 | No Content | Suppression rΓ©ussie | +| 400 | Bad Request | RequΓͺte invalide | +| 401 | Unauthorized | Authentification requise | +| 403 | Forbidden | AccΓ¨s refusΓ© | +| 404 | Not Found | Ressource non trouvΓ©e | +| 409 | Conflict | Conflit de version | +| 422 | Unprocessable Entity | Validation Γ©chouΓ©e | +| 429 | Too Many Requests | Rate limited | +| 500 | Internal Server Error | Erreur serveur | + +### 12.2 Format d'erreur + +```json +{ + "statusCode": 400, + "message": "Validation failed", + "error": "Bad Request", + "details": [ + { + "field": "email", + "message": "email must be a valid email address" + } + ] +} +``` + +### 12.3 Exemples d'erreurs + +**Authentification manquante**: +```json +{ + "statusCode": 401, + "message": "Unauthorized - No token provided", + "error": "Unauthorized" +} +``` + +**Permission insuffisante**: +```json +{ + "statusCode": 403, + "message": "You don't have permission to access this resource", + "error": "Forbidden" +} +``` + +**Validation Γ©chouΓ©e**: +```json +{ + "statusCode": 422, + "message": "Validation failed", + "error": "Unprocessable Entity", + "details": [ + { + "field": "email", + "message": "email must be a valid email" + }, + { + "field": "password", + "message": "password must be at least 8 characters" + } + ] +} +``` + +--- + +## Exemples complets + +### Exemple 1: CrΓ©er une base complΓ¨te avec tables et donnΓ©es + +```bash +#!/bin/bash + +TOKEN="your_access_token" +SPACE_ID="space-123" + +# 1. CrΓ©er une base +BASE_RESPONSE=$(curl -s -X POST "http://localhost:3000/api/v1/spaces/$SPACE_ID/bases" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"name": "Task Manager", "description": "Manage team tasks"}') + +BASE_ID=$(echo $BASE_RESPONSE | jq -r '.id') +echo "Created base: $BASE_ID" + +# 2. CrΓ©er une table +TABLE_RESPONSE=$(curl -s -X POST "http://localhost:3000/api/v1/bases/$BASE_ID/tables" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"name": "Tasks", "description": "Task list"}') + +TABLE_ID=$(echo $TABLE_RESPONSE | jq -r '.id') +echo "Created table: $TABLE_ID" + +# 3. Ajouter des champs +curl -s -X POST "http://localhost:3000/api/v1/bases/$BASE_ID/tables/$TABLE_ID/fields" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"name": "Title", "type": "text", "required": true}' > /dev/null + +curl -s -X POST "http://localhost:3000/api/v1/bases/$BASE_ID/tables/$TABLE_ID/fields" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"name": "Status", "type": "select", "options": [{"label": "Todo"}, {"label": "In Progress"}, {"label": "Done"}]}' > /dev/null + +# 4. CrΓ©er une vue +VIEW_RESPONSE=$(curl -s -X POST "http://localhost:3000/api/v1/bases/$BASE_ID/tables/$TABLE_ID/views" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"name": "All Tasks", "type": "grid"}') + +VIEW_ID=$(echo $VIEW_RESPONSE | jq -r '.id') +echo "Created view: $VIEW_ID" + +# 5. Ajouter des enregistrements +curl -s -X POST "http://localhost:3000/api/v1/bases/$BASE_ID/tables/$TABLE_ID/records" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"fields": {"Title": "Design API", "Status": "In Progress"}}' > /dev/null + +curl -s -X POST "http://localhost:3000/api/v1/bases/$BASE_ID/tables/$TABLE_ID/records" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"fields": {"Title": "Implement endpoints", "Status": "Todo"}}' > /dev/null + +echo "Setup complete!" +``` + +--- + +**Documentation API - Version 1.0** +**Date**: FΓ©vrier 2025 +**Base URL**: http://localhost:3000/api/v1 diff --git a/ARCHITECTURE_DETAILS_FR.md b/ARCHITECTURE_DETAILS_FR.md new file mode 100644 index 0000000000..e8f32c8f3a --- /dev/null +++ b/ARCHITECTURE_DETAILS_FR.md @@ -0,0 +1,959 @@ +# Architecture DΓ©taillΓ©e du Projet Teable + +**Document de rΓ©fΓ©rence technique** +**Version**: 1.0 +**Date**: FΓ©vrier 2025 + +--- + +## πŸ“š Table des matiΓ¨res + +1. [Diagrammes d'architecture](#1-diagrammes-darchitecture) +2. [Communication entre services](#2-communication-entre-services) +3. [Flux de donnΓ©es](#3-flux-de-donnΓ©es) +4. [Patterns et bonnes pratiques](#4-patterns-et-bonnes-pratiques) +5. [DΓ©pendances critiques](#5-dΓ©pendances-critiques) +6. [Points d'intΓ©gration](#6-points-dintΓ©gration) +7. [Analyse des modules](#7-analyse-des-modules) + +--- + +## 1. Diagrammes d'architecture + +### 1.1 Architecture globale en couches + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ COUCHE PRΓ‰SENTATION β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Grid View β”‚ Form View β”‚ Kanban View β”‚ Calendar Viewβ”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Comment β”‚ Share β”‚ Collaboration β”‚ β”‚ +β”‚ β”‚ Thread β”‚ Modal β”‚ Features β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ React Components (Next.js) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ HTTP/WebSocket + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ COUCHE MΓ‰TIER (BUSINESS) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ NestJS Backend β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Auth β”‚ Access β”‚ Validation & Schema β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Module β”‚ Control β”‚ Management β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Record β”‚ Field β”‚ View Operations β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Service β”‚ Service β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Attachment β”‚ Comment β”‚ Share & Permission β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Manager β”‚ Service β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Aggregation β”‚ AI Service β”‚ Notification Service β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Engine β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ Plugin β”‚ Import β”‚ Export Service β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Manager β”‚ Export β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Core Business β”‚ Field Formula β”‚ Query Language Parser β”‚ β”‚ +β”‚ β”‚ Logic β”‚ ANTLR4 Parser β”‚ (TQL) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ Prisma ORM + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ COUCHE PERSISTANCE β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ PostgreSQL β”‚ Redis β”‚ MinIO (S3) β”‚ β”‚ +β”‚ β”‚ DonnΓ©es β”‚ Cache β”‚ Stockage fichiers β”‚ β”‚ +β”‚ β”‚ principales β”‚ Sessions β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 1.2 Architecture microservices-like + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ API Gateway (Express) β”‚ +β”‚ Port 3000 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ + ↓ ↓ ↓ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Auth β”‚ β”‚ Record β”‚ β”‚ Attachment β”‚ + β”‚ Service β”‚ β”‚ Service β”‚ β”‚ Service β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Access β”‚ β”‚ View β”‚ β”‚ Comment β”‚ + β”‚ Token β”‚ β”‚ Service β”‚ β”‚ Service β”‚ + β”‚ Service β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Field β”‚ + β”‚ Service β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Prisma β”‚ β”‚ Cache β”‚ + β”‚ ORM β”‚ β”‚ (Redis) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚PostgreSQLβ”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 1.3 Flux de requΓͺte HTTP + +``` +1. USER REQUEST + └─→ HTTP(S) POST/GET/PATCH/DELETE + User agent β†’ Next.js (Frontend) + +2. FRONTEND PROCESSING + └─→ React component updates state + └─→ API call via fetch/axios + └─→ Add JWT token to headers + +3. BACKEND ROUTING + └─→ Express/NestJS routing + └─→ Controller method dispatch + └─→ Guard decorators (Auth, Permission) + +4. VALIDATION + └─→ DTO validation (class-validator) + └─→ Zod schema validation + └─→ Return 400 if invalid + +5. BUSINESS LOGIC + └─→ Service layer execution + └─→ Prisma ORM queries + └─→ Cache check (Redis) + +6. DATABASE OPERATION + └─→ Query builder + └─→ SQL execution on PostgreSQL + └─→ Cache update + +7. RESPONSE PREPARATION + └─→ Serialize response data + └─→ HTTP status code (200, 201, etc.) + └─→ JSON body + +8. REAL-TIME BROADCAST + └─→ WebSocket emit (ShareDB) + └─→ Other connected clients receive update + +9. FRONTEND UPDATE + └─→ React state update + └─→ Component re-render + └─→ UI reflects new data +``` + +--- + +## 2. Communication entre services + +### 2.1 REST API + +**Pattern**: RESTful avec HTTP methods + +```typescript +// Base routes +POST /api/v1/bases # Create base +GET /api/v1/bases # List bases +GET /api/v1/bases/:id # Get base +PATCH /api/v1/bases/:id # Update base +DELETE /api/v1/bases/:id # Delete base + +// Table routes +POST /api/v1/bases/:baseId/tables # Create table +GET /api/v1/bases/:baseId/tables # List tables +PATCH /api/v1/bases/:baseId/tables/:tableId +DELETE /api/v1/bases/:baseId/tables/:tableId + +// Record routes +POST /api/v1/bases/:baseId/tables/:tableId/records +GET /api/v1/bases/:baseId/tables/:tableId/records +GET /api/v1/bases/:baseId/tables/:tableId/records/:recordId +PATCH /api/v1/bases/:baseId/tables/:tableId/records/:recordId +DELETE /api/v1/bases/:baseId/tables/:tableId/records/:recordId + +// View routes +POST /api/v1/bases/:baseId/tables/:tableId/views +GET /api/v1/bases/:baseId/tables/:tableId/views +PATCH /api/v1/bases/:baseId/tables/:tableId/views/:viewId +DELETE /api/v1/bases/:baseId/tables/:tableId/views/:viewId + +// Field routes +POST /api/v1/bases/:baseId/tables/:tableId/fields +GET /api/v1/bases/:baseId/tables/:tableId/fields +PATCH /api/v1/bases/:baseId/tables/:tableId/fields/:fieldId +DELETE /api/v1/bases/:baseId/tables/:tableId/fields/:fieldId + +// Share routes +POST /api/v1/bases/:baseId/shares +GET /api/v1/bases/:baseId/shares +DELETE /api/v1/bases/:baseId/shares/:shareId + +// Comment routes +POST /api/v1/bases/:baseId/tables/:tableId/records/:recordId/comments +GET /api/v1/bases/:baseId/tables/:tableId/records/:recordId/comments +DELETE /api/v1/bases/:baseId/tables/:tableId/records/:recordId/comments/:commentId +``` + +### 2.2 WebSocket Real-time + +**Pattern**: ShareDB + Custom events + +```typescript +// ShareDB operations (CRUD) +{ + type: 'create', + collection: 'records', + id: 'record-123', + data: { /* record data */ } +} + +// Custom events +connection.send({ + type: 'recordUpdate', + payload: { + recordId: 'record-123', + changes: { field1: 'newValue' } + } +}) + +// Subscription pattern +connection.subscribe('records', recordId, (err, doc) => { + if (!err) { + doc.fetch((err) => { + if (!err) { + doc.on('op', (op, source) => { + // Handle operation + }); + } + }); + } +}); +``` + +### 2.3 Event Bus (Internal) + +**Pattern**: EventEmitter ou Observer Pattern + +```typescript +// Example: Record created event +this.eventEmitter.emit('record:created', { + recordId: 'rec-123', + tableId: 'tbl-456', + userId: 'user-789', + timestamp: new Date(), +}); + +// Listeners +eventEmitter.on('record:created', async (data) => { + // Update aggregations + // Trigger webhooks + // Send notifications + // Broadcast via WebSocket +}); +``` + +--- + +## 3. Flux de donnΓ©es + +### 3.1 CrΓ©ation d'un enregistrement + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ User clicks β”‚ +β”‚ "New Record" β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Frontend Event Handler β”‚ +β”‚ - Collect form data β”‚ +β”‚ - Validate client-side β”‚ +β”‚ - Show loading state β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ POST /api/records β”‚ +β”‚ Header: Authorization token β”‚ +β”‚ Body: { fields: {...} } β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Backend Router β†’ Controller β”‚ +β”‚ - Parse request β”‚ +β”‚ - Extract JWT token from header β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Guard: AuthGuard β”‚ +β”‚ - Verify JWT token β”‚ +β”‚ - Attach user to request β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Guard: PermissionGuard β”‚ +β”‚ - Check if user can create records β”‚ +β”‚ - Check base/table permissions β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ DTO Validation β”‚ +β”‚ - class-validator validates DTO fields β”‚ +β”‚ - Type checking β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Service: RecordService β”‚ +β”‚ - Business logic execution β”‚ +β”‚ - Generate record ID (UUID) β”‚ +β”‚ - Apply default values β”‚ +β”‚ - Formula/computed field evaluation β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ ORM: Prisma β”‚ +β”‚ - Build INSERT statement β”‚ +β”‚ - Execute transaction β”‚ +β”‚ - Return created record β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Database: PostgreSQL β”‚ +β”‚ - Insert row in records table β”‚ +β”‚ - Apply constraints/triggers β”‚ +β”‚ - Return inserted data β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Cache Update (Redis) β”‚ +β”‚ - Update aggregate cache β”‚ +β”‚ - Invalidate related caches β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Event Bus β”‚ +β”‚ - Emit 'record:created' event β”‚ +β”‚ - Trigger webhooks β”‚ +β”‚ - Send notifications β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ WebSocket Broadcast β”‚ +β”‚ - ShareDB operation broadcast β”‚ +β”‚ - Custom event to all connected clients β”‚ +β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Frontend Update β”‚ +β”‚ - React state update β”‚ +β”‚ - Component re-render β”‚ +β”‚ - Display new record in grid β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 3.2 Filtrage et recherche de donnΓ©es + +``` +User Input: "Search: name contains 'John'" + └─→ Filter configuration + β”‚ + β”œβ”€β†’ Parse filter expression + β”‚ └─→ Field: "name" + β”‚ └─→ Operator: "contains" + β”‚ └─→ Value: "John" + β”‚ + β”œβ”€β†’ Build WHERE clause + β”‚ └─→ SQL: WHERE "name" ILIKE '%John%' + β”‚ + β”œβ”€β†’ Execute query + β”‚ └─→ Prisma findMany({ + β”‚ where: { name: { contains: 'John' } } + β”‚ }) + β”‚ + β”œβ”€β†’ Return filtered records + β”‚ + └─→ Update UI with results +``` + +### 3.3 AgrΓ©gation de donnΓ©es + +``` +User selects: Aggregate "price" by "category" β†’ SUM + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 1. Parse aggregation config β”‚ +β”‚ - Field: price β”‚ +β”‚ - Operation: SUM β”‚ +β”‚ - Group by: category β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 2. Build SQL query β”‚ +β”‚ SELECT category, β”‚ +β”‚ SUM(price) as total β”‚ +β”‚ FROM records β”‚ +β”‚ GROUP BY category β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 3. Check cache (Redis) β”‚ +β”‚ Key: agg:table:price:SUM:categoryβ”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + ↓ ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ CACHE β”‚ β”‚ Query DB β”‚ +β”‚ HIT β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”¬β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β””β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 4. Format results β”‚ +β”‚ { β”‚ +β”‚ Electronics: 5000, β”‚ +β”‚ Books: 1200, β”‚ +β”‚ Clothing: 800 β”‚ +β”‚ } β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 5. Return to frontend & update UI β”‚ +β”‚ Render aggregation chart/table β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## 4. Patterns et bonnes pratiques + +### 4.1 Repository Pattern + +```typescript +// Interface +interface IRecordRepository { + create(data: CreateRecordDto): Promise; + findById(id: string): Promise; + findAll(query: QueryDto): Promise; + update(id: string, data: UpdateRecordDto): Promise; + delete(id: string): Promise; +} + +// Implementation +@Injectable() +export class RecordRepository implements IRecordRepository { + constructor(private prisma: PrismaService) {} + + async create(data: CreateRecordDto): Promise { + return this.prisma.record.create({ + data: { + tableId: data.tableId, + fields: data.fields, + }, + }); + } + + // ... other methods +} + +// Usage in Service +@Injectable() +export class RecordService { + constructor(private recordRepository: RecordRepository) {} + + async createRecord(data: CreateRecordDto): Promise { + // Business logic + return this.recordRepository.create(data); + } +} +``` + +### 4.2 Dependency Injection + +```typescript +// NestJS built-in DI + +@Module({ + providers: [ + RecordService, + RecordRepository, + { + provide: 'DATABASE_CONNECTION', + useFactory: (configService: ConfigService) => { + return new PrismaService(configService); + }, + inject: [ConfigService], + }, + ], +}) +export class RecordModule {} + +// Using +@Injectable() +export class RecordService { + constructor( + private recordRepository: RecordRepository, + @Inject('DATABASE_CONNECTION') private db: PrismaService, + ) {} +} +``` + +### 4.3 Guard Pattern (Authorization) + +```typescript +// Custom Guard +@Injectable() +export class PermissionGuard implements CanActivate { + constructor(private permissionService: PermissionService) {} + + async canActivate(context: ExecutionContext): Promise { + const request = context.switchToHttp().getRequest(); + const user = request.user; + const baseId = request.params.baseId; + + return this.permissionService.hasAccess(user.id, baseId); + } +} + +// Usage on Controller +@Controller('bases/:baseId/records') +@UseGuards(AuthGuard('jwt'), PermissionGuard) +export class RecordController { + @Post() + async createRecord(@Param('baseId') baseId: string) { + // Only executed if guards pass + } +} +``` + +### 4.4 Interceptor Pattern (Logging/Transformation) + +```typescript +@Injectable() +export class LoggingInterceptor implements NestInterceptor { + intercept(context: ExecutionContext, next: CallHandler): Observable { + const now = Date.now(); + const request = context.switchToHttp().getRequest(); + + return next.handle().pipe( + tap(() => { + const time = Date.now() - now; + console.log(`${request.method} ${request.url} - ${time}ms`); + }), + catchError((err) => { + console.error(`Error in ${request.url}:`, err); + throw err; + }), + ); + } +} + +// Usage +@UseInterceptors(LoggingInterceptor) +@Controller('records') +export class RecordController { + // All requests logged +} +``` + +### 4.5 Pipe Pattern (Validation/Transformation) + +```typescript +@Injectable() +export class ParseUUIDPipe implements PipeTransform { + transform(value: string): string { + if (!isUUID(value)) { + throw new BadRequestException(`${value} is not a valid UUID`); + } + return value; + } +} + +// Usage +@Get(':id') +async getRecord(@Param('id', ParseUUIDPipe) id: string) { + return this.recordService.findById(id); +} +``` + +### 4.6 Strategy Pattern (Multiple implementations) + +```typescript +// Abstract strategy +interface AuthStrategy { + validate(token: string): Promise; +} + +// Implementations +@Injectable() +export class JwtStrategy implements AuthStrategy { + async validate(token: string): Promise { + return this.jwtService.verify(token); + } +} + +@Injectable() +export class ApiKeyStrategy implements AuthStrategy { + async validate(key: string): Promise { + return this.userService.findByApiKey(key); + } +} + +// Factory +@Injectable() +export class AuthFactory { + constructor( + private jwtStrategy: JwtStrategy, + private apiKeyStrategy: ApiKeyStrategy, + ) {} + + getStrategy(type: 'jwt' | 'api-key'): AuthStrategy { + return type === 'jwt' ? this.jwtStrategy : this.apiKeyStrategy; + } +} +``` + +--- + +## 5. DΓ©pendances critiques + +### 5.1 DΓ©pendances principales + +``` +Frontend: +β”œβ”€β”€ react@18.3.1 +β”‚ β”œβ”€β”€ react-dom@18.3.1 +β”‚ └── react-router-dom (navigation) +β”œβ”€β”€ next@16.1.3 +β”‚ β”œβ”€β”€ server-side rendering +β”‚ └── API routes +β”œβ”€β”€ @tanstack/react-query@5.x +β”‚ └── Server state management +β”œβ”€β”€ zustand@4.x +β”‚ └── Client state management +β”œβ”€β”€ tailwindcss@3.4.1 +β”‚ └── Utility-first CSS +β”œβ”€β”€ @radix-ui/* (UI primitives) +β”œβ”€β”€ glide-data-grid (Advanced grid) +β”œβ”€β”€ slate & plate.js (Rich text) +β”œβ”€β”€ react-hook-form (Form management) +└── sharedb@4.1.2 (Collaboration) + +Backend: +β”œβ”€β”€ @nestjs/core@10.3.5 +β”‚ β”œβ”€β”€ @nestjs/common +β”‚ β”œβ”€β”€ @nestjs/platform-express +β”‚ └── @nestjs/websockets +β”œβ”€β”€ prisma@6.2.1 +β”‚ β”œβ”€β”€ Database ORM +β”‚ └── Schema management +β”œβ”€β”€ @nestjs/passport (Authentication) +β”œβ”€β”€ passport-jwt (JWT strategy) +β”œβ”€β”€ class-validator (DTO validation) +β”œβ”€β”€ zod (Schema validation) +β”œβ”€β”€ bullmq (Job queue) +β”œβ”€β”€ ioredis (Redis client) +β”œβ”€β”€ pino (Logging) +β”œβ”€β”€ aws-sdk (S3/MinIO) +└── nestjs-i18n (Translation) + +Shared (Core): +β”œβ”€β”€ @teable/core +β”‚ β”œβ”€β”€ ANTLR4 (Formula parser) +β”‚ β”œβ”€β”€ TQL (Query language) +β”‚ └── Validators +β”œβ”€β”€ zod (Schema validation) +β”œβ”€β”€ typescript@5.4.3 +└── tslib (TypeScript utilities) +``` + +### 5.2 Conflits et compatibilitΓ©s + +| Package | Version | Notes | +|---------|---------|-------| +| React | 18.3.1+ | Requires Node 18+ | +| TypeScript | 5.4+ | Strict mode enabled | +| Prisma | 6.2+ | Requires migration | +| NestJS | 10.3+ | Compatible with Node 22 | +| ShareDB | 4.1+ | WebSocket required | + +--- + +## 6. Points d'intΓ©gration + +### 6.1 IntΓ©grations externes + +``` +Teable β”œβ”€β”€ OpenAI API (AI features) + β”œβ”€β”€ GitHub OAuth (Authentication) + β”œβ”€β”€ Google OAuth (Authentication) + β”œβ”€β”€ Email Service (Notifications) + β”œβ”€β”€ S3 / MinIO (File storage) + β”œβ”€β”€ Sentry (Error tracking) + β”œβ”€β”€ OpenTelemetry (Tracing) + └── Webhooks (External integrations) +``` + +### 6.2 Extension via plugins + +```typescript +// Plugin interface +interface Plugin { + load(): Promise; + unload(): Promise; + registerMenuItems?(): MenuItemConfig[]; + registerComponents?(): ComponentConfig[]; + registerHooks?(): HookConfig[]; +} + +// Plugin lifecycle +1. Discovery (scan plugin directories) +2. Load (execute plugin.load()) +3. Register (register extensions) +4. Activate (make available to users) +5. Unload (cleanup on deactivation) +``` + +### 6.3 Webhooks + +```typescript +// Webhook event payload +{ + id: 'webhook-123', + event: 'record.created', + timestamp: '2025-02-05T10:00:00Z', + data: { + recordId: 'rec-456', + tableId: 'tbl-789', + fields: { name: 'John', email: 'john@example.com' }, + createdBy: 'user-123', + }, + signatures: { + 'x-teable-signature': 'sha256=...', + } +} +``` + +--- + +## 7. Analyse des modules + +### 7.1 Module Backend: Authentication + +**Fichier**: `apps/nestjs-backend/src/features/auth/` + +**Flux**: +``` +Login Request + ↓ +Validate credentials (bcrypt comparison) + ↓ +Generate JWT token (expires in 7 days) + ↓ +Generate Refresh token (expires in 30 days) + ↓ +Store refresh token in database + ↓ +Return tokens to client + ↓ +Client stores JWT in localStorage/cookie + ↓ +Client sends JWT in Authorization header + ↓ +Backend validates JWT on each request +``` + +**StratΓ©gies**: +- Local (username/password) +- JWT (Bearer token) +- GitHub OAuth +- Google OAuth +- API Key + +### 7.2 Module Backend: Record Management + +**Fichier**: `apps/nestjs-backend/src/features/record/` + +**Services**: +- `RecordService` - CRUD operations +- `RecordFieldService` - Field-specific operations +- `RecordValidationService` - Validation logic +- `RecordAggregationService` - Aggregation queries + +**Key Operations**: +```typescript +// Create +POST /api/records { fields: {...} } + +// Read +GET /api/records?filter=...&sort=...&skip=0&limit=100 + +// Update +PATCH /api/records/:id { fields: {...} } + +// Delete (soft delete with Trash) +DELETE /api/records/:id + +// Batch operations +POST /api/records/batch { operations: [...] } + +// Undo/Redo +POST /api/records/:id/undo +POST /api/records/:id/redo +``` + +### 7.3 Module Backend: View Management + +**Fichier**: `apps/nestjs-backend/src/features/view/` + +**Types de vues**: +- Grid (table) +- Form (form entries) +- Kanban (card-based) +- Gallery (image grid) +- Calendar (date-based) + +**Chaque vue supporte**: +- Custom field visibility (viewFields) +- Filtering (viewFilters) +- Sorting (viewSorts) +- Grouping (viewGroups) +- View-specific options (colors, dimensions, etc.) + +### 7.4 Module Frontend: Grid Component + +**Fichier**: `apps/nextjs-app/src/modules/grid/` + +**Architecture**: +``` + + β”œβ”€ + β”‚ β”œβ”€ + β”‚ └─ + β”œβ”€ + β”‚ └─ (TanStack Virtual) + β”‚ └─ + β”‚ └─ + β”‚ β”œβ”€ + β”‚ β”œβ”€ + β”‚ β”œβ”€ + β”‚ └─ ... (field-specific editors) + β”œβ”€ + β”‚ β”œβ”€ + β”‚ β”œβ”€ + β”‚ └─ + └─ + └─ +``` + +**State Management**: +```typescript +// Zustand store +const gridStore = create((set) => ({ + selectedCells: [], + filteredRecords: [], + sortConfig: {}, + groupConfig: {}, + + setSelectedCells: (cells) => set({ selectedCells: cells }), + applyFilter: (filter) => set({ filteredRecords: [...] }), + applySort: (sort) => set({ sortConfig: sort }), + applyGroup: (group) => set({ groupConfig: group }), +})); +``` + +### 7.5 Module Frontend: Comment Thread + +**Fichier**: `apps/nextjs-app/src/modules/comment/` + +**Components**: +``` + + β”œβ”€ + β”‚ └─ + β”‚ β”œβ”€ + β”‚ β”œβ”€ + β”‚ β”œβ”€ + β”‚ └─ + β”‚ + └─ + β”œβ”€ + β”‚ └─ Mentions (@user) + └─ +``` + +**Real-time Sync**: +``` +User A writes comment + ↓ +POST /api/comments { recordId, text } + ↓ +Backend saves comment + ↓ +Emit WebSocket event: 'comment:created' + ↓ +All connected users receive event + ↓ +Re-render comment thread + ↓ +User B sees comment instantly +``` + +--- + +## Conclusion + +Cette analyse dΓ©taillΓ©e fournit une vision complΓ¨te de l'architecture de Teable. Comprendre ces patterns et flux est crucial pour: + +1. **Contribuer efficacement** - Savoir oΓΉ placer nouveau code +2. **DΓ©boguer rapidement** - Suivre le flux de donnΓ©es +3. **Optimiser les performances** - Identifier les goulots d'Γ©tranglement +4. **Maintenir la qualitΓ©** - Respecter les patterns Γ©tablis +5. **Scaler l'application** - Planifier les extensions + +--- + +**Document de rΓ©fΓ©rence technique** +**Version**: 1.0 +**DerniΓ¨re mise Γ  jour**: FΓ©vrier 2025 +**Statut**: Complet et validΓ© diff --git a/PROJECT_ANALYSIS_FR.md b/PROJECT_ANALYSIS_FR.md new file mode 100644 index 0000000000..52a0451d2e --- /dev/null +++ b/PROJECT_ANALYSIS_FR.md @@ -0,0 +1,1319 @@ +# Analyse du Projet Teable - Documentation ComplΓ¨te + +**Version**: 1.10.0 +**Date**: FΓ©vrier 2025 +**Licence**: AGPL-3.0 (Community Edition) / Enterprise Edition disponible + +--- + +## πŸ“‹ Table des matiΓ¨res + +1. [Vue d'ensemble du projet](#1-vue-densemble-du-projet) +2. [Architecture globale](#2-architecture-globale) +3. [Structure du monorepo](#3-structure-du-monorepo) +4. [Stack technologique](#4-stack-technologique) +5. [Modules et composants clΓ©s](#5-modules-et-composants-clΓ©s) +6. [Base de donnΓ©es](#6-base-de-donnΓ©es) +7. [Flux de dΓ©veloppement](#7-flux-de-dΓ©veloppement) +8. [Guide de dΓ©ploiement](#8-guide-de-dΓ©ploiement) +9. [Guide de dΓ©veloppement](#9-guide-de-dΓ©veloppement) +10. [IntΓ©grations et extensions](#10-intΓ©grations-et-extensions) + +--- + +## 1. Vue d'ensemble du projet + +### 1.1 Qu'est-ce que Teable ? + +Teable est une plateforme **no-code/low-code** qui fournit une interface de type feuille de calcul pour crΓ©er des applications de gestion de donnΓ©es puissantes. Elle permet aux utilisateurs de : + +- **GΓ©rer les donnΓ©es** de maniΓ¨re intuitive avec une interface spreadsheet-like +- **Collaborer en temps rΓ©el** avec leur Γ©quipe +- **Visualiser les donnΓ©es** selon plusieurs perspectives (Grid, Form, Kanban, Gallery, Calendar) +- **Automatiser les tΓ’ches** via des formules et plugins +- **Scaler Γ  des millions de lignes** avec de vraies performances + +### 1.2 Principes fondateurs + +La vision de Teable repose sur 7 principes clΓ©s : + +1. **Interface intuitive** - Interface spreadsheet familiΓ¨re accessible Γ  tous +2. **AccΓ¨s aux donnΓ©es ouvert** - PossibilitΓ© d'exporter/importer les donnΓ©es librement +3. **Vie privΓ©e des donnΓ©es** - Options cloud, on-premise, ou locale +4. **AdaptΓ© aux dΓ©veloppeurs** - Code ouvert, extensible, standard en industrie +5. **ScalabilitΓ©** - Performance constante mΓͺme avec des millions de lignes +6. **FlexibilitΓ© d'intΓ©gration** - Connecteurs multiples avec autres services +7. **IA native** - IntΓ©gration AI pour amΓ©liorer l'expΓ©rience utilisateur + +### 1.3 Cas d'usage typiques + +- **Gestion de projets** - Suivi des tΓ’ches, planning, ressources +- **CRM** - Gestion des clients et des opportunitΓ©s +- **Gestion d'inventaire** - Suivi des stocks, commandes +- **Applications mΓ©tier** - Collecte de donnΓ©es, reporting +- **Bases de connaissances** - Documentation collaborative +- **Automation** - Workflows et processus mΓ©tier + +--- + +## 2. Architecture globale + +### 2.1 Diagramme d'architecture + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ UTILISATEURS β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + HTTP/WebSocket + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ FRONTEND β”‚ β”‚ API REST/WS β”‚ + β”‚ Next.js β”‚ β”‚ NestJS Backend β”‚ + β”‚ React β”‚ β”‚ Port 3000 β”‚ + β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” + β”‚ ShareDB β”‚ β”‚ Prisma ORM β”‚ + β”‚ (Real- β”‚ β”‚ Schema Manager β”‚ + β”‚ time) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ + β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ + β”‚ β”‚ β”‚ + β”Œβ”€β”€β”€β”€β–Όβ”€β” β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β” + β”‚Redis β”‚ β”‚PostgreSQLβ”‚ β”‚ MinIO β”‚ + β”‚Cache β”‚ β”‚ Databaseβ”‚ β”‚ S3 Storage β”‚ + β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 2.2 Flux de donnΓ©es + +1. **RequΓͺte utilisateur** β†’ Frontend (Next.js) +2. **API Call** β†’ Backend (NestJS) +3. **Validation + Logique mΓ©tier** β†’ Backend +4. **Sauvegarde** β†’ Prisma β†’ PostgreSQL +5. **Real-time sync** β†’ ShareDB β†’ Frontend +6. **Mise Γ  jour UI** β†’ React components + +### 2.3 Couches applicatives + +#### **Couche PrΓ©sentation** +- Interface React avec Next.js +- Grid, Form, Kanban, Gallery, Calendar views +- Composants rΓ©utilisables (UI-lib) + +#### **Couche MΓ©tier** +- Logique de validation +- Formules et calculs (ANTLR4 parser) +- Gestion des permissions +- Traitement des requΓͺtes + +#### **Couche DonnΓ©es** +- ORM Prisma +- Migrations de schΓ©ma +- Caching Redis +- Stockage de fichiers (MinIO) + +--- + +## 3. Structure du monorepo + +### 3.1 Vue gΓ©nΓ©rale + +``` +teable/ +β”œβ”€β”€ apps/ # Applications +β”‚ β”œβ”€β”€ nextjs-app/ # Frontend React +β”‚ └── nestjs-backend/ # Backend API +β”‚ +β”œβ”€β”€ packages/ # Packages partagΓ©s +β”‚ β”œβ”€β”€ core/ # Logique mΓ©tier, formules +β”‚ β”œβ”€β”€ sdk/ # SDK client pour intΓ©grations +β”‚ β”œβ”€β”€ ui-lib/ # Composants UI rΓ©utilisables +β”‚ β”œβ”€β”€ db-main-prisma/ # SchΓ©ma DB et migrations +β”‚ β”œβ”€β”€ openapi/ # Documentation API +β”‚ β”œβ”€β”€ icons/ # IcΓ΄nes SVG +β”‚ β”œβ”€β”€ common-i18n/ # Traductions/i18n +β”‚ └── eslint-config-bases/ # Configuration ESLint +β”‚ +β”œβ”€β”€ plugins/ # Plugins extensibles +β”‚ +β”œβ”€β”€ dockers/ # Configuration Docker +β”œβ”€β”€ scripts/ # Scripts utilitaires +β”œβ”€β”€ static/ # Ressources statiques +└── Configuration files +``` + +### 3.2 DΓ©pendances entre packages + +``` +nextjs-app (Frontend) + β”œβ”€β”€ sdk (hooks, composants, client ShareDB) + β”œβ”€β”€ core (types, formules, validators) + β”œβ”€β”€ ui-lib (composants visuels) + β”œβ”€β”€ icons (icΓ΄nes) + β”œβ”€β”€ openapi (types API) + └── common-i18n (traductions) + +nestjs-backend (API) + β”œβ”€β”€ core (types, formules, validators) + β”œβ”€β”€ db-main-prisma (schΓ©ma DB) + β”œβ”€β”€ openapi (documentation API) + └── common-i18n (traductions) + +sdk + β”œβ”€β”€ core + β”œβ”€β”€ ui-lib + β”œβ”€β”€ icons + └── openapi + +ui-lib + β”œβ”€β”€ icons + └── common-i18n +``` + +### 3.3 StratΓ©gie de publication + +| Package | Licence | PubliΓ© | NPM | +|---------|---------|--------|-----| +| core | MIT | βœ“ | @teable/core | +| sdk | MIT | βœ“ | @teable/sdk | +| ui-lib | MIT | βœ“ | @teable/ui-lib | +| openapi | MIT | βœ“ | @teable/openapi | +| icons | MIT | βœ“ | @teable/icons | +| common-i18n | MIT | βœ“ | @teable/common-i18n | +| db-main-prisma | - | βœ— | - | +| nestjs-backend | AGPL | βœ— | - | +| nextjs-app | AGPL | βœ— | - | + +--- + +## 4. Stack technologique + +### 4.1 Frontend + +| Technologie | Version | Usage | +|-------------|---------|-------| +| **React** | 18.3.1 | Framework UI | +| **Next.js** | 16.1.3 | Framework fullstack | +| **TypeScript** | 5.4.3 | Langage de programmation | +| **Tailwind CSS** | 3.4.1 | Styling | +| **Radix UI** | Latest | Primitives UI | +| **TanStack Query** | 5.x | Gestion de cache/requΓͺtes | +| **TanStack Table** | Latest | Grille de donnΓ©es avancΓ©e | +| **TanStack Virtual** | Latest | Virtualisation de listes | +| **Zustand** | Latest | State management | +| **ShareDB** | 4.1.2 | Collaboration real-time | +| **Plate.js** | Latest | Rich text editor | +| **ECharts** | Latest | Visualisation graphiques | +| **Recharts** | Latest | Graphiques React | +| **Glide Data Grid** | Latest | Grid composant | +| **FullCalendar** | Latest | Calendrier | +| **react-hook-form** | Latest | Gestion formulaires | +| **Zod** | Latest | Validation de schΓ©mas | + +### 4.2 Backend + +| Technologie | Version | Usage | +|-------------|---------|-------| +| **Node.js** | >= 22.0.0 | Runtime | +| **TypeScript** | 5.4.3 | Langage de programmation | +| **NestJS** | 10.3.5 | Framework backend | +| **Express.js** | Via NestJS | Serveur HTTP | +| **Prisma** | 6.2.1 | ORM et migrations | +| **PostgreSQL** | 12+ | Base de donnΓ©es principale | +| **SQLite** | 3+ | Mode dΓ©veloppement | +| **Redis** | 6+ | Cache et sessions | +| **BullMQ** | Latest | Job queues | +| **Passport.js** | Latest | Authentification | +| **JWT** | Latest | Tokens d'authentification | +| **Pino** | Latest | Logging | +| **Zod** | Latest | Validation | +| **ANTLR4** | Latest | Parser formules | + +### 4.3 DevOps & Infrastructure + +| Technologie | Usage | +|-------------|-------| +| **Docker** | Containerisation | +| **Docker Compose** | Orchestration locale | +| **pnpm** 9.13.0 | Package manager | +| **GitHub Actions** | CI/CD | +| **MinIO** | S3-compatible storage | +| **Sentry** | Error tracking | +| **OpenTelemetry** | ObservabilitΓ© | +| **Coveralls** | Coverage tracking | +| **Vitest** | Unit testing | +| **Playwright** | E2E testing | +| **ESLint** | Linting | +| **Prettier** | Code formatting | + +### 4.4 Authentification & SΓ©curitΓ© + +- **JWT** pour API authentication +- **Passport.js** avec stratΓ©gies multiples + - Local (username/password) + - OAuth (GitHub, Google) + - Tokens d'accΓ¨s API +- **CORS** configurΓ© +- **Validation d'entrΓ©e** avec Zod +- **HTTPS** recommandΓ© pour production + +--- + +## 5. Modules et composants clΓ©s + +### 5.1 Backend - Modules principaux + +#### **Access Control Module** (`src/features/access`) +- Gestion des tokens d'accΓ¨s +- API keys management +- ContrΓ΄le d'accΓ¨s granulaire + +#### **Authentication Module** (`src/features/auth`) +- JWT authentication +- OAuth integration (GitHub, Google) +- Session management +- Password hashing (bcrypt) + +#### **Base Module** (`src/features/base`) +- Gestion des bases de donnΓ©es +- CrΓ©er, modifier, supprimer des bases +- Gestion des espaces (Space) +- Collaboration base-level + +#### **Table Module** (`src/features/table`) +- Gestion des tables +- MΓ©tadonnΓ©es des tables +- OpΓ©rations CRUD table + +#### **Field Module** (`src/features/field`) +- DΓ©finitions des types de champs +- Lookups et linked records +- Computed fields +- Field conversions + +#### **View Module** (`src/features/view`) +- Gestionnaires de vues multiples + - Grid View (tables classiques) + - Form View (formulaires) + - Kanban View (cards) + - Gallery View (images) + - Calendar View (Γ©vΓ©nements) +- Configurations de vues (filtres, tris, groupes) + +#### **Record Module** (`src/features/record`) +- OpΓ©rations CRUD enregistrements +- Batch operations +- Real-time updates via WebSocket + +#### **Aggregation Module** (`src/features/aggregation`) +- AgrΓ©gations (SUM, COUNT, AVG, etc.) +- Calculs groupΓ©s +- Statistiques + +#### **Comment Module** (`src/features/comment`) +- Comments sur enregistrements +- Mentions utilisateur +- Notifications de commentaires + +#### **Attachment Module** (`src/features/attachment`) +- Upload de fichiers +- Gestion de stockage (MinIO) +- Preview fichiers + +#### **Import/Export Module** (`src/features/import-export`) +- Import CSV/XLSX +- Export donnΓ©es +- Mapping de colonnes + +#### **Share Module** (`src/features/share`) +- Public shares +- Share links +- Permission management + +#### **Plugin Module** (`src/features/plugin`) +- Plugin management +- Plugin context menus +- Extension points + +#### **AI Features Module** (`src/features/ai`) +- AI-powered features +- Multiple AI provider support +- Prompt management + +#### **Notification Module** (`src/features/notification`) +- Email notifications +- Real-time notifications +- Notification preferences + +#### **Undo/Redo Module** (`src/features/operation`) +- OpΓ©rations CRUD tracking +- Undo/Redo stack +- Collaboration support + +### 5.2 Frontend - Composants principaux + +#### **Layout Components** +- `` - Layout principal +- `` - Navigation +- `
` - Barre supΓ©rieure +- `