Skip to content

Profils OPCO

Qu'est-ce qu'un profil ?

Un profil est une description declarative de la maniere dont l'API d'un OPCO differe du schema normalise Opcovia. Chaque OPCO a ses particularites : fautes de frappe dans les enums, formats de date differents, champs obligatoires supplementaires, wrappers autour des reponses, etc.

Au lieu d'ecrire un adapter TypeScript par OPCO, on declare un profil avec le DSL. Le profil est un ensemble de routes, chacune associant un endpoint Opcovia a un endpoint upstream avec ses transforms.

Pourquoi des profils ?

Chaque OPCO expose une API differente. Exemples de divergences reelles :

ProblemeExemple OPCO EP
Typos dans les enumsRUTPURE au lieu de RUPTURE
Format de date non standardISO datetime au lieu de YYYY-MM-DD
Noms en majuscules exigesapprenti.nom doit etre uppercase
Crash sur nullL'API plante si un champ est null
Reponse non pagineeArray brut au lieu d'un objet pagine
Durees en stringHeures/minutes attendues comme string, pas number

Le profil absorbe ces differences. Le code metier ne les voit jamais.

Architecture

                        Profil OPCO
                     ┌──────────────────┐
                     │  defineProfile()  │
                     │  ├── route GET    │
                     │  ├── route POST   │
                     │  └── ...          │
                     └──────────────────┘


                       ProfileAdapter
                      (implements OpcoAdapter)

Flux request

Corps JSON client


  requestOps[]          t.transform('nom', cleanName)
  (appliques            t.stripNulls()
   sequentiellement)


  Corps JSON OPCO  →  envoi a l'API upstream

Flux response

Reponse JSON OPCO


  responseOps[]         t.mapDeep('etat', corrections)
  (appliques            t.editData(normaliserPagination)
   sequentiellement)


  Reponse normalisee  →  renvoyee au client

Pipeline de transformation DSL

Concepts cles

defineRoute

Definit une route simple : un endpoint Opcovia mappe a un endpoint upstream.

typescript
defineRoute('/dossiers', 'POST', {
  dest: '/v1/dossiers',
  cacheTtl: 600,
  rateLimit: { maxPerMinute: 60 },
  requestTransform: (t) => { /* ops sur la requete */ },
  responseTransform: (t) => { /* ops sur la reponse */ },
})

defineCompositeRoute

Definit une route composite : plusieurs appels upstream enchaines, avec passage de donnees entre etapes via t.next() / t.previous().

defineProfile

Assemble les routes en un profil complet.

typescript
defineProfile('opco-ep', {
  sync: { batchSize: 50 },
  poll: { intervalMs: 300_000 },
  routes: [routeGet, routePost, ...],
})

FieldTransform (t.xxx())

Transforms chainables et immutables sur une valeur. Stockables dans des variables pour reutilisation.

typescript
const cleanName = t.trim().uppercase()
// reutilisable sur N champs
t.transform('apprenti.nom', cleanName)
t.transform('apprenti.prenom', cleanName)

Structure des fichiers

profiles/
  field-transform.ts     — FieldTransform chainable + factory t
  dsl.ts                 — defineRoute, defineProfile, TransformBuilder
  engine.ts              — applyOps() execute les operations
  adapter.ts             — ProfileAdapter implements OpcoAdapter
  types.ts               — Op, RouteDefinition, ProfileDefinition
  opco-ep/               — 1 fichier par route
  opco-mock/             — profil mock pour les tests
  __tests__/             — tests unitaires et integration

Voir aussi