Formats
The seven config formats tyfigo reads and how each one is typed.
tyfigo reads seven formats under eight suffixes, since YAML takes both .config.yaml and .config.yml.
| Suffix | Format | Parser |
|---|---|---|
.config.yaml, .config.yml | YAML | yaml |
.config.toml | TOML | toml-eslint-parser |
.config.jsonc | JSONC | jsonc-parser |
.config.json5 | JSON5 | jsonc-eslint-parser |
.config.ini | INI | tyfigo |
.config.properties | .properties | tyfigo |
.config.xml | XML | @rgrove/parse-xml |
In a .config directory, the plain extensions (.yaml, .yml, .toml, .jsonc,
.json5, .ini, .properties, .xml) pick the same formats: .config/app.toml is TOML. Type-checking those files means
giving tyfigo the plain extensions in tsconfig.json, and then any other file with one of them is typed as plain data with the
same parser and rules, but without layers or placeholders.
Plain JSON
tyfigo can't read .json files: .json is built into TypeScript, so no content mapper can claim .json, .config.json or
.config/<name>.json. tsc rejects them in tsconfig.json:
error TS18066: Content mapper file extension '.config.json' is a built-in extension and cannot be registered by a content mapper.Rename the file to .config.jsonc (or .config/<name>.jsonc) instead. Every JSON file is valid JSONC, so nothing else changes.
Every parser keeps the position of each key and value, which is how errors point at a line and column. An empty file is {}.
A duplicate key is an error in every format. The typing rules on Type checking apply to all of them:
strings, numbers and booleans are widened, arrays are readonly T[], and everything is readonly.
YAML
Typed values as YAML reads them: numbers, booleans, null, strings, sequences and mappings. Anchors and aliases work. A file
with several documents (---) is a parse error.
server:
port: ${PORT:-3000}
hosts: [a.example.com, b.example.com]TOML
Tables are objects and arrays are arrays. Placeholders go in strings: port = "${PORT:-3000}".
log_level = "debug"
[server]
port = "${PORT:-3000}"
idle_timeout = 10JSONC and JSON5
JSONC is JSON with comments and trailing commas. JSON5 adds unquoted keys, single quotes and more. Placeholders go in strings.
{
// comments are fine
"port": "${PORT:-3000}",
"compression": false,
}INI, .properties and XML
These formats store only text, so tyfigo reads every unquoted value with one rule:
trueandfalseare booleans.- A number is a number only when JavaScript prints it back as the same text:
8080and-1.5are numbers,08080,1.50and1e3stay strings. - Anything else is a string, and an empty value is
''.
INI
; comment
name = api
port = 3000
[db]
url = "postgres://localhost/app" ; inline comment
version = '1.50'
[server.http]
hosts[] = a.example.com
hosts[] = b.example.com
debug = false// {
// readonly name: string; readonly port: number;
// readonly db: { readonly url: string; readonly version: string };
// readonly server: { readonly http: { readonly hosts: readonly string[]; readonly debug: boolean } };
// }[a.b]sections nest. A section that appears twice is merged.key[] = valuelines build an array.;and#start a comment at the start of a line or after whitespace, sohttp://x/#fragis kept.- Quoted values are always strings. Double quotes use JSON escapes; single quotes are literal.
.properties
# comment
! also a comment
name = api
port=3000
db.url: postgres://localhost/app
db.pool 5
message = hello \
world
dotted\.key = 1.50// {
// readonly name: string; readonly port: number;
// readonly db: { readonly url: string; readonly pool: number };
// readonly message: string; readonly "dotted.key": string;
// }- Keys and values are separated by
=,:or whitespace. - Dots in keys nest (
db.urlisdb: { url }); an escaped\.keeps the dot in the key. - A trailing
\continues the line.\uXXXX,\t,\nand the other Java escapes work.
XML
<config env="prod" debug="true">
<name>api</name>
<port>3000</port>
<db url="postgres://localhost/app" pool="5"/>
<tags><tag>a</tag><tag>b</tag></tags>
<server host="a">text & more</server>
</config>// {
// readonly config: {
// readonly "@env": string; readonly "@debug": boolean;
// readonly name: string; readonly port: number;
// readonly db: { readonly "@url": string; readonly "@pool": number };
// readonly tags: { readonly tag: readonly string[] };
// readonly server: { readonly "@host": string; readonly "#text": string };
// };
// }- The root element is the top-level key.
- Attributes become
@namekeys. - An element with only text is a value. An element with attributes or children is an object, and its text is
#text. - A child element that appears more than once is an array. One that appears once is not, so keep repeated items repeated in the base file.
- An empty element is
''. CDATA is text.