28.02.2024

Apple опубликовал Pkl, язык программирования для определения конфигурации

Компания Apple открыла реализацию языка программирования Pkl, предназначенного для определения конфигурации и продвигающего модель «конфигурация как код». Связанный с Pkl инструментарий написан на Kotlin и опубликован под лицензией Apache. Плагины для работы с кодом на языке Pkl подготовлены для сред разработки IntelliJ, Visual Studio Code и Neovim. В ближайшее время ожидается публикация обработчика LSP (Language Server Protocol).

Pkl сочетает свойства простого для восприятия декларативного языка c расширенными возможностями, свойственными для языков общего назначения. В языке поддерживаются аннотации типов, классы, функции, вычислительные выражения, условия и циклы. Pkl может применяться как для генерации статических конфигураций в разных форматах, таких как JSON, YAML, XML и простой список свойств, так для формирования модулей для обработки заданных форматов конфигурации в приложениях на различных языках программирования.

Привязки для интеграции Pkl в приложения подготовлены для Java, Kotlin, Go и Swift. Отдельно предложен модуль для интеграции с фреймворком Spring. Привязки позволяют на основе конфигурации на языке Pkl сформировать готовые пакеты и модули с классами для работы с описанной конфигурацией в приложения на языках Java, Kotlin, Go и Swift. Пакеты с описанием конфигурации могут публиковаться в репозиториях и импортироваться в качестве зависимости, что допускает совместное использование кода 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 } }

Источник: https://www.opennet.ru/opennews/art.shtml?num=60549 Источник.