npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lerma-corps/gestion-scolaire-client-ts

v1.0.0

Published

Client JavaScript basé sur Axios pour l'API Gestion Scolaire.

Downloads

191

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 install

Exécution des tests :

npm test

Import 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 :

  • message
  • httpStatus
  • exception
  • fieldErrors
  • status
  • headers
  • data
  • cause
  • raw

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.js et createApiClient, incluant les domaines quarters, sequences, courseAllocations et notes.
  • 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 pour UserAccountDto.
  • 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ête X-SCHOOL-ID n'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 TeacherUpdateRestRequest avec additionalProperties: true. La librairie transmet donc le payload sans normalisation supplémentaire.