@aventii/config (1.0.1)
Installation
@aventii:registry=npm install @aventii/config@1.0.1"@aventii/config": "1.0.1"About this package
@aventii/config
Gestion de configuration commune aux services Aventii.
@aventii/config fournit un mécanisme générique de lecture, conversion,
validation et sécurisation des variables de configuration des
microservices Node.js.
Il permet notamment de :
- déclarer les variables attendues sous forme de schéma ;
- convertir automatiquement les valeurs vers les types attendus ;
- appliquer des valeurs par défaut ;
- valider les valeurs individuellement et globalement ;
- agréger les erreurs de configuration ;
- identifier les secrets ;
- produire une représentation journalisable sans exposer les secrets ;
- générer des fichiers
.envdédiés à plusieurs microservices ; - produire un manifeste descriptif des variables attendues.
Le package ne dépend d'aucune configuration métier particulière.
Installation
Le package est distribué sur le registre npm privé Aventii.
npm install @aventii/config
Principes
@aventii/config sépare deux usages principaux :
- la construction de la configuration d'un microservice au démarrage ;
- le tooling permettant de générer des fichiers d'environnement dédiés à plusieurs services.
La configuration est construite à partir d'une source générique.
Par défaut, cette source est :
process.env
mais n'importe quel objet peut être fourni explicitement.
Le package ne charge pas lui-même un fichier .env lors de
createConfig().
Création d'une configuration
Le package expose createConfig.
const {
createConfig
} = require('@aventii/config');
const config = createConfig({
PORT: {
type: 'port',
required: true
},
NODE_ENV: {
type: 'string',
enum: [
'development',
'production'
],
default: 'development'
},
AUTH_TOKEN: {
type: 'string',
required: true,
secret: true
},
USE_PROOF_OF_WORK: {
type: 'boolean',
default: false
}
});
Les valeurs sont lues depuis process.env, converties puis validées.
Source personnalisée
Une source peut être injectée explicitement.
const config = createConfig(
{
PORT: {
type: 'port',
required: true
}
},
{
source: {
PORT: '8448'
}
}
);
Cela facilite notamment les tests et les outils de génération.
Types supportés
Les types actuellement disponibles sont :
string
string[]
integer
number
boolean
url
port
json
string
Les chaînes sont trimées par défaut.
NAME: {
type: 'string'
}
Pour conserver les espaces :
NAME: {
type: 'string',
trim: false
}
string[]
Par défaut, les valeurs sont séparées par des virgules.
CORS_ORIGINS: {
type: 'string[]'
}
Exemple :
https://a.example.com,https://b.example.com
Un séparateur personnalisé peut être fourni :
CORS_ORIGINS: {
type: 'string[]',
separator: ';'
}
Les éléments vides sont supprimés.
integer
RETRY_COUNT: {
type: 'integer'
}
Seuls les entiers sûrs JavaScript sont acceptés.
number
RATIO: {
type: 'number'
}
La valeur doit être un nombre fini.
boolean
USE_PROOF_OF_WORK: {
type: 'boolean'
}
Les booléens sont volontairement stricts.
Les valeurs textuelles acceptées sont uniquement :
true
false
La casse et les espaces sont ignorés.
Les formes suivantes ne sont pas acceptées :
1
0
yes
no
on
off
url
KEY_API_URL: {
type: 'url'
}
La valeur doit être comprise par l'API URL de Node.js.
port
PORT: {
type: 'port'
}
La valeur doit être un entier compris entre 1 et 65535.
json
OPTIONS: {
type: 'json'
}
Une chaîne est décodée avec JSON.parse().
Une valeur déjà fournie sous forme d'objet est conservée telle quelle.
Variables obligatoires et valeurs par défaut
Une variable obligatoire est déclarée avec :
AUTH_TOKEN: {
type: 'string',
required: true
}
Une valeur par défaut peut être fournie :
PORT: {
type: 'port',
default: 8448
}
Une variable optionnelle absente reste présente dans la configuration avec la valeur :
undefined
Contraintes supplémentaires
Plusieurs règles peuvent être combinées dans une définition.
Valeurs autorisées
NODE_ENV: {
type: 'string',
enum: [
'development',
'production'
]
}
Minimum et maximum
Les contraintes min et max sont disponibles pour :
integer
number
port
Exemple :
RETRY_COUNT: {
type: 'integer',
min: 1,
max: 5
}
Expression régulière
COUNTRY: {
type: 'string',
pattern: /^[A-Z]{2}$/
}
Transformation
Une valeur peut être transformée après sa conversion et avant sa validation.
COUNTRY: {
type: 'string',
transform: value =>
value.toUpperCase(),
enum: [
'CM',
'MG'
]
}
Validation personnalisée
EVEN_NUMBER: {
type: 'integer',
validate: value =>
value % 2 === 0 ||
'doit être pair'
}
La fonction peut retourner :
true
false
une chaîne décrivant l'erreur
Les validateurs doivent être synchrones.
Validation globale
Une validation portant sur l'ensemble de la configuration peut être fournie.
const config = createConfig(
{
MAIL_DISABLED: {
type: 'boolean',
required: true
},
SMTP_HOST: {
type: 'string'
}
},
{
validate: config => {
if (
!config.MAIL_DISABLED &&
!config.SMTP_HOST
) {
return 'SMTP_HOST requis';
}
return true;
}
}
);
La validation globale est exécutée après la validation des champs.
Elle doit également être synchrone.
Agrégation des erreurs
Les erreurs de configuration sont regroupées dans une seule
ConfigError.
const {
ConfigError
} = require('@aventii/config');
Exemple :
[config] Configuration invalide
- AUTH_TOKEN: variable obligatoire absente
- PORT: port attendu entre 1 et 65535
- NODE_ENV: valeur non autorisée, valeurs possibles : development, production
Cela permet de corriger plusieurs problèmes de configuration en une seule fois au lieu de provoquer plusieurs cycles de démarrage.
L'erreur expose également :
error.errors
qui contient la liste structurée des anomalies.
Configuration immuable
Par défaut, la configuration produite est gelée récursivement.
const config = createConfig(schema);
Cela concerne également les tableaux et objets imbriqués produits par
les types string[] et json.
Cette protection peut être désactivée :
const config = createConfig(
schema,
{
freeze: false
}
);
Secrets et journalisation
Une variable peut être marquée comme secrète.
AUTH_TOKEN: {
type: 'string',
required: true,
secret: true
}
Le package expose redactConfig.
const {
redactConfig
} = require('@aventii/config');
console.log(
redactConfig(config)
);
Exemple :
{
AUTH_TOKEN: '[REDACTED]',
PORT: 8448
}
Seules les variables explicitement déclarées avec secret: true sont
masquées.
Métadonnées de configuration
Le package associe des métadonnées internes aux configurations créées
avec createConfig().
const {
getConfigMetadata
} = require('@aventii/config');
const metadata =
getConfigMetadata(config);
La structure retournée contient actuellement :
{
generatedAt,
secretKeys
}
Un objet qui n'a pas été créé par createConfig() retourne :
null
Les métadonnées retournées sont une copie défensive.
Environnements générés
Le package réserve la variable :
AVENTII_CONFIG_GENERATED_AT
Lorsqu'elle est présente dans la source, createConfig() vérifie sa
validité et mémorise sa date dans les métadonnées.
La valeur n'est pas ajoutée à la configuration métier.
Exemple de log :
[config] pmc-pdf — environnement généré le 2026-08-20T11:14:32.481Z
Le nom du service peut être fourni :
createConfig(schema, {
name: 'pmc-pdf'
});
Le logger est configurable :
createConfig(schema, {
logger: customLogger
});
ou désactivable :
createConfig(schema, {
logger: null
});
Lecture d'un fichier .env
Le tooling expose readEnvFile.
const {
readEnvFile
} = require('@aventii/config');
const source =
readEnvFile('/path/to/.env');
La fonction utilise dotenv.parse().
Elle retourne un objet contenant les valeurs du fichier mais ne modifie pas :
process.env
readEnvFile() appartient au tooling.
createConfig() lui-même reste indépendant de tout fichier .env.
Génération de fichiers d'environnement
generateEnvFiles permet de générer un fichier dédié à chaque
microservice à partir d'une source commune.
const {
generateEnvFiles
} = require('@aventii/config');
const result = generateEnvFiles({
services: {
'pmc-pdf': {
AUTH_TOKEN: {
type: 'string',
required: true,
secret: true
},
PDF_PORT: {
type: 'port',
required: true
}
},
'pmc-di': {
AUTH_TOKEN: {
type: 'string',
required: true,
secret: true
},
DI_PORT: {
type: 'port',
required: true
}
}
},
source: masterEnvironment,
outputDirectory:
'./env-generated'
});
Le résultat contient :
{
generatedAt,
files,
manifestPath
}
Projection par service
Chaque fichier généré contient uniquement les variables déclarées dans le schéma du service concerné.
Une variable présente dans la source globale mais absente du schéma du service n'est pas écrite dans son fichier.
Exemple :
env-generated/
├── pmc-di.env.generated
├── pmc-pdf.env.generated
└── env-manifest.json
Les variables optionnelles absentes sont omises.
Les valeurs par défaut sont en revanche projetées.
Chaque configuration est validée avec createConfig() avant l'écriture
du fichier correspondant.
Horodatage de génération
Tous les fichiers produits lors d'une même génération utilisent exactement le même horodatage.
Exemple :
# Generated by @aventii/config
# Service: pmc-pdf
# Generated at: 2026-08-20T11:14:32.481Z
AVENTII_CONFIG_GENERATED_AT='2026-08-20T11:14:32.481Z'
Le même horodatage est également enregistré dans le manifeste.
Manifeste d'environnement
Le manifeste peut aussi être créé indépendamment avec
createEnvManifest.
const {
createEnvManifest
} = require('@aventii/config');
const manifest =
createEnvManifest(services);
Le manifeste décrit les variables attendues mais ne contient aucune valeur réelle.
Exemple :
{
generatedAt: '...',
services: {
'pmc-pdf': {
variables: {
AUTH_TOKEN: {
type: 'string',
required: true,
secret: true,
hasDefault: false
}
}
}
}
}
Selon la définition, le manifeste peut également exposer :
enum
min
max
pattern
Les valeurs par défaut elles-mêmes ne sont pas exposées.
Seule leur présence est indiquée via :
hasDefault
Emplacement du manifeste
Par défaut, le manifeste est généré dans :
<outputDirectory>/env-manifest.json
Un emplacement différent peut être fourni :
generateEnvFiles({
services,
source,
outputDirectory,
manifestPath:
'./env-manifest.json'
});
Nettoyage des fichiers générés
Avant une nouvelle génération, le package supprime dans le répertoire de sortie :
*.env.generated
env-manifest.json
Les autres fichiers sont conservés.
Les noms de services utilisés pour produire les fichiers sont validés afin d'empêcher notamment l'utilisation de chemins tels que :
../pmc-pdf
API
Le package expose actuellement :
createConfig
ConfigError
getConfigMetadata
redactConfig
readEnvFile
createEnvManifest
generateEnvFiles
GENERATED_AT_KEY
Articulation avec les autres packages Aventii
Le rôle attendu de @aventii/config est généralement situé au début du
cycle de vie du microservice.
process.env / fichier maître
↓
@aventii/config
↓
configuration validée et typée
↓
infrastructure/
↓
@aventii/runtime
@aventii/db
@aventii/link
@aventii/security
...
Les autres packages peuvent ainsi recevoir une configuration déjà convertie et validée.
Hors périmètre
@aventii/config ne décide pas :
- quelles variables un produit doit définir ;
- quelles valeurs doivent être utilisées en production ;
- comment les secrets sont obtenus ou renouvelés ;
- où les secrets sont stockés ;
- comment les fichiers générés sont distribués ;
- comment Docker ou un orchestrateur injecte les variables ;
- quelles règles métier dépendent d'une configuration ;
- comment un microservice doit démarrer ou s'arrêter.
Ces décisions appartiennent aux services consommateurs et à leur infrastructure.
Tests
npm test
Les tests couvrent notamment :
- les différents types de valeurs ;
- les valeurs par défaut ;
- les variables obligatoires ;
- l'agrégation des erreurs ;
- les booléens stricts ;
- les ports ;
enum,min,maxetpattern;- les transformations ;
- les validations personnalisées et globales ;
- l'interdiction des validateurs asynchrones ;
- le gel récursif ;
- le masquage des secrets ;
- les métadonnées ;
- l'horodatage des environnements générés ;
- la lecture de fichiers
.env; - la génération par service ;
- le manifeste ;
- le nettoyage des artefacts générés ;
- la validation des noms de services.
Dependencies
Dependencies
| ID | Version |
|---|---|
| dotenv | ^17.4.2 |