Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/glguy/config-schema

Self-documenting, combinator constructed configuration schemas
https://github.com/glguy/config-schema

configuration haskell schema

Last synced: 3 months ago
JSON representation

Self-documenting, combinator constructed configuration schemas

Awesome Lists containing this project

README

        

config-schema
=============

[![Hackage](https://img.shields.io/hackage/v/config-schema.svg)](https://hackage.haskell.org/package/config-schema)

Live Demo
--------

The config-value and config-schema packages are available in a [live demo](https://glguy.net/config-demo/).

About
--------

This package allows the user to define configuration schemas suitable for
matching against configuration files written in the
[config-value](https://hackage.haskell.org/package/config-value) format.
These schemas allow the user to extract an arbitrary Haskell value from
an interpretation of a configuration file. It also allows the user to
programatically generate documentation for the configuration files
accepted by the loader.

```haskell
{-# Language OverloadedStrings, ApplicativeDo #-}
module Example where

import qualified Data.Text as Text
import Data.Text (Text)
import Data.Monoid ((<>))
import Data.Functor.Alt (())
import Data.List.NonEmpty (NonEmpty)

import Config
import Config.Schema

exampleFile :: Text
exampleFile =
" name: \"Johny Appleseed\" \n\
\ age : 99 \n\
\ happy: yes \n\
\ kids: \n\
\ * name: \"Bob\" \n\
\ * name: \"Tom\" \n"

exampleValue :: Value Position
Right exampleValue = parse exampleFile

exampleSpec :: ValueSpec Text
exampleSpec = sectionsSpec "" $
do name <- reqSection "name" "Full name"
age <- reqSection "age" "Age of user"
happy <- optSection' "happy" yesOrNo
"Current happiness status"
kids <- reqSection' "kids" (oneOrList kidSpec)
"All children's names"

return $
let happyText = case happy of Just True -> " and is happy"
Just False -> " and is not happy"
Nothing -> " and is private"

in name <> " is " <> Text.pack (show (age::Integer)) <>
" years old and has kids " <>
Text.intercalate ", " kids <>
happyText

kidSpec :: ValueSpec Text
kidSpec = sectionsSpec "kid" (reqSection "name" "Kid's name")

-- | Matches the 'yes' and 'no' atoms
yesOrNo :: ValueSpec Bool
yesOrNo = True <$ atomSpec "yes"
False <$ atomSpec "no"

printDoc :: IO ()
printDoc = print (generateDocs exampleSpec)
-- *Example> printDoc
-- Top-level configuration file fields:
-- name: REQUIRED text
-- Full name
-- age: REQUIRED integer
-- Age of user
-- happy: `yes` or `no`
-- Current happiness status
-- kids: REQUIRED kid or list of kid
-- All children
--
-- kid
-- name: REQUIRED text
-- Kid's name

example :: Either (NonEmpty (LoadError Position)) Text
example = loadValue exampleSpec exampleValue
-- *Example> exampleVal
-- Right "Johny Appleseed is 99 years old and has kids Bob, Tom and is happy"
```