Ficheros de configuración

Una configuración es un documento que leen dos públicos: la persona que la ajusta y el programa que la carga. STXT sirve a los dos con el mismo fichero, y con una plantilla detecta en el editor el error que de otro modo aparecería en producción.

Los ficheros de configuración empiezan pequeños y crecen sin plan: se añaden claves, se copian bloques entre entornos, se acumulan comentarios que explican por qué un valor es el que es. Con el tiempo, las reglas que hacen válido el fichero —qué claves existen, qué valores admiten, cuáles son obligatorias— solo están en la cabeza de quien lo mantiene y en el código que lo lee. Un nombre mal escrito puede no fallar al cargar: muchos cargadores lo ignoran y aplican el valor por defecto.

STXT aborda esto con tres cosas: una jerarquía visible, que no necesita llaves ni sangrías ambiguas; bloques de texto donde la explicación larga vive junto al valor que explica; y una plantilla que convierte las reglas implícitas en un contrato que el editor aplica al escribir.

La configuración de un servicio

Server Config (com.acme.server):
	Name: api-gateway
	Environment: production

	Network:
		Host: 0.0.0.0
		Port: 8080
		Public url: https://api.acme.com

	Threads:
		Min: 8
		Max: 64

	Timeouts:
		Read ms: 5000
		Write ms: 5000

	Logging:
		Level: INFO
		Format: json

	Features:
		Feature: experimental-cache
			Enabled: false
		Feature: audit-logging
			Enabled: true

	Notes >>
		Configuración principal del gateway de APIs. Se versiona con la aplicación
		y se despliega con ella.

		Los cambios en Network y Timeouts pasan por revisión de Reliability:
		el límite de 5000 ms viene del SLA con el proveedor de pagos.

Cada grupo (Network, Threads, Logging) es un nodo sin valor que agrupa a sus hijos; cada ajuste es un nodo con valor; cada feature flag es un nodo cuyo valor es su nombre y cuyo hijo es su estado. El bloque Notes >> lleva lo que en otros formatos va en comentarios dispersos: aquí es parte del documento, con párrafos, y un programa puede enseñarlo o ignorarlo.

La plantilla

La plantilla hace explícito lo que el programa que carga la configuración da por supuesto:

Template (@stxt.template): com.acme.server
	Description >>
		Server Config: Configuración de un servicio del gateway
		Features: Interruptores de funcionalidad, uno por nodo
	Structure >>
		Server Config:
			Name: (1)
			Environment: (1) ENUM [dev, staging, production]
			Network: (1)
				Host: (1)
				Port: (1) NATURAL
				Public url: (?) URL
			Threads: (?)
				Min: (1) NATURAL
				Max: (1) NATURAL
			Timeouts: (?)
				Read ms: (?) NATURAL
				Write ms: (?) NATURAL
			Logging: (?)
				Level: (1) ENUM [DEBUG, INFO, WARN, ERROR]
				Format: (?) ENUM [text, json]
			Features: (?)
				Feature: (*)
					Enabled: (1) BOOLEAN
			Notes: (?) TEXT

Con ella, los errores típicos de configuración dejan de ser silenciosos (modelo de contenido cerrado):

  • Ports: 8080 (con una s de más) es CHILD_NOT_DECLARED, no una clave ignorada que deja al servicio escuchando en el puerto por defecto.
  • Port: 80a o Enabled: yes son INVALID_VALUE: un natural es un natural y un booleano es true o false.
  • Level: info en minúsculas no es INFO: el ENUM compara el valor tal cual.
  • Falta Network, o Host dentro de Network: TOO_FEW_CHILDREN.

La extensión de VS Code marca esos errores al escribir. En integración continua, stxt validate --recursive config/ hace la misma comprobación y detiene el despliegue de una configuración inválida (La línea de comandos).

Varios entornos, una estructura

Cuando la misma aplicación se configura para varios entornos, la tentación es copiar el fichero y cambiar valores. Con STXT se puede mantener un solo documento con un nodo por entorno, y la plantilla garantiza que todos declaran lo mismo:

Application Config (com.acme.app):
	App name: Billing

	Environments:
		Environment: dev
			Database:
				Url: jdbc:postgresql://localhost/dev
				Max connections: 5
			Debug: true
		Environment: staging
			Database:
				Url: jdbc:postgresql://staging/db
				Max connections: 10
			Debug: false
		Environment: production
			Database:
				Url: jdbc:postgresql://prod/db
				Max connections: 30
			Debug: false
Template (@stxt.template): com.acme.app
	Description >>
		Application Config: Configuración de una aplicación en todos sus entornos
	Structure >>
		Application Config:
			App name: (1)
			Environments: (1)
				Environment: (+)
					Database: (1)
						Url: (1)
						Max connections: (1) NATURAL
					Debug: (1) BOOLEAN

La diferencia entre staging y production es un diff de tres líneas, y un entorno al que le falte Database no valida. Si la aplicación prefiere un fichero por entorno, el mismo documento se parte en tres con el mismo namespace y la misma plantilla; la garantía no cambia.

Cómo lo lee el programa

El programa que carga la configuración no parsea texto: recibe un árbol. Con la biblioteca de su lenguaje recorre los nodos por nombre canónico —port, max-connections— y obtiene valores ya validados contra la plantilla: el código de carga convierte los valores, pero no comprueba rangos ni valores permitidos, porque eso ya ha pasado. Las guías de TypeScript, Java y Python muestran el recorrido; la resolución de la plantilla sigue la cadena de directorios .stxt/ de STXT-DISCOVERY-SPEC, igual que en el editor, así que validador y programa aplican la misma definición.

Límites

STXT describe la configuración; no la calcula. No hay variables, ni referencias a otros valores, ni inclusión de ficheros, ni expresiones: un valor es el texto que está escrito. Es una decisión de diseño (Principios de diseño), a cambio de que un fichero de configuración no pueda ejecutar nada ni depender de otro. La composición —un fichero base más uno por entorno— la hace la aplicación al cargar, de forma explícita.

Tampoco hay valores por defecto en la plantilla: un campo es obligatorio u opcional, y si es opcional y falta, es el programa quien decide qué vale.

Cómo se compara este uso con los formatos que más se eligen para configuración se desarrolla en STXT frente a YAML y STXT frente a JSON.