Trabajo con YAML en TypeScript: análisis, generación y validación
YAML (YAML Ain't Markup Language) es uno de los formatos de serialización de datos más populares, ampliamente utilizado en archivos de configuración, DevOps (Docker, Kubernetes, Ansible) y pipelines de CI/CD. En el ecosistema de TypeScript, para trabajar con YAML se utiliza la biblioteca js-yaml, que proporciona soporte completo para la especificación YAML 1.2, incluyendo estructuras complejas, etiquetas y tipos de datos personalizados.
Instalación y configuración
Para empezar, instale la biblioteca y sus tipos a través de npm:
npm install js-yamlnpm install --save-dev @types/js-yamlDespués de la instalación, puede importar la biblioteca en su proyecto TypeScript:
import * as yaml from 'js-yaml';import * as fs from 'fs';Análisis de YAML en TypeScript
La función principal para leer YAML es yaml.load(), que convierte una cadena YAML en un objeto JavaScript/TypeScript. Veamos un ejemplo con un archivo de configuración:
// config.yaml// server:// port: 3000// host: "localhost"// database:// url: "mongodb://localhost:27017/mydb"// poolSize: 10// features:// - logging// - authentication
interface Config { server: { port: number; host: string; }; database: { url: string; poolSize: number; }; features: string[];}
const yamlContent = fs.readFileSync('config.yaml', 'utf8');const config = yaml.load(yamlContent) as Config;
console.log(config.server.port); // 3000console.log(config.features); // ['logging', 'authentication']Para un análisis seguro (sin ejecución de código), use yaml.load() — es más seguro que yaml.eval(), que puede ejecutar código JavaScript arbitrario.
Generación de YAML a partir de objetos TypeScript
La operación inversa — convertir un objeto TypeScript en una cadena YAML — se realiza con la función yaml.dump(). Esto es útil para crear archivos de configuración sobre la marcha:
interface DeploymentConfig { apiVersion: string; kind: string; metadata: { name: string; labels?: Record<string, string> }; spec: { replicas: number; selector: Record<string, string> };}
const deployment: DeploymentConfig = { apiVersion: 'apps/v1', kind: 'Deployment', metadata: { name: 'my-app', labels: { app: 'my-app', tier: 'backend' } }, spec: { replicas: 3, selector: { matchLabels: { app: 'my-app' } } }};
const yamlString = yaml.dump(deployment, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: true});
console.log(yamlString);// apiVersion: apps/v1// kind: Deployment// metadata:// labels:// app: my-app// tier: backend// name: my-app// spec:// replicas: 3// selector:// matchLabels:// app: my-appTrabajo con tipos personalizados
La biblioteca js-yaml admite esquemas y tipos de datos personalizados. Esto es especialmente útil al trabajar con fechas, expresiones regulares u objetos especiales:
import * as yaml from 'js-yaml';
// Creamos un tipo personalizado para fechasconst DateType = new yaml.Type('!date', { kind: 'scalar', resolve: (data: string) => !isNaN(Date.parse(data)), construct: (data: string) => new Date(data), instanceOf: Date, represent: (date: Date) => date.toISOString()});
// Creamos un esquema con soporte para tipos estándar y personalizadosconst schema = yaml.DEFAULT_SCHEMA.extend([DateType]);
const yamlWithDates = `event: !date 2024-12-25T10:00:00Ztitle: "Seminario de Navidad"`;
const parsed = yaml.load(yamlWithDates, { schema });console.log(parsed.event instanceof Date); // trueconsole.log(parsed.event.toLocaleDateString('es-ES')); // 25/12/2024