NEON pro JavaScript
Balíček @nette/neon čte a zapisuje NEON v JavaScriptu a TypeScriptu, v Node i v prohlížeči.
Díky němu:
- dekódujete konfigurační soubor do hodnot JavaScriptu a hodnoty zakódujete zpět do NEONu
- upravíte soubor tak, že každý komentář a mezera, na které nesáhnete, zůstanou na svém místě
- zkontrolujete soubory pomocí
neon-lintv editoru, v CI nebo po AI agentovi
Instalace
npm install @nette/neon
Jde o ES modul s typy pro TypeScript, pro Node 22 nebo novější či kterýkoliv současný prohlížeč, a nemá žádné
závislosti. API Node používá jen příkaz neon-lint.
Dekódování a kódování
Funkce decode() převede NEON na hodnoty JavaScriptu a encode() je převede zpět:
import { decode, encode } from '@nette/neon';
decode('roles: [guest, admin]'); // { roles: ['guest', 'admin'] }
encode({ roles: ['guest', 'admin'] }); // '{roles: [guest, admin]}'
encode({ roles: ['guest', 'admin'] }, true); // 'roles:\n\t- guest\n\t- admin\n\n'
Knihovna sama soubory nečte, soubor tedy načte Node:
import { readFileSync } from 'node:fs';
const config = decode(readFileSync('config.neon', 'utf8'));
Místo true může být druhým argumentem encode() funkce, která u každého pole rozhodne, zda ho
zapsat jako blok. Dostane pole a seznam klíčů, které k němu vedou:
encode(config, (value, path) => !path.length); // bloky jen v první úrovni
Hodnoty formátu se převedou na tyto hodnoty JavaScriptu:
| NEON | JavaScript |
|---|---|
null, true, yes … |
null, boolean |
| celé číslo | number; nad 253 bigint |
| desetinné číslo | number |
| řetězec | string |
| datum | NeonDate |
| entita, řetěz | Entity |
| sekvence | Array |
| mapování | obyčejný objekt |
NeonDate drží datum tak, jak bylo zapsané, včetně chybějící časové zóny; toDate(zone) ho
převede na Date. Mapování je obyčejný objekt jen s vlastními vlastnostmi, takže klíč jako
__proto__ je prostě klíč.
Dvě věci plynou ze samotného JavaScriptu. Desetinné číslo bez desetinné části, třeba 1.0, je stejné
number jako 1 a zapíše se zpět jako 1. A objekt uvádí klíče, které vypadají jako
celá čísla, první a vzestupně; syntaktický strom pořadí ze souboru
zachovává.
Chyby
Když vstup není platný NEON, decode() a parse() vyhodí NeonError. Jeho vlastnost
position obsahuje řádek a sloupec problému:
import { decode, NeonError } from '@nette/neon';
try {
decode('database:\n\thost: localhost\n\thost: db');
} catch (e) {
if (e instanceof NeonError) {
e.message; // "Duplicated key 'host'"
e.position.line; // 3
}
}
Úpravy souborů
Funkce parse() vrátí syntaktický strom souboru a přes něj soubor změníte tak, že jeho zbytek zůstane, jak
ho autor napsal:
import { readFileSync, writeFileSync } from 'node:fs';
import { parse } from '@nette/neon';
const doc = parse(readFileSync('config.neon', 'utf8'));
doc.setValue(['database', 'host'], 'db.example.com');
writeFileSync('config.neon', doc.print());
Jak položky měnit, přidávat, odebírat a přejmenovávat a jak se vyznat ve stromu, popisuje stránka Úpravy souborů.
Kontrola souborů: neon-lint
Balíček obsahuje příkaz neon-lint. Předáte mu soubory nebo adresáře a on vypíše jeden řádek pro
každý problém:
npx neon-lint config/
config/local.neon:3:2: Duplicated key 'user'
Příkaz, jeho volby i návratové kódy jsou stejné jako v knihovně pro PHP. Bez instalace balíčku ho spustíte
jako npx --package=@nette/neon neon-lint config/.
AI agent, který ho spustí po každé změně souboru .neon, se o rozbitém souboru dozví hned. Návod pro AI agenty ukazuje, jak ho nastavit jako
hook, a funguje bez ohledu na jazyk projektu.
Další příklady, každý se skutečným výstupem, najdete v repozitáři knihovny.