@imolko/ultra-settings
v0.1.5
Published
Contrato tipado de settings con Zod y comandos init/generate para aplicaciones imolko
Downloads
126
Readme
Ultra settings
Librería encargada de generar los archivos con las variables de entorno de un proyecto y generar los YAML con dichas variables de entorno según sea el caso.
- Contrato tipado de settings con Zod.
- CLI
init/generate/validatepara sembrar, generar y validar la configuración. - Templates y receta de generación locales y editables por aplicación.
- API programática con errores estructurados.
- Integración runtime para NestJS.
Instalación
npm install @imolko/ultra-settingsRequisitos:
- Node.js >= 20
- Solo para el perfil
nestjs:@nestjs/config^4 (peer dependency opcional)
npm install @nestjs/configQuick start
npm install @imolko/ultra-settings
# 1. Inicializar el perfil
npx ultra-settings init --profile nestjs
# 2. (opcional) Editar src/settings/settings.ts, conditions.ts, templates/ y files.ts
# 3. Validar la configuración sin generar
npx ultra-settings validate
# 4. Generar archivos de entorno y YAMLs
npx ultra-settings generate --dry-run # previsualizar
npx ultra-settings generate # escribirScripts en package.json
Después de instalar la librería, agrega estos scripts al package.json de la aplicación:
{
"scripts": {
"settings:init": "ultra-settings init --profile angular",
"settings:validate": "ultra-settings validate",
"settings:generate": "ultra-settings generate"
}
}--profile acepta nestjs, angular o express. Ajusta el perfil según la aplicación.
settings:initcrea la definición de settings ensrc/settings/, la carpetasrc/settings/templates/, la recetasrc/settings/files.tsy el archivoultra-settings.config.json.settings:validateverifica configuración, perfil, schema, receta y templates sin generar.settings:generategenera los archivos de entorno y los YAMLs a partir de la receta y los templates locales.
Pasar flags a los scripts
Si ejecutas un script con npm run y quieres pasarle una flag del CLI (por
ejemplo --force), usa -- para que npm no la intercepte:
npm run settings:init -- --forceSin el --, npm consume la flag como propia (npm run settings:init --force
muestra npm warn using --force y la flag no llega a ultra-settings):
| Comando | Resultado |
| --- | --- |
| npm run settings:init --force | npm se queda con --force; ejecuta ultra-settings init sin forzar |
| npm run settings:init -- --force | ejecuta ultra-settings init --profile angular --force |
Alternativamente, puedes invocar el CLI directamente para evitar la ambigüedad:
npx ultra-settings init --forceCLI
Puedes ver la ayuda completa en cualquier momento:
npx ultra-settings --help
npx ultra-settings init --help
npx ultra-settings generate --help
npx ultra-settings validate --helpultra-settings init
| Flag | Alias | Descripción |
| --- | --- | --- |
| --profile <name> | — | Perfil de aplicación: nestjs, angular o express |
| --force | — | Sobrescribe los archivos sembrados aunque ya existan |
init es idempotente: no sobrescribe archivos existentes salvo con --force.
ultra-settings generate
| Flag | Alias | Descripción |
| --- | --- | --- |
| --config-dir <path> | — | Sobrescribe el directorio de salida de los archivos de entorno (default: config) |
| --settings-path <path> | — | Sobrescribe la ruta del settings local |
| --templates-path <path> | — | Sobrescribe el directorio de templates locales |
| --files-path <path> | — | Sobrescribe la ruta de la receta local |
| --schema-path <path> | — | Sobrescribe la ruta de salida del values.schema.json |
| --dry-run | — | Previsualiza los cambios sin escribir en disco |
ultra-settings validate
Valida la configuración sin generar. Reporta todos los errores juntos: configuración, perfil, schema local, receta local y existencia de cada template.
npx ultra-settings init --profile angular
npx ultra-settings validate
npx ultra-settings generateContrato de settings
Guía completa para construir settings (parámetros de
.meta(), valores desetting_typeysetting_source, tablas de implicaciones y plantillas): SETTINGS.md.
Cada campo del settingsSchema se define con Zod y se anota con .meta({...}). De estas anotaciones dependen los filtros que alimentan los templates de generate.
setting_type
Clasifica el origen y la naturaleza de un campo:
| Valor | Significado |
| --- | --- |
| metadata | Metadatos de la aplicación (nombre) — labels y ConfigMap |
| infra | Infraestructura (puertos, dominio, environment) |
| secret | Credenciales — alimenta .credentials.env.sample |
| env | Variables de entorno de la aplicación |
| cluster | Valores que provienen del cluster — alimenta values.yaml |
setting_source
Indica de dónde proviene el valor. Puede coincidir con setting_type o ser cluster_ref, cuando el valor se toma de un secret del cluster (se transforma en cluster_<campo> en el values.schema.json).
Declarar un setting
import { PortBaseConditions } from '@imolko/ultra-settings';
export const ServerPortConditions = PortBaseConditions
.default(3101)
.meta({
description: 'Server port',
setting_type: 'infra',
examples: ['3000', '3101'],
});Propiedades soportadas en .meta(): title, description, setting_type, setting_source y examples. Con .default(...) fijas un valor por defecto y con .optional() lo haces opcional.
Fuente única de
z:@imolko/ultra-settingsre-exportazoden su raíz. Importazdesde el paquete — no desde'zod'— para compartir la misma instancia de Zod que las condiciones base y evitar errores deinstanceofo encadenados (.default(),.meta()).
init siembra src/settings/settings.ts y src/settings/conditions.ts; ahí defines y personalizas tus settings.
Condiciones base
La librería exporta validadores reutilizables para usar en tu conditions.ts:
| Export | Valida |
| --- | --- |
| NameBaseConditions | nombres (2–63 chars, [a-zA-Z_-]+) |
| StorageBaseConditions | storage K8s (10Gi, 500Mi, 1T) |
| MemoryBaseConditions | memoria K8s (512Mi, 1Gi) |
| CpuBaseConditions | CPU K8s (500m, 0.5) |
| PortBaseConditions | puerto 1–65535 |
| DomainBaseConditions | hostname o http://localhost |
| MongoUriBaseConditions | mongodb:// / mongodb+srv:// |
| TokenBaseCondition | string no vacío |
import { NameBaseConditions } from '@imolko/ultra-settings';
export const AppNameConditions = NameBaseConditions
.default('mi-app')
.meta({ setting_type: 'metadata', description: 'Nombre de la aplicación' });Configuración (ultra-settings.config.json)
init escribe este archivo y generate lo lee:
{
"profile": "nestjs",
"configDir": "config",
"settingsPath": "src/settings/settings.ts",
"templatesPath": "src/settings/templates",
"filesPath": "src/settings/files.ts",
"schemaPath": "helm-chart/values.schema.json"
}| Campo | Tipo | Requerido | Default | Descripción |
| --- | --- | --- | --- | --- |
| profile | string | sí | — | Perfil: nestjs, angular o express |
| configDir | string | sí | config | Directorio de salida de los archivos de entorno |
| settingsPath | string | no | — | Ruta al settings.ts local |
| templatesPath | string | sí | src/settings/templates | Directorio de templates YAML locales |
| filesPath | string | sí | src/settings/files.ts | Ruta de la receta local |
| schemaPath | string | sí | helm-chart/values.schema.json | Ruta de salida del values.schema.json |
Si settingsPath está presente, generate carga tu settingsSchema desde ese archivo en tiempo de ejecución (con jiti, sin compilar nada). Si falta, usa el schema empaquetado del perfil.
Los flags de rutas del CLI (--config-dir, --settings-path, --templates-path, --files-path y --schema-path) tienen prioridad sobre los valores del archivo.
Receta y templates locales
init copia los seis templates YAML del perfil a src/settings/templates/:
| Template | Contenido |
| --- | --- |
| sample.env.hbs | plantilla de entorno (.env*) |
| values.yaml.hbs | valores de Helm |
| config_map.yaml.hbs | ConfigMap |
| _common_labels.tpl.hbs | helper de labels |
| secret.yaml.hbs | Secret (disponible, no se genera por defecto) |
| config_map_requirements.yaml.hbs | requisitos del ConfigMap (disponible, no se genera por defecto) |
No copia el template de siguientes pasos (next-steps.hbs).
init también siembra la receta src/settings/files.ts. La receta es un array
Tipado de generaciones que define qué YAMLs se generan, con qué template,
nombre, carpeta y filtros:
import { SettingsGeneration } from '@imolko/ultra-settings';
export const settingsGenerations: SettingsGeneration[] = [
{
template: 'config_map.yaml.hbs',
folder: 'helm-chart/templates',
name: 'server-config.yaml',
setting_types: ['metadata', 'infra', 'env'],
setting_sources: ['cluster_ref'],
},
// ...
];Agrega o quita entradas para controlar la salida. generate carga la receta
(validada con Zod) y los templates desde estas rutas, sin fallback a los
templates empaquetados.
Archivos generados
generate mantiene una lista fija de archivos .env* bajo configDir:
| Archivo | Contenido |
| --- | --- |
| config/.metadata.env.sample | settings metadata |
| config/.no-cluster.env.sample | env + infra |
| config/.with-cluster.env.sample | env + infra + cluster |
| config/.credentials.env.sample | secret |
| config/cicd/overlays/test/.properties.env.sample | propiedades de test |
Los YAMLs los controla la receta local. La receta sembrada por init produce:
| Archivo | Contenido |
| --- | --- |
| helm-chart/values.sample.yaml | valores base del chart |
| config/cicd/values.sample.yaml | valores CICD |
| helm-chart/templates/server-config.yaml | ConfigMap |
| helm-chart/templates/_common_labels.tpl | helper de labels |
generate escribe además values.schema.json en schemaPath.
Diferencias entre perfiles
La receta y la lista de archivos son idénticas en los tres perfiles; cambia el contenido de los templates y del schema:
| Perfil | Diferencias |
| --- | --- |
| nestjs | settings mongo_* + credenciales GA/scouters; init además siembra src/settings/register-env.ts; título del schema "Values Schema for NestJS Helm Chart" |
| angular | setting backend_url; sin mongo_*; título "Values Schema for Angular Helm Chart" |
| express | setting server_db_path (SQLite inline); sin mongo_*; título "Values Schema for Express Helm Chart" |
Uso programático
El CLI es un wrapper fino sobre la API programática:
import { run } from '@imolko/ultra-settings';
const result = await run(
{ generator: 'init', data: { profile: 'nestjs' } },
{ projectRoot: process.cwd(), dryRun: false },
);
if (result.success) {
console.log(result.changes);
} else {
console.error(result.error.code, result.error.message);
}run devuelve una unión discriminada:
- éxito:
{ success: true, generator, changes, dryRun } - error:
{ success: false, error: { code, message, details? } }
Códigos de error
| Código | Cuándo |
| --- | --- |
| INVALID_INPUT | entrada, JSON, schema local o receta inválidos |
| PROFILE_NOT_FOUND | --profile o profile desconocido |
| CONFIG_MISSING | falta ultra-settings.config.json (ejecutar init primero) |
| SETTINGS_NOT_FOUND | no se pudo cargar settingsPath |
| RECIPE_NOT_FOUND | no se pudo cargar la receta local filesPath |
| TEMPLATE_NOT_FOUND | falta un template referenciado en templatesPath |
| VALIDATION_FAILED | validate encontró uno o más errores (detallados en details.errors) |
| FILESYSTEM_ERROR | error de lectura/escritura (EACCES, etc.) |
| GENERATOR_ERROR | generador desconocido u otro error |
Integración NestJS
Para el perfil nestjs, la librería publica el subpath @imolko/ultra-settings/nestjs:
import { ConfigModule } from '@nestjs/config';
import { registerEnv } from '@imolko/ultra-settings/nestjs';
@Module({
imports: [ConfigModule.forRoot({ load: [registerEnv] })],
})
export class AppModule {}import { ConfigService } from '@nestjs/config';
import { getEnvConfig, EnvConfig } from '@imolko/ultra-settings/nestjs';
const env: EnvConfig = getEnvConfig(configService);registerEnvvalidaprocess.envcontra el schema de Zod y falla rápido al arrancar si falta o es inválida una variable requerida.getEnvConfig(configService)devuelve la configuración validada y tipada.
Variables de entorno
Las variables se leen en MAYÚSCULAS: para app_name se busca APP_NAME, para server_domain se busca SERVER_DOMAIN. registerEnv normaliza process.env a las claves del schema.
Desarrollo
¿Vas a contribuir? Ver CONTRIBUTING.md (flujo pi.dev, Ralph y release).
