@communecter/cocolight-api-client

1.0.37 • Public • Published

Cocolight API Client

Ce module fournit un client JavaScript prêt à l'emploi pour interagir avec l'API Cocolight. Il encapsule la gestion des appels HTTP, l'authentification, la validation des schémas, la gestion des erreurs, ainsi qu'un ensemble de normalisations des données pour simplifier l'intégration côté client.

📦 Installation

npm install @communecter/cocolight-api-client

🧭 Objectif

Ce client facilite l'intégration avec l'API Cocolight en offrant :

  • Des appels simplifiés avec axios
  • Un système de validation des entrées/sorties avec AJV
  • La gestion automatique du token d'accès et du token de rafraîchissement
  • Un circuit breaker configurable
  • Un logger intégré avec Pino
  • Des outils de transformation de données compatibles MongoDB/EJSON
  • La gestion des appels API à partir de métadonnées JSON (endpoints)

🧱 Architecture

Le projet est structuré autour des fichiers suivants :

src/
  ApiClient.js         # Client principal : logique d'appel, authentification, validation, transformation
  EJSONType.js         # Support pour les ObjectID MongoDB avec EJSON
  endpoints.module.js  # Fichier généré avec les définitions d'endpoints (voir ci-dessous)
  error.js             # Erreurs personnalisées (ApiClientError, CircuitBreakerError)
package.json           # Dépendances, scripts, métadonnées

imports

ESM

import Cocolight from "@communecter/cocolight-api-client";

const { Api, ApiClient, tokenStorageStrategy } = Cocolight;

CommonJS

const { ApiClient, Api, tokenStorageStrategy } = require("@communecter/cocolight-api-client").default;

🔗 Intégration via CDN

Vous pouvez inclure le client directement dans une page HTML :

<script src="https://cdn.jsdelivr.net/npm/@communecter/cocolight-api-client@latest/dist/cocolight-api-client.browser.js"></script>
<script>
  const client = new CocolightApiClient.ApiClient({
    baseURL: "https://www.communecter.org"
  });

client.callEndpoint("AUTHENTICATE_URL", {
        email: "EMAIL",
        password: "PASSWORD"
      }).then(res => {
          const { accessToken, refreshToken, user } = res.data;
          console.log("✅ Authentifié :", user.username);
        })
        .then(() => {
          return client.callEndpoint("ME_INFO_URL");
        })
        .then(res => {
          console.log("👤 Profil utilisateur :", res.data);
        })
        .then(() => {
          console.log("userId :", client.userId);
        })
      .catch(err => console.error("Erreur :", err));
</script>

🔧 Utilisation de base

import { ApiClient } from "@communecter/cocolight-api-client";

const client = new ApiClient({
  baseURL: "https://mon-api.com"
});

try {
    const authResponse = await client.callEndpoint("AUTHENTICATE_URL", {
      email: "EMAIL",
      password: "PASSWORD"
    });

    const { accessToken, refreshToken, user } = authResponse.data;

    console.log("✅ Authentifié :", user.username);

    const meResponse = await client.callEndpoint("ME_INFO_URL");

    console.log("👤 Profil utilisateur :", meResponse.data);

    console.log("userId :", client.userId);
  } catch (error) {
    console.error("❌ Erreur durant la session :", error.message, error.details);
  }

📜 API détaillée

new ApiClient(options)

Option Type Description
baseURL (requis) string URL de base de l'API
accessToken string Token d'accès initial
refreshToken string Token de rafraîchissement
refreshUrl string URL pour rafraîchir le token (défaut : /api/cocolight/refreshtoken)
endpoints Array Liste des endpoints (par défaut : endpoints.module.js)
timeout number Timeout en ms (défaut : 30000)
debug boolean Active le logger debug (défaut : false)
maxRetries number Nombre de tentatives max (défaut : 0)
circuitBreakerThreshold number Seuil d'erreurs avant blocage (défaut : 5)
circuitBreakerResetTime number Délai de réactivation (en ms, défaut : 60000)
fromJSONValue boolean Applique EJSON.fromJSONValue sur les réponses (défaut : true)

Méthodes principales

callEndpoint(constant, data, transform, validate)

Effectue un appel à un endpoint défini via endpoints.module.js.

  • constant: nom unique du endpoint
  • data: objet avec pathParams et données du corps
  • transform: true (par défaut), false, ou fonction de transformation
  • validate: true (par défaut), permet de valider la réponse via AJV

setToken(token) / getToken()

Gère le token d'accès.

setRefreshToken(rt) / getRefreshToken()

Gère le token de rafraîchissement.

resetSession()

Réinitialise la session utilisateur.

Événements

  • refreshSuccess — déclenché après un rafraîchissement réussi
  • validationError — déclenché si AJV détecte des erreurs
  • sessionReset — déclenché par resetSession()

🛠️ Scripts disponibles

Depuis package.json :

  • npm run test — Lance les tests via Jest
  • npm run exemple — Lance un exemple
  • npm run lint / lint:fix — Vérifie et corrige le code avec ESLint
  • npm run build — Génère les builds navigateur + Node via Webpack
  • npm run generate:* — Génère les modules, documentation ou données de test depuis les fichiers JSON d’API

🧩 Dépendances principales

  • axios & axios-retry — pour les appels HTTP robustes
  • ajv & ajv-formats — pour la validation JSON Schema
  • ejson — pour la compatibilité MongoDB (ObjectID, dates...)
  • pino — logger performant, compatible navigateur
  • events — pour la gestion des événements custom côté client

🗃️ Format des endpoints

Chaque endpoint dans endpoints.module.js suit le schéma :

{
  constant: "GET_USER_INFO",
  method: "GET",
  path: "/api/users/{userId}",
  auth: "bearer",
  pathParams: { type: "object", properties: { userId: { type: "string" } }, required: ["userId"] },
  request: { ...schemaAjv },
  responses: { "200": { ...schemaAjv } },
  postActions: [
    { type: "setToken", path: "accessToken" },
    { type: "setUserId", path: "user._id" }
  ]
}

🔒 Sécurité et circuit breaker

Un circuit breaker est intégré :

  • Blocage temporaire après trop d’échecs (circuitBreakerThreshold)
  • Réactivation après un délai (circuitBreakerResetTime)
  • Journalisation complète avec pino

🧪 Validation AJV

Chaque appel est validé avant (requête) et après (réponse) via AJV. En cas d’erreur, l’événement validationError est déclenché avec les détails.

🔄 Rafraîchissement automatique

Si une réponse retourne 401, le client tente automatiquement un appel POST vers refreshUrl avec le refreshToken, et réessaie l’appel initial si réussi.

🧼 Transformation des données

Les réponses sont normalisées :

  • Champs dates, images, IDs MongoDB
  • Structures communes comme results, news, notif, replies, etc.
  • Conversion EJSON via EJSON.fromJSONValue()

🧙 Valeurs dynamiques

Dans les données pathParams, il est possible d’utiliser des alias dynamiques :

pathParams: {
  userId: "@userId",
  accessToken: "@accessToken"
}

🎩 API de façade : Api

La classe Api fournit une interface unifiée pour gérer les utilisateurs, organisations, projets et actualités. Elle encapsule les appels à ApiClient et permet de manipuler les entités comme des objets métier avec des méthodes pratiques.

🧪 Authentification

Api.userLogin(email, password, options)

Crée une instance d’Api authentifiée.

const api = await Api.userLogin("john@doe.com", "password123", { baseURL: "https://api.monapp.com" });
const user = await api.me();

Api.userApi(options)

Retourne une instance UserApi si tu veux gérer manuellement l’authentification :

const userApi = Api.userApi({ baseURL: "..." });
const user = await userApi.login("email", "mdp");

🔐 Session et utilisateur courant

api.me()

Retourne l'utilisateur actuellement connecté (User).

const user = await api.me();
console.log(user.data.email);

👤 Utilisateurs

api.user(userData)

Crée une instance User (autre que le connecté).

const otherUser = await api.user({ slug: "caroline" });
console.log(otherUser.data.description);

🏛️ Organisations

api.organization({ id | slug })

Retourne une instance d’Organization. Récupère automatiquement le profil public.

const orga = await api.organization({ slug: "asso-verte" });
console.log(orga.data.name);

🏗️ Projets

api.project({ id | slug })

Retourne une instance Project. Récupère automatiquement le profil public.

const projet = await api.project({ id: "647..." });

📦 Entités métiers

Les entités suivantes partagent une API commune grâce aux mixins : User, Organization, Project, News.

Propriétés

Propriété Description
data Proxy combiné serverData + draftData
draftData Données modifiables avant save()
initialDraftData Snapshot initial pour détection des changements
serverData Dernières données serveur
isConnected Vrai si ApiClient a un token
userId ID de l'utilisateur connecté
isMe Vrai si l'entité correspond à l'utilisateur courant

Méthodes génériques

entity.save()

Sauvegarde les données via les blocs modifiés (UPDATE_BLOCK_*, ADD_*).

entity.refresh()

Recharge les données depuis le serveur.

entity.hasChanges()

Retourne true si le draft est différent du snapshot initial.


✏️ Méthodes d’édition (communes à toutes les entités)

Méthode Description
updateDescription Met à jour les champs shortDescription, description, descMentions
updateInfo Nom, email, téléphone, etc.
updateSocial Réseaux sociaux (Facebook, GitHub...)
updateLocality Adresse, géolocalisation
updateSlug Slug de l’URL
updateImageProfil Upload de l’avatar

📰 Actualités (News)

Créées à partir d’un User, Organization ou Project.

Création

const news = await orga.news();
news.data.text = "Nouvelle actu !";
await news.save();

Gestion

Méthode Description
addMention({ slug | id }) Ajoute une mention à la news
addImage(file) Ajoute une image (via validation MIME)
addFile(file) Ajoute un fichier (PDF, CSV...)
delete() Supprime la news
refresh() Recharge la news
get() Récupère les données à partir de l’ID

🔄 Utilisation des schémas de validation (AJV)

Toutes les entités sont basées sur les constantes de schéma :

  • ADD_*
  • UPDATE_BLOCK_*
  • PROFIL_IMAGE

Ces constantes sont mappées automatiquement pour les appels save(), updateX(), etc.


✅ Exemple : mise à jour d’un projet

const projet = await api.project({ slug: "bio-bazar" });
projet.data.description = "Nouveau descriptif de mon projet.";
if (projet.hasChanges()) {
  await projet.save();
}

👤 API : Utilisateur (User)

Une instance User offre un ensemble de méthodes métier pour interagir avec les projets, organisations et actualités de l’utilisateur.


🔍 Chargement

const user = await api.user({ slug: "caroline" });
await user.get();

🏭 Création d'entités depuis User

Un utilisateur peut créer :

➕ Organisation

const orga = await user.organization({ name: "Ma nouvelle asso" });
await orga.save(); // appelle ADD_ORGANIZATION puis rafraîchit les données

➕ Projet

const projet = await user.project({ name: "Mon projet citoyen" });
await projet.save(); // appelle ADD_PROJECT

➕ Actualité

const news = await user.news({ text: "Hello world 🌍" });
await news.save(); // appelle ADD_NEWS

📦 Récupération des projets de l'utilisateur

user.getProjects()

Retourne la liste des projets créés ou co-administrés par l’utilisateur.

const { results: projets } = await user.getProjects();
console.log("Projets liés à l'utilisateur :", projets.map(p => p.data.name));

🧑‍🤝‍🧑 Récupération des organisations de l'utilisateur

user.getOrganizations()

Retourne les organisations où il est membre (admin ou non).

const { results: orgs } = await user.getOrganizations();
console.log("Organisations :", orgs.map(o => o.data.name));

📰 Actualités associées

user.getNews()

Retourne toutes les actualités liées à l’utilisateur.

const newsList = await user.getNews({ indexStep: 5 });

user.news(newsData)

Crée une nouvelle actualité, ou charge une existante si id est fourni.

const actu = await user.news({ text: "Ceci est une nouvelle actu" });
await actu.save();

⚙️ Mise à jour du profil utilisateur

Les méthodes updateX disponibles sont :

  • updateDescription(data)
  • updateInfo(data)
  • updateSocial(data)
  • updateLocality(data)
  • updateSlug({ slug })
  • updateImageProfil({ profil_avatar })
  • updateSettings({ type, value })

🔑 Sécurité et gestion de compte

Modifier mot de passe

await user.changePassword({
  oldPassword: "secret1",
  newPassword: "secret2",
  newPassword2: "secret2"
});

Supprimer son compte

await user.delete({ reason: "Je souhaite quitter la plateforme" });

Licence

MIT

👤 Auteur

Thomas Craipeau

Package Sidebar

Install

npm i @communecter/cocolight-api-client

Weekly Downloads

372

Version

1.0.37

License

MIT

Unpacked Size

2.2 MB

Total Files

52

Last publish

Collaborators

  • aboire