Pkl сочетает свойства простого для восприятия декларативного языка c расширенными возможностями, свойственными для языков общего назначения. В языке поддерживаются аннотации типов, классы, функции, вычислительные выражения, условия и циклы. Pkl может применяться как для генерации статических конфигураций в разных форматах, таких как JSON, YAML и XML, так для формирования модулей для обработки заданных форматов конфигурации в приложениях на различных языках программирования.
Привязки для интеграции Pkl в приложения подготовлены для Java, Kotlin, Go и Swift. Отдельно предложен модуль для интеграции с фреймворком Spring. Привязки позволяют на основе конфигурации на языке Pkl сформировать готовые пакеты и модули с классами для работы с описанной конфигурацией в приложении. Пакеты с описанием конфигурации могут публиковаться в репозиториях и импортироваться в качестве зависимости, что допускает совместное использование кода Pkl между разными проектами.
Язык предоставляет гибкие средства для определения условий и проверок корректности значений, позволяющих выявлять ошибки в итоговой конфигурации на этапе до её применения в приложении. Например, можно определить допустимый диапазон значений («port: Int(this > 1000)» или «age: Int(isBetween(0, 130))»), обязательность или необязательность заполнения и формат («zipCode: String(matches(Regex(«\d{5}»)))»). В случае присвоения значения, не соответствующего условию, валидатор выведет ошибку (например, при попытке присвоить значение 1001 параметру, определённому как «Int(this > 1000)»).
Например, на языке Pkl можно написать модуль Application.pkl с шаблоном конфигурации подключения к СУБД:
module Application hostname: String port: UInt16 environment: Environment database: Database class Database { username: String password: String host: String port: UInt16 dbName: String } typealias Environment = "dev"|"qa"|"prod"
Далее можно создать непосредственно файл конфигурации, использующий данный модуль для проверки корректности значений:
amends "Application.pkl" hostname = "localhost" port = 3599 environment = "dev" database { host = "localhost" port = 5786 username = "admin" password = read("env:DATABASE_PASSWORD") dbName = "myapp" }
А также написать генератор для автоматизации изменения номера порта для четырёх разных СУБД:
import "Application.pkl" hidden db: Application.Database = new { host = "localhost" username = "admin" password = read("env:DATABASE_PASSWORD") dbName = "myapp" } sidecars { for (offset in List(0, 1, 2, 3)) { (db) { port = 6000 + offset } } }
При желании можно экспортировать конфигурацию в другом формате, например, YAML:
sidecars: - username: admin password: hunter2 host: localhost port: 6000 dbName: myapp - username: admin password: hunter2 host: localhost port: 6001 dbName: myapp - username: admin password: hunter2 host: localhost port: 6002 dbName: myapp - username: admin password: hunter2 host: localhost port: 6003 dbName: myapp
Схема конфигурации на языке Pkl также может быть преобразована в классы или структуры для встраивания в код приложения. Например, можно сгенерировать привязку для Kotlin:
import kotlin.Int import kotlin.Long import kotlin.String data class Application( val hostname: String, val port: Int, val environment: Environment, val database: Database ) { data class Database( val username: String, val password: String, val host: String, val port: Int, val dbName: String ) enum class Environment( val value: String ) { DEV("dev"), QA("qa"), PROD("prod"); override fun toString() = value } }
Источник: http://www.opennet.ru/opennews/art.shtml?num=60549