v0.4.0

bconf

An enhanced data-serialization format for better configuration files

Read the spec
// This is a bconf file

@extends "./base.bconf"
$app_env = env("APP_ENV")

title = "bconf example"
env = $app_env

admins = [
    { name = "John Doe"; email = "john@example.com" },
    { name = "Jane Smith"; email = "jane@example.com" }
]

admins[0] = {
    name = "Cooler John Doe"
    email = "coolerjohn@example.com"
}

server {
    port = env("PORT")
    timeout_ms = 30_000
    cors {
        enabled
        allowed_origins = ["https://example.com", "https://${$app_env}.example.com"]
    }
}

server.max_connections = 4

Composable

bconf is designed with a single objective in mind: make it easy to compose large or complex configurations.

It is trivial to breakdown and organize large objects or arrays into more manageable chunks.

Flexible

Built-in dynamic features such as reading an environment variable, extended files and importing/exporting variables use generic syntax.

This means it is easy to implement custom modifiers and directives to enable common logic specific for your needs.

Simple

At its core, bconf is not inventing anything new. The syntax and features should be familiar to anyone who has programmed.

A Quick Overview

Strings

Strings can either be single-line or multi-line. A multi-line string uses three quotation marks as its delimiter and allows for raw tabs and newline characters

single_line = "The quick brown fox jumps over the lazy dog"
multi_line = """
    Roses are red,
    Violets are blue
"""

Both single- and multi-line support escape sequences and embedded values. Almost any value can be used as an embedded value

$root = "/Users/brody"
path = "${$root}/projects/bconf/src"

Variables

Keys that start with a dollar sign ($) are a mutable variable. If they start with two dollar signs ($$) they are a constant and cannot be reassigned. Variables can be used as a value and their value will be deeply copied

$$PORT = 8080
$domain = "https://example.com"
config.domain = $domain
config.port = $$PORT

Variable keys will not appear in the resolved hash-map

// $config will not appear in the output
$config = { domain = "https://example.com"; port = 8080 }

Resolvers

Resolvers are basically just if-else statements, allowing for a single key to have a different value if certain criteria is met. Branches are evaluated first to last and are lazily evaluated when parsing. They are enclosed in parentheses (()), with branches separated by a pipe (|)

auth.token_expiry = (
	| eq(env("APP_ENV"), "prod") => "1hr"
	| "6hr"
)

Modifiers

Modifiers are simply function calls. They can take any arbitrary number of arguments and must always return a value. They are evaluated when parsing. Arguments are enclosed with parentheses (()) and must have a leading identifier

// The final value will be `trim = "modifier example"`
title = trim("    modifier example       ")

Directives

Identifiers that start with an at-symbol (@) are a directive. Directives take any number of arguments which are provided as the unevaluated input. Bare identifiers are allowed as arguments. A directive can return a value and/or modify the document

// Will insert the resolved value of the "./base.bconf" file
@extends "./base.bconf"
config.port = 8080

More bconf

bconf supports more values, features, syntax, and many built-in modifiers and directives

Read the full spec