Das Konfigurationsformat CASC
CASC ist eine Konfigurationssprache mit echter Spezifikation: verschachtelte Blöcke, typisierte Werte von Zeitdauern bis zu IP-Bereichen, Variablen, Umgebungszugriffe, Verweise auf andere Schlüssel, Imports und Schleifen — in einer Syntax, die als Klartext lesbar bleibt.
Ein erster Blick
Eine CASC-Datei ist eine Folge von Anweisungen, die zusammen einen Baum benannter Werte ergeben. Diese hier liest eine Umgebungsdatei, einige Umgebungsvariablen und eine gemeinsame Variable und verweist von einem Schlüssel auf zwei andere:
#@version = 1.0
import "env/${COOPER_ENV}.casc"
@region = ${REGION:"eu-west"}
server {
host = "0.0.0.0"
port = !int(${PORT:8080})
}
database {
host = "db.@{region}.internal"
*password = ${DB_PASSWORD:?"DB_PASSWORD is required"}
timeout = 500ms
cache = 512MiB
}
health.url = "http://%{server.host}:%{server.port}/health"#@version = 1.0— jede Datei beginnt mit ihrer Formatversion.importholt eine weitere Datei hinzu; ihr Pfad darf die Umgebung lesen.${COOPER_ENV}nennt in jeder Implementierung die aktuelle Umgebung, etwadevoderprod.@regionist eine Variable,${…}liest die Umgebung,%{…}verweist auf einen anderen Schlüssel des fertigen Baums.500msund512MiBsind Werte eigenen Typs, keine Zeichenketten, die später noch geparst werden müssen.*passwordist als geheim markiert: der Wert bleibt überall geschwärzt, wo er landet.:?"…"macht eine fehlende Umgebungsvariable zu einem Ladefehler mit eigener Meldung.
Gestaltung
- Eine Art von Map. Block und Punkt-Pfad sind zwei Schreibweisen desselben Baums, und doppelt geschriebene Blöcke werden zusammengeführt.
- Typisierte Literale. Zeitdauern, Bytegrößen, Datum und Uhrzeit, IP-Adressen und Tupel sind Werte der Sprache selbst.
- Drei Verweisarten, eine Grammatik.
@{}für Variablen,${}für die Umgebung und%{}für Konfigurationspfade teilen sich Defaults, Wächter, Indizes und Filter. - Ausdrückliches Zusammenführen. Spätere Zuweisungen gewinnen, Blöcke werden tief gemischt; die Sigils
~,+und-ersetzen, hängen an und entfernen, wenn genau das gemeint ist. - Nichts Unbekanntes rutscht durch. Ein Tag, Resolver oder Import-Schema, das niemand registriert hat, ist ein Ladefehler, der es beim Namen nennt.
- Geheimnisse in der Syntax. Ein
*am Schlüssel markiert den Wert als geheim, und wer ihn interpoliert, erhält ein ebenfalls geschwärztes Ergebnis. - Überall dieselbe Bedeutung. Ein Dokument ergibt in jeder Implementierung dieselbe Konfiguration, und ein abgelehntes scheitert mit derselben Fehlerkategorie.
Der Name ist ein Wortspiel: Ein Cooper ist ein Böttcher, und ein „casc“ ist ein Fass. Das Format ist das, was im Fass steckt.
Eckdaten
| Eigenschaft | Wert |
|---|---|
| Endung | .casc |
| Kodierung | UTF-8 |
| Kopfzeile | #@version = 1.0 — Pflicht, in jeder Datei; davor dürfen nur Kommentare und Leerzeilen stehen |
| Kommentare | # gefolgt von einem Leerzeichen, bis zum Zeilenende |
| Ergebnis | Ein Baum: Blöcke sind Maps, Blätter typisierte Werte |
| Grammatik | PEG, geschrieben in Aether — siehe Grammatik |
| Implementierungen | Elixir (die Referenz), Node.js, PHP, Praxis |
Coopers README beginnt, wie die der anderen Implementierungen, mit einer Warnung: Die Bibliothek ist in starker Entwicklung und vor 1.0.0 nicht für den Produktiveinsatz gedacht. Bis dahin können sich die Bibliotheken und die Spezifikation zwischen zwei beliebigen Releases ändern; deshalb ist CASC hier als in Entwicklung markiert. Die Formatversion bleibt 1.0.
Implementierungen und Werkzeuge
Diese Seiten beschreiben das Format. Vier Implementierungen lesen es — in Elixir, Node.js, PHP und Praxis —, und zu jeder gehören Bibliotheken, die das Ergebnis an eine Anwendung oder ein Framework weitergeben. Wie sie das Format laden oder bereitstellen, steht jeweils in deren eigener Dokumentation.
| Name | Sprache | Rolle |
|---|---|---|
| cooper | Elixir | Die Referenzimplementierung (Hex: cooper 0.7.0) |
| cooper_config | Elixir | Nutzt eine CASC-Datei als Konfiguration eines Mix-Projekts oder Releases (Hex: cooper_config 0.5.1) |
| node-cooper | Node.js | Der Port für Node.js (npm: @joetjen/cooper 0.2.2) |
| node-cooper-config | Node.js | Lädt die Konfiguration einer Anwendung einmal beim Start und gibt dem Programm Funktionen, um sie zu lesen (npm: @joetjen/cooper-config 0.2.1) |
| node-cooper-fastify | Node.js | Fastify-Plugin: die Konfiguration unter fastify.config, die Optionen des Servers selbst aus demselben Dokument (npm: @joetjen/cooper-fastify 0.2.1) |
| node-cooper-nestjs | Node.js | NestJS-Modul, das die Konfiguration an @nestjs/config übergibt (npm: @joetjen/cooper-nestjs 0.2.1) |
| php-cooper | PHP | Der Port für PHP (Packagist: joetjen/cooper 0.2.1) |
| php-cooper-config | PHP | Lädt die Konfiguration einer Anwendung einmal beim Start und gibt ihr Funktionen, um sie zu lesen (Packagist: joetjen/cooper-config 0.3.1) |
| php-cooper-laravel | PHP | Laravel-Integration: config/config.casc ersetzt config/*.php (Packagist: joetjen/cooper-laravel 0.2.1) |
| php-cooper-symfony | PHP | Symfony-Integration: ein CASC-Dokument ersetzt config/packages/*.yaml für Bundle-Konfiguration und Container-Parameter (Packagist: joetjen/cooper-symfony 0.2.1) |
| cooper | Praxis | Der Port für Praxis, aus derselben Grammatik erzeugt; Teil des Praxis-Repositorys, noch nicht eigenständig veröffentlicht |
| cooper_prx | Praxis | Liest die config.casc eines Praxis-Projekts in die Anwendungsumgebung |
| cooper_conformance | Praxis | Die Konformitätssuite: dieselben Dokumente durch jede Implementierung, jede Abweichung benannt |
| CASC for VS Code | TypeScript | Syntaxhervorhebung, Snippets und ein Language Server — Definitionen, Hover, Vervollständigung, Gliederung und Diagnosen über Imports hinweg. Version 0.2.0, noch nicht im VS Code Marketplace oder bei Open VSX veröffentlicht |
| ichor | Elixir | Der Grammatik-Compiler, mit dem die Parser für Elixir und Praxis erzeugt werden |
Die Parser für Node.js und PHP sind von Hand geschrieben und übertragen die Grammatik Regel für Regel. Die Konformitätssuite schickt einen gemeinsamen Satz von Dokumenten durch alle vier Implementierungen und vergleicht jedes Ergebnis exakt, jede Ablehnung anhand ihrer Fehlerkategorie.
Auf diesen Seiten
- Aufbau — Kopfzeile, Kommentare, Schlüssel, Blöcke, Zusammenführen.
- Werte — alle Literal-Typen.
- Verweise — Variablen, Umgebung, Konfigurationspfade, Filter, Tags.
- Imports und Schleifen — Konfiguration aufteilen und erzeugen, mit einem vollständigen Beispiel.
- Grammatik — die formale Grammatik, die Fehlerkategorien und wo die Implementierungen noch von der Spezifikation abweichen.