@lerma-corps/gestion-scolaire-client-ts
v1.0.0
Published
Client JavaScript basé sur Axios pour l'API Gestion Scolaire.
Downloads
191
Maintainers
Readme
gestin-scolaire-client-ts
Client JavaScript basé sur Axios pour l'API Gestion Scolaire.
L'objectif de cette librairie est de fournir une factory unique, createApiClient(config), qui centralise l'instance HTTP, applique les interceptors communs, expose les services métier réellement implémentés et rend les enums métier disponibles côté frontend.
Installation
Le dépôt est actuellement configuré comme package privé et ne déclare pas encore de point d'entrée package via main ou exports. L'entrée publique réellement implémentée est src/index.js.
Installation locale des dépendances du dépôt :
npm installExécution des tests :
npm testImport de l'API publique depuis ce dépôt :
import {
createApiClient,
Gender,
UserRole,
SequenceStatus,
SchoolCycle,
SchoolSection,
ActivityName,
} from './src/index.js';API publique
Le point d'entrée public est createApiClient(config).
La factory retourne un objet avec :
| Propriété | Description |
| --- | --- |
| http | Instance Axios centralisée utilisée par tous les services. |
| services | Regroupement des services publics (schools, accounts, students, teachers, academicYears, quarters, sequences, courseAllocations, notes). |
| schools | Alias direct de services.schools. |
| accounts | Alias direct de services.accounts. |
| students | Alias direct de services.students. |
| teachers | Alias direct de services.teachers. |
| academicYears | Alias direct de services.academicYears. |
| quarters | Alias direct de services.quarters. |
| sequences | Alias direct de services.sequences. |
| courseAllocations | Alias direct de services.courseAllocations. |
| notes | Alias direct de services.notes. |
| enums | Namespace regroupant les enums exportés par src/models/enums.js. |
Initialisation avec createApiClient
import { createApiClient } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
timeout: 10000,
headers: {
'X-CLIENT-APP': 'web-frontend',
},
});Comportement de base :
| Option | Type | Comportement |
| --- | --- | --- |
| baseURL | string | Obligatoire. |
| token | string | Token statique utilisé si getToken() n'est pas fourni. |
| getToken | () => string \| null \| undefined | Prioritaire sur token. |
| getSchoolId | () => string \| number \| null \| undefined | Utilisé uniquement pour les opérations marquées comme nécessitant X-SCHOOL-ID. |
| timeout | number | Timeout Axios optionnel en millisecondes (défaut: 30000). |
| headers | Record<string, string> | En-têtes globaux additionnels appliqués à l'instance Axios. |
| debug | boolean | Mode debug pour logger les requêtes/réponses dans la console (défaut: false). |
| retry | Object | Configuration du retry logic pour les erreurs temporaires. |
| retry.maxRetries | number | Nombre maximum de tentatives (défaut: 0, désactivé). |
| retry.delayMs | number | Délai initial entre les tentatives en ms (défaut: 1000). |
| retry.backoffMultiplier | number | Multiplicateur pour backoff exponentiel (défaut: 2). |
| onError | (error) => void | Hook appelé lors d'une erreur pour logging ou traitement personnalisé. |
Exemple avec retry logic et debug
import { createApiClient } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
getToken: () => localStorage.getItem('access_token'),
debug: true,
retry: {
maxRetries: 3,
delayMs: 1000,
backoffMultiplier: 2,
},
onError: (error) => {
console.error('API Error:', error.message, 'Status:', error.httpStatus);
},
});
// Les requêtes échouant avec des erreurs 5xx seront automatiquement retentées
// avec un délai exponentiel : 1s, 2s, 4s...
const school = await client.schools.getSchoolById(12);Configuration avec token statique
import { createApiClient } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
token: 'jwt-static-token',
});
const school = await client.schools.getSchoolById(12);Si token est défini et qu'aucun getToken() n'est fourni, les requêtes partent avec Authorization: Bearer <token>.
Configuration avec getToken()
import { createApiClient } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
token: 'fallback-token',
getToken: () => localStorage.getItem('access_token'),
});
const accounts = await client.accounts.listAccounts();getToken() est prioritaire sur token. Si aucun token n'est disponible, l'en-tête Authorization n'est pas envoyé.
Configuration avec getSchoolId()
import { createApiClient } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
getToken: () => localStorage.getItem('access_token'),
getSchoolId: () => sessionStorage.getItem('school_id'),
});
const teacherUpdatePayload = {
// TeacherUpdateRestRequest est souple dans la spec.
// Transmettez ici les champs attendus par votre backend.
};
await client.teachers.updateTeacher(7, teacherUpdatePayload);Dans l'API publique actuellement implémentée, X-SCHOOL-ID est injecté pour client.teachers.updateTeacher(id, payload) et client.quarters.createQuarter(payload) lorsque getSchoolId() retourne une valeur non nulle.
Pagination
Les services paginés actuellement exposés sont :
client.students.pageStudents({ page, size, sort })client.teachers.pageTeachers({ page, size, sort })client.academicYears.pageAcademicYears({ page, size, sort })
Exemple :
import { createApiClient } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
getToken: () => localStorage.getItem('access_token'),
});
const page = await client.students.pageStudents({
page: 0,
size: 20,
});Les paramètres undefined, null et les chaînes vides sont filtrés avant envoi.
Exemple de création d'entité
Exemple avec createAccount, en utilisant les noms de champs réellement définis dans la spec UserAccountDto :
import { createApiClient, Gender, UserRole } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
getToken: () => localStorage.getItem('access_token'),
});
const createdAccount = await client.accounts.createAccount({
username: 'ada.lovelace',
email: '[email protected]',
first_name: 'Ada',
last_name: 'Lovelace',
role: UserRole.ADMIN,
gender: Gender.FEMALE,
matricule: 'ADM-001',
phone_number: '+237600000000',
picture_url: 'https://cdn.example.com/users/ada.jpg',
});Autres méthodes de création actuellement exposées :
client.schools.createSchool(payload)client.accounts.createStudentAccount(payload)client.accounts.createTeacherAccount(payload)client.academicYears.createAcademicYear(payload)client.quarters.createQuarter(payload)client.courseAllocations.createCourseAllocation(payload)client.notes.createSequenceNote(payload)
Exemple de téléchargement PDF
downloadSchoolReport(year, quarter) appelle /api/v1/schools/reports/{year}/{quarter} avec responseType: 'blob' et retourne directement response.data.
Exemple navigateur :
import { createApiClient } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
getToken: () => localStorage.getItem('access_token'),
});
const pdfBlob = await client.schools.downloadSchoolReport(2026, 2);
const pdfUrl = URL.createObjectURL(pdfBlob);
window.open(pdfUrl, '_blank', 'noopener,noreferrer');Services exportés
Les services publics sont accessibles à la fois via client.services et via des alias directs sur client.
| Service | Méthodes réellement exposées |
| --- | --- |
| schools | createSchool(payload), getSchoolById(id), downloadSchoolReport(year, quarter) |
| accounts | listAccounts(params), createAccount(payload), getAccountById(id), updateAccount(id, payload), deleteAccount(id), createStudentAccount(payload), createTeacherAccount(payload) |
| students | pageStudents(params), listStudents(), countStudents(), getStudentById(id), updateStudent(id, payload), deleteStudent(id) |
| teachers | pageTeachers(params), listTeachers(), countTeachers(), getTeacherById(id), updateTeacher(id, payload), deleteTeacher(id) |
| academicYears | pageAcademicYears(params), createAcademicYear(payload), listAcademicYears(), countAcademicYears(), getAcademicYearById(id), updateAcademicYear(id, payload), deleteAcademicYear(id) |
| quarters | createQuarter(payload), changeQuarterStatus(id, status) |
| sequences | searchSequences(params) |
| courseAllocations | searchCourseAllocations(params), createCourseAllocation(payload) |
| notes | listSequenceNotes(), createSequenceNote(payload) |
Enums exportés
Les enums sont exportés de deux façons :
- en exports nommés depuis
src/index.js - dans
client.enums
| Enum | Valeurs |
| --- | --- |
| Gender | MALE, FEMALE |
| UserRole | ADMIN, TEACHER, STUDENT, DIRECTOR |
| SequenceStatus | CLOSED, CREATED, EXPIRED, IN_PROGRESS, TERMINATED |
| SchoolCycle | FIRST_CYCLE, SECOND_CYCLE |
| SchoolSection | ANGLOPHONE, FRANCOPHONE |
| ActivityName | ACTIVITY_1, ACTIVITY_2, ACTIVITY_3, ACTIVITY_4 |
Exemple :
import { createApiClient, UserRole } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
});
if (UserRole.ADMIN === 'ADMIN') {
console.log(client.enums.UserRole.ADMIN);
}Gestion des erreurs
Les interceptors de réponse retournent response.data par défaut et homogénéisent les erreurs Axios dans un format commun. Les promesses rejetées remontent une erreur dont name vaut ApiClientError avec les propriétés utiles suivantes selon les données disponibles :
messagehttpStatusexceptionfieldErrorsstatusheadersdatacauseraw
Exemple de gestion d'erreur
import { createApiClient } from './src/index.js';
const client = createApiClient({
baseURL: 'https://api.example.com',
getToken: () => localStorage.getItem('access_token'),
});
try {
const school = await client.schools.getSchoolById(999);
} catch (error) {
console.error('Erreur API:', error.message);
console.error('Statut HTTP:', error.httpStatus);
console.error('Données:', error.data);
if (error.httpStatus === 404) {
// Gérer le cas "non trouvé"
} else if (error.httpStatus >= 500) {
// Erreur serveur - peut être retry automatiquement si configuré
}
}Hook onError global
Vous pouvez définir un hook onError lors de l'initialisation pour centraliser la gestion des erreurs :
const client = createApiClient({
baseURL: 'https://api.example.com',
onError: (error) => {
// Logging centralisé
console.error('[API Error]', error.httpStatus, error.message);
// Déconnexion automatique en cas de 401
if (error.httpStatus === 401) {
localStorage.removeItem('access_token');
window.location.href = '/login';
}
},
});Limites connues et hypothèses conservatrices
- Ce README documente l'API réellement exportée aujourd'hui par
src/index.jsetcreateApiClient, incluant les domainesquarters,sequences,courseAllocationsetnotes. - Le dépôt n'est pas encore câblé comme package consommable via un import bare specifier. L'entrée publique réelle est
src/index.js. - Les payloads ne sont pas normalisés côté client. Les noms de propriétés doivent suivre la spec OpenAPI telle quelle, y compris lorsqu'elle emploie du
snake_case, par exemple pourUserAccountDto. - Les réponses sont renvoyées telles que fournies par
response.data. La librairie n'ajoute pas de transformation métier frontend. getSchoolId()n'est pas injecté globalement sur toutes les requêtes. L'en-têteX-SCHOOL-IDn'est ajouté que pour les opérations explicitement marquées comme le nécessitant.- Certains schémas de mise à jour dans la spec sont souples, par exemple
TeacherUpdateRestRequestavecadditionalProperties: true. La librairie transmet donc le payload sans normalisation supplémentaire.
