Skip to content

Reference DSL

FieldTransform (t.xxx())

Chaque methode retourne une nouvelle instance immutable. Les transforms sont chainables et stockables dans des variables.

Semantique null/undefined : les transforms sautent les valeurs null/undefined sans erreur. Exceptions : t.default() remplace null/undefined, t.require() lance une erreur.

Transforms de valeur

MethodeDescriptionExemple
t.uppercase()Majuscules'martin' -> 'MARTIN'
t.lowercase()Minuscules'MARTIN' -> 'martin'
t.trim()Supprime les espaces' foo ' -> 'foo'
t.padStart(n, char)Padding a gauchet.padStart(13, '0') : '123' -> '0000000000123'
t.replace(regex, str)Remplacement regext.replace(/\s/g, '') : '01 23' -> '0123'
t.dateFormat('YYYY-MM-DD')Tronque ISO datetime'2024-01-15T12:00:00Z' -> '2024-01-15'
t.coerce('string')Conversion de type42 -> '42'
t.coerce('number')Conversion de type'42' -> 42
t.map(mapping)Mapping de valeurst.map({ 'A': 'B' }) : 'A' -> 'B'
t.edit(fn)Fonction customt.edit(v => v + '_suffix')

Default et validation

MethodeDescriptionExemple
t.default(value)Valeur par defaut si null/undefinedt.default('99100').apply(null) -> '99100'
t.require()Erreur si null/undefinedt.require().apply(null) -> throw

Transforms structurels

MethodeDescription
t.remove()Supprime la cle du payload
t.rename(newPath)Renomme la cle

Chainage et reutilisation

typescript
// Stocker un transform reutilisable
const cleanName = t.trim().uppercase()
const isoDate = t.dateFormat('YYYY-MM-DD')

// Composer : default puis nettoyage
const safeCode = t.default('  default  ').trim().uppercase()
safeCode.apply(null)       // 'DEFAULT'
safeCode.apply('  test  ') // 'TEST'

TransformBuilder (le t dans les callbacks)

Le t passe aux callbacks requestTransform / responseTransform est un TransformBuilder. Il fait double emploi :

  1. Creer des FieldTransforms : t.trim(), t.uppercase(), etc.
  2. Accumuler des operations : t.transform(), t.stripNulls(), etc.

Les operations s'executent dans l'ordre d'appel.

Operations sur un champ

MethodeDescription
t.transform(path, ft)Applique un FieldTransform au champ path
typescript
requestTransform: (t) => {
  t.transform('apprenti.nom', t.trim().uppercase())
  t.transform('contrat.dateDebut', t.dateFormat('YYYY-MM-DD'))
  t.transform('contrat.dureeHeures', t.coerce('string'))
}

Operations globales

MethodeDescription
t.stripNulls()Supprime toutes les cles dont la valeur est null
t.mapDeep(key, mapping)Mappe les valeurs d'une cle dans tout l'arbre
t.unwrap(key)Extrait data[key] comme nouveau root
t.spread(key)Merge data[key] dans le parent
t.editData(fn)Acces complet aux donnees (escape hatch)
typescript
responseTransform: (t) => {
  // Corriger les typos dans tous les champs 'etat'
  t.mapDeep('etat', { 'RUTPURE': 'RUPTURE', 'En cours': 'EN_COURS' })

  // Normaliser une reponse non paginee
  t.editData((data) => {
    if (!Array.isArray(data)) return data
    return { total: data.length, results: data }
  })
}

Operations pour routes composites

MethodeDescription
t.next(path)Stocke la valeur de path pour l'etape suivante
t.previous()FieldTransform qui resout vers la valeur passee par t.next()
typescript
defineCompositeRoute('/dossiers', 'POST', [
  {
    dest: '/v1/dossiers',
    responseTransform: (t) => { t.next('numeroInterneDossier') },
  },
  {
    dest: '/v1/conventions',
    requestTransform: (t) => {
      t.transform('numeroDossier', t.previous())
    },
  },
])

defineRoute

typescript
defineRoute(path, method, {
  dest: string | DestConfig,   // endpoint upstream
  destMethod?: 'GET' | 'POST', // override methode upstream
  cacheTtl?: number,           // TTL cache en secondes
  rateLimit?: { maxPerMinute: number },
  requestTransform?: (t: TransformBuilder) => void,
  responseTransform?: (t: TransformBuilder) => void,
})

dest accepte un string (JSON par defaut) ou un objet pour le multipart :

typescript
dest: {
  endpoint: '/v1/factures',
  format: 'multipart',
  multipart: { metadata: 'facture' },
}

defineProfile

typescript
defineProfile(id, {
  sync?: { batchSize: number },
  poll?: { intervalMs: number },
  routes: AnyRouteDefinition[],
})

Le profil est converti en ProfileAdapter qui implemente OpcoAdapter pour le pipeline.