# Normes
Note : Ces normes ne sont en aucun cas figĂ©es dans le marbre ; en tant que communautĂ©, nous souhaitons toujours les faire Ă©voluer et amĂ©liorer Mojaloop. Pour proposer une modification de ces normes ou suggĂ©rer des amĂ©liorations supplĂ©mentaires, nâhĂ©sitez pas Ă contacter le canal Design Authority sur le Slack Mojaloop (#design-authority).
# Invariants Mojaloop
Mojaloop définit des invariants importants à comprendre et à respecter lorsque vous contribuez à la base de code.
Ces invariants dĂ©coulent des principes Level One (opens new window) et dâautres exigences mĂ©tier telles quâarrĂȘtĂ©es par le conseil de gouvernance technique Mojaloop, le comitĂ© de contrĂŽle des changements dâAPI, la Design Authority et le conseil produit. Ils visent Ă ce que la plateforme conserve des caractĂ©ristiques adaptĂ©es Ă une exploitation de type infrastructure nationale.
Assurez-vous de connaĂźtre ces invariants avant de contribuer.
# Environnement dâexĂ©cution
Les normes dâexĂ©cution suivantes sâappliquent Ă Mojaloop.
# Microservices et bibliothĂšques
Javascript
NodeJS est lâenvironnement dâexĂ©cution standard pour tous les services et composants Mojaloop pour lâexĂ©cution des fichiers de code source Javascript.
Notre objectif est que tous les services NodeJS tournent sur la derniĂšre version
Active LTS(Long Time Support) de NodeJS, conformĂ©ment au cycle de release NodeJS (opens new window).Conteneur (Docker) et systĂšme dâexploitation (OS)
Les microservices Mojaloop sont construits Ă partir de lâimage de base
node:<NODE_ACTIVE_LTS_VERSION>-alpine, oĂčNODE_ACTIVE_LTS_VERSIONest la LTS NodeJS courante selon le cycle de release NodeJS (opens new window). Voir DockerHub (opens new window) pour la liste des images officielles Node Alpine.NOTE : pour
NODE_ACTIVE_LTS_VERSION, utilisez la version sémantique complÚte<MAJOR>-<MINOR>-<PATCH>.node:16.15.0-alpine<-- correctlts-alpine3.16<-- incorrectExemple de
DockerfileJavascript standard :FROM node:<NODE_ACTIVE_LTS_VERSION>-alpine as builder WORKDIR /opt/app RUN apk --no-cache add git RUN apk add --no-cache -t build-dependencies make gcc g++ python3 libtool libressl-dev openssl-dev autoconf automake \ && cd $(npm root -g)/npm \ && npm config set unsafe-perm true \ && npm install -g node-gyp COPY package*.json /opt/app/ RUN npm ci --production FROM node:<NODE_ACTIVE_LTS_VERSION>-alpine WORKDIR /opt/app # Create empty log file & link stdout to the application log file RUN mkdir ./logs && touch ./logs/combined.log RUN ln -sf /dev/stdout ./logs/combined.log # Create a non-root user: ml-user RUN adduser -D ml-user USER ml-user # Copy builder artefact COPY /opt/app . # Copy source files COPY src /opt/app/src # Copy default config COPY config /opt/app/config EXPOSE <PORT> CMD ["npm", "run", "start"]Exemple de
DockerfileTypescript standard :FROM node:<NODE_ACTIVE_LTS_VERSION>-alpine as builder USER root WORKDIR /opt/app RUN apk update \ && apk add --no-cache -t build-dependencies git make gcc g++ python3 libtool autoconf automake openssh \ && cd $(npm root -g)/npm \ && npm config set unsafe-perm true \ && npm install -g node-gyp COPY package.json package-lock.json* ./ RUN npm ci FROM node:<NODE_ACTIVE_LTS_VERSION>-alpine WORKDIR /opt/app # Create empty log file & link stdout to the application log file RUN mkdir ./logs && touch ./logs/combined.log RUN ln -sf /dev/stdout ./logs/combined.log # Create a non-root user: ml-user RUN adduser -D ml-user USER ml-user # Copy builder artefact COPY /opt/app ./ COPY src /opt/app/src COPY config /opt/app/config # NPM script to build source (./src) to destination (./dist) RUN npm run build # Prune devDependencies RUN npm prune --production # Prune source files RUN rm -rf src EXPOSE <PORT> CMD ["npm", "run", "start"]
# Pipelines CI (Intégration Continue)
Les jobs CI Mojaloop sâexĂ©cutent sur la version Ubuntu LTS courante selon le cycle de release Ubuntu (opens new window).
# Kubernetes
Les charts Helm Mojaloop (mojaloop/helm (opens new window), mojaloop/charts (opens new window)) sont déployés et vérifiés sur la version Kubernetes LTS courante selon le cycle de release Kubernetes (opens new window).
# Guide de style
La communauté Mojaloop fournit des lignes directrices pour le style de code. Elles contribuent à maintenir une base de code de qualité, maintenable et cohérente.
Ces guides sont choisis car ils peuvent ĂȘtre appliquĂ©s et vĂ©rifiĂ©s avec des outils courants et peu de personnalisation. Bien que nous reconnaissions que les dĂ©veloppeurs ont des prĂ©fĂ©rences personnelles pouvant entrer en conflit avec ces rĂšgles, nous privilĂ©gions la cohĂ©rence au bike-shedding (opens new window).
Lâobjectif est de faciliter le flux de travail des dĂ©veloppeurs et de rĂ©duire les commits dont les changements sont motivĂ©s par le seul style plutĂŽt que par le fond. En rĂ©duisant le bruit dans les diffs, on facilite le travail des relecteurs.
# Style de code
# Conventions de nommage
Pour éviter toute confusion et garantir la cohérence des conventions entre les différents langages :
- Nâutilisez pas dâabrĂ©viations ou de contractions dans les identifiants. Ex. :
SettlementWindowplutĂŽt queSetWin. - Nâutilisez pas dâacronymes non universellement acceptĂ©s en informatique.
- Lorsque câest pertinent, utilisez des acronymes reconnus pour raccourcir. Ex. :
UIpour User Interface. - Utilisez le Pascal case ou le camel case pour les noms de plus de deux caractĂšres, selon le contexte (classes vs variables). Ex. :
SettlementWindow(classe) ousettlementWindow(variable). - Mettez en majuscules les acronymes de deux lettres isolés, ex.
IDplutĂŽt queId. Ex. :/transfer/plutĂŽt que/transfer/pour un paramĂštre dâURI. - Ăvitez les abrĂ©viations dans les identifiants ou paramĂštres. Si vous devez en utiliser, camel case pour les abrĂ©viations de plus de deux caractĂšres, mĂȘme si cela diverge de lâabrĂ©viation usuelle.
- Utilisez le SCREAMING_SNAKE_CASE pour les énumérations. Ex. :
RECORD_FUNDS_OUT_PREPARE_RESERVE.
Réf. : Microsoft - Design Guidelines for Class Library Developers (opens new window)
# Javascript
Mojaloop suit le style Javascript défini par StandardJS (opens new window). RÚgles complÚtes : Standard Rules (opens new window). Extraits :
- 2 espaces pour lâindentation
function helloWorld (name) {
console.log('hi', name)
}
- Guillemets simples pour les chaĂźnes sauf pour Ă©viter dâĂ©chapper.
console.log('hello there') // â ok
console.log("hello there") // â avoid
console.log(`hello there`) // â avoid
- Pas de point-virgules. (voir : 1, 2, 3)
window.alert('hi') // â ok
window.alert('hi'); // â avoid
# Typescript
Note : Standard et Typescript
Ă mesure que nous introduisons davantage de TypeScript dans la base de code, Standard devient moins adaptĂ© et peut mĂȘme nuire Ă notre flux de travail si lâon tente dâappliquer Standard au Javascript compilĂ© depuis TypeScript. Il faudra Ă©valuer dâautres options pour Typescript, par ex. Prettier + ESLint.
Voir le dépÎt template-typescript-public (opens new window) pour la configuration Typescript de référence.
# YAML
Les désérialiseurs YAML peuvent varier ; rÚgles suivantes :
Crédit : exemples issus du guide de style Flathub (opens new window)
- Indentation de 2 espaces
- Toujours indenter les éléments enfants
# BON :
modules:
- name: foo
sources:
- type: bar
# MAUVAIS :
modules:
- name: foo
sources:
- type: bar
- Nâalignez pas les valeurs sur des colonnes
# MAUVAIS :
id: org.example.Foo
modules:
- name: foo
sources:
- type: git
# sh + bash
- Le shebang doit respecter lâenvironnement local de lâutilisateur :
#!/usr/bin/env bash
Le script utilisera le bash dĂ©fini dans lâenvironnement plutĂŽt quâun chemin codĂ© en dur.
- Pour rĂ©fĂ©rencer dâautres fichiers, Ă©vitez les chemins relatifs simples :
En effet, si quelqu'un exĂ©cute le script depuis un rĂ©pertoire diffĂ©rent de celui oĂč il se trouve, le script risque fort de ne pas fonctionner.
# MAUVAIS :
cat ../Dockerfile | wc -l
# BON :
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cat ${DIR}/../Dockerfile | wc -l
Autres bonnes pratiques bash : Best Practices for Writing Shell Scripts (opens new window)
# Documentation
- Rédiger la documentation en Markdown.
- Les schémas dessinés à la main doivent utiliser un format SVG éditable (ex. : architecture / composants / blocs / diagrammes de transition d'état), exportés depuis diagrams.net (opens new window)
NOTE : intĂ©grez le diagramme Ă©ditable lors de lâexport SVG depuis diagrams.net (opens new window) !
- Diagrammes de séquence : PlantUML
- Les documents de discussion doivent ĂȘtre placĂ©s dans
/community/archive/discussion-docs. - Il est dĂ©conseillĂ© dâutiliser Google Docs et autres outils propriĂ©taires pour la collaboration Ă lâĂ©chelle de la communautĂ©.
# Structure de répertoires
Outre le style de code, la communautĂ© recommande la structure suivante afin que les dĂ©veloppeurs puissent passer facilement dâun projet Ă lâautre, et que nos outils et configurations (.circleci/config.yml, Dockerfiles, etc.) puissent ĂȘtre portĂ©s dâun projet Ă lâautre avec des modifications mineures.
Structure attendue :
âââ README.md # Infos gĂ©nĂ©rales : prĂ©requis, tests, etc.
âââ LICENSE.md # Descripteur de licence Mojaloop standard.
âââ package.json # Descripteur npm du projet.
âââ package-lock.json # Arbre de dĂ©pendances exact dans le temps.
âââ nvmrc.json # NVMRC : runtime NodeJS (de prĂ©fĂ©rence Active LTS).
âââ .ncurc.yaml # Ignore pour le script dep:check (npm-check-updates).
âââ Dockerfile # Optionnel
âââ docker-compose.yml # Optionnel (dĂ©pendances backend, etc.)
âââ .npmignore # Optionnel â publication des bibliothĂšques npm.
âââ .gitignore # Fichier ignore GitHub.
âââ src # Sources du projet.
â âââ index.<js/ts> # Point dâentrĂ©e principal.
â âââ <filename>.<js/ts> # Convention des fichiers sources.
â âââ ...
âââ dist # Javascript compilĂ© (voir tsconfig).
âââ test # Tests, au minimum :
â âââ unit # Tests unitaires, structure alignĂ©e sur `./src`.
â â âââ <filename>.test.<js/ts>
â â âââ ...
â âââ integration # Tests dâintĂ©gration.
â âââ functional # Tests fonctionnels.
â âââ util # Scripts et helpers de test.
âââ config
âââ default.json # Configuration par dĂ©faut.
# Fichiers de configuration
Ces fichiers renforcent les styles de code ci-dessus :
# EditorConfig
EditorConfig est pris en charge nativement dans de nombreux IDE. Voir le guide EditorConfig (opens new window).
.editorconfig
root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
[{*.js,*.ts,package.json,*.yml,*.cjson}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
# NYC (couverture de code)
.nycrc.yml
temp-directory: "./.nyc_output"
check-coverage: true
per-file: true
lines: 90
statements: 90
functions: 90
branches: 90
all: true
include: [
"src/**/*.js"
]
reporter: [
"lcov",
"text-summary"
]
exclude: [
"**/node_modules/**",
'**/migrations/**'
]
# Typescript
.tsconfig.json
{
"include": [
"src"
],
"exclude": [
"node_modules",
"**/*.spec.ts",
"test",
"lib",
"coverage"
],
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"lib": [
"esnext"
],
"importHelpers": true,
"declaration": true,
"sourceMap": true,
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"*": [
"src/*",
"node_modules/*"
]
},
"esModuleInterop": true
}
}
.eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser', // Specifies the ESLint parser
extends: [
'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
// Enforces ES6+ import/export syntax
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
],
parserOptions: {
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-var-requires': 'off'
},
overrides: [
{
// Disable some rules that we abuse in unit tests.
files: ['test/**/*.ts'],
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
},
},
],
};
Configuration Typescript détaillée (package.json, jest.config.js, etc.) : Typescript Template Project (opens new window).
# Gestion des dépendances
# Mises à jour des dépendances
Il est important dâutiliser des dĂ©pendances Ă jour afin dâattĂ©nuer les risques de sĂ©curitĂ©.
# NodeJS
Installez npm-check-updates (opens new window) :
npm install -D npm-check-updates
Ajoutez dans package.json :
"scripts": {
"dep:check": "npx ncu -e 2",
"dep:update": "npx ncu -u"
}
Pour vérifier les mises à jour :
npm run dep:check
Pour installer les derniĂšres versions :
npm run dep:update && npm i
Si une dĂ©pendance ne peut pas ĂȘtre mise Ă jour pour une raison valide, ajoutez .ncurc.yaml Ă la racine avec la dĂ©pendance dans reject et un comment :
## TODO : raison pour chaque rejet et comment le traiter (story, etc.).
reject: [
# TODO: <Insert detailed information as to why this dependency should be ignored.>
"<DEPENDENCY_TO_IGNORE>",
]
Moyens pour maintenir les dépendances à jour :
# Hook Git pre-commit
Validation locale Ă chaque commit Git.
Ajoutez dep:check comme hook pre-commit avec Husky (opens new window) :
npx husky add .husky/pre-commit "npm run dep:check"
On peut contourner avec
git commit -nm <message>. Un job CItest-dependencies(section suivante) est donc nécessaire.
# Validations CI automatisées
ContrÎles lors des revues et releases ; évite le contournement du hook.
Les configs CI (.circleci/config.yml) doivent inclure un job test-dependencies (npm run dep:check) pour les PR, fusions vers la branche principale et releases étiquetées.
# Audit des dépendances
# NodeJS
Installez audit-ci (opens new window) :
npm install -D audit-ci
Ajoutez dans package.json :
"scripts": {
"audit:check": "npx audit-ci --config ./audit-ci.jsonc"
}
Pour vérifier les mises à jour :
npm run audit:check
Correctifs connus via npm audit (opens new window) :
npm audit fix --package-lock-only
NOTES
- Commitez les correctifs appliqués au
package-lock.json.- Relancez les tests : un changement de version peut introduire des ruptures.
Sans correctif, ajoutez audit-ci.jsonc Ă la racine avec lâID dâavis dans allowlist et un commentaire :
{
"$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json",
// audit-ci supports reading JSON, JSONC, and JSON5 config files.
// Only use one of ["low": true, "moderate": true, "high": true, "critical": true]
"moderate": true,
"allowlist": [ // NOTE: Please add as much information as possible to any items added to the allowList
// Currently no fixes available for the following advisory ID
"<VULNERABILITY_ADVISORY_ID>"
]
}
# Hook Git pre-commit
Exécute les contrÎles de vulnérabilités localement à chaque commit.
Ajoutez audit:check avec Husky (opens new window) :
npx husky add .husky/pre-commit "npm run audit:check"
Contournement possible avec
git commit -nm. Un job CIvulnerability-check(section suivante) est requis.
# Validations CI automatisées
Audits lors des revues et releases ; évite le contournement du hook.
Les configs CI (.circleci/config.yml) doivent inclure un job vulnerability-check (npm run audit:check) pour les PR, fusions vers la branche principale et releases étiquetées.
# Lignes directrices de conception et dâimplĂ©mentation
Recommandations pour le code au sein de la communauté Mojaloop (ou le code qui y sera intégré). Si vous souhaitez donner du code à la communauté, suivez ces lignes directrices autant que possible pour la cohérence et la maintenabilité. Les contributions alignées seront intégrées plus facilement.
Voir la FAQ ci-dessous.
# Outils et frameworks
La communauté OSS Mojaloop privilégie les outils et frameworks suivants :
- Serveur web :
HapiJS(opens new window) - Framework UI web :
ReactJS(opens new window) - Configuration dâexĂ©cution :
convict(opens new window), avecrc(opens new window) pour lâexistant. (variables dâenvironnement et fichiers de config) - Gestion des paquets :
npm - Journalisation : bibliothĂšque
@mojaloop/central-services-logger(opens new window), basée sur Winston - Conteneurs et orchestration :
docker(opens new window) etkubernetes(opens new window) - Tests unitaires : pour lâexistant,
Tape(opens new window) ; les nouvelles bases passent progressivement ĂJest(opens new window). - Couverture de tests :
nyc(opens new window) - CI :
CircleCI(opens new window)
En utilisant ces outils et frameworks, nous maintenons un haut niveau de cohĂ©rence et de maintenabilitĂ© sur lâensemble de la base de code, ce qui permet Ă nos dĂ©veloppeurs de rester productifs et sereins. Nous nâimposons pas leur usage aux dĂ©pĂŽts fournis en contribution, mais dâautres choix peuvent alourdir la maintenance pour la communautĂ©.
# Adopter des contributions open source dans Mojaloop
Lignes directrices pour lâadoption dâune contribution dans les dĂ©pĂŽts open source Mojaloop. Lâadoption est le processus par lequel la communautĂ© accompagne un contributeur pour aligner sa contribution sur nos normes afin quâelle rejoigne la base de code OSS Mojaloop.
Note : les contributions sont Ă©valuĂ©es au cas par cas. Celles qui ne respectent pas ces lignes directrices passent par la phase dâincubation ci-dessous. Dâautres Ă©carts (p. ex. choix de framework) peuvent figurer sur une feuille de route pour standardisation ultĂ©rieure.
# Ătape 0 : prĂ©requis
Avant quâune contribution soit considĂ©rĂ©e pour adoption :
- Elle doit ĂȘtre alignĂ©e avec les principes du Level One Project (opens new window).
- Elle doit respecter le guide de style et les lignes directrices de conception et dâimplĂ©mentation ci-dessus.
- Elle doit inclure de la documentation de dĂ©marrage : plus il y en a, mieux câest.
- Elle doit inclure des tests avec une bonne couverture. Au minimum des tests unitaires ; une suite unitaire, dâintĂ©gration et fonctionnelle est prĂ©fĂ©rĂ©e. Voir le guide des contributeurs.
# Ătape 1 : incubation
- CrĂ©er un dĂ©pĂŽt privĂ© dans lâorganisation GitHub Mojaloop pour le code adoptĂ©.
- Faire examiner par une sous-Ă©quipe de la DA pour vĂ©rifier la portabilitĂ© (vers lâOSS), lâalignement avec les principes L1P, etc., et la conformitĂ© de la conception aux normes.
- Vérifier les licences de la contribution et des nouvelles dépendances ; ajouter la licence Mojaloop standard avec attribution aux donateur(s)/contributeur(s).
- Ăvaluer lâĂ©tat du code : documentation, tests, qualitĂ© ; combler les lacunes.
- Ăvaluer lâimpact sur les performances.
- Créer des actions (stories) pour renommer, retirer ou anonymiser tout élément non générique.
- Examiner et discuter les choix de frameworks et dâoutils.
- En cas de décision de changement, les ajouter à la feuille de route.
# Ătape 2 : adoption publique
- Rendre le projet public sur GitHub Mojaloop.
- Annoncer sur le canal Slack
#announcements(opens new window). - Activer les pipelines CI/CD et publier les artefacts pertinents (images Docker, modules npm, etc.).
- Examiner et recommander un module ou une formation pour le programme de formation Mojaloop si pertinent.
# Versionnement
Voir versionnement pour Mojaloop.
# Créer de nouvelles fonctionnalités
Processus pour les fonctionnalités et branches dans Mojaloop.
# Processus de pull request
Pour les changements importants, demandez conseil sur Slack (opens new window). Les PR doivent décrire le changement et sa motivation. Vous pouvez utiliser les brouillons de PR GitHub pour recueillir commentaires et revue.
Les PR qui violent les principes Level One (opens new window) seront refusées.
# Code de conduite
Nous appliquons le code de conduite de la Fondation Mojaloop (opens new window).
# Licence
Voir la politique License (opens new window).
# FAQ
1. Je veux contribuer du code qui ne suit pas le style ou les outils recommandés dans ce guide.
Les contributions sont acceptĂ©es au cas par cas. Si la contribution nâest pas prĂȘte pour une adoption complĂšte, nous pouvons passer par la phase dâincubation : refactoring avec notre aide pour aligner code et documentation.
2. Ces normes sont dépassées et un outil (ou framework, méthode, langage) plus récent résoudrait le problÚme x. Comment mettre à jour les normes ?
Ăcrire du code de qualitĂ© est une cible en constante Ă©volution, et nous cherchons toujours activement de nouveaux outils susceptibles dâamĂ©liorer la base de code OSS Mojaloop. NâhĂ©sitez donc pas Ă nous en parler sur le canal Slack design authority (#design-authority) si vous avez une recommandation.
