diff --git a/summercms/resources/application.conf b/summercms/resources/application.conf index 46242f8..6627315 100644 --- a/summercms/resources/application.conf +++ b/summercms/resources/application.conf @@ -5,6 +5,7 @@ server { port = ${?SERVER_PORT} } +# Database configuration for ZIO config (used by AppConfig) database { host = "localhost" host = ${?DB_HOST} @@ -17,3 +18,24 @@ database { password = "summercms" password = ${?DB_PASSWORD} } + +# HikariCP configuration for Quill DataSource +# Reads from "database" prefix via Quill.DataSource.fromPrefix +database { + dataSourceClassName = "org.postgresql.ds.PGSimpleDataSource" + dataSource { + serverName = "localhost" + serverName = ${?DB_HOST} + portNumber = 5432 + portNumber = ${?DB_PORT} + databaseName = "summercms" + databaseName = ${?DB_NAME} + user = "summercms" + user = ${?DB_USER} + password = "summercms" + password = ${?DB_PASSWORD} + } + # HikariCP pool settings + maximumPoolSize = 10 + connectionTimeout = 30000 +} diff --git a/summercms/src/db/QuillContext.scala b/summercms/src/db/QuillContext.scala new file mode 100644 index 0000000..d7a224b --- /dev/null +++ b/summercms/src/db/QuillContext.scala @@ -0,0 +1,52 @@ +package db + +import io.getquill.* +import io.getquill.jdbczio.Quill +import zio.* +import javax.sql.DataSource + +/** Quill PostgreSQL context with ZIO integration + * + * Provides compile-time SQL query validation via Quill. Exports two layers: + * - dataSourceLayer: HikariCP-managed connection pool configured from application.conf + * - quillLayer: Quill PostgreSQL context with SnakeCase naming strategy + * + * Usage: + * {{{ + * import db.QuillContext.* + * + * def findUser(email: String) = + * run(query[SummerUser].filter(_.email == lift(email))) + * .provide(quillLive) + * }}} + * + * IMPORTANT: Never use "io" as a variable name in files importing Quill + * (conflicts with io.getquill package). + */ +object QuillContext { + + /** DataSource layer from HikariCP configuration + * + * Reads configuration from "database" prefix in application.conf. + * HikariCP manages the connection pool. + */ + val dataSourceLayer: ZLayer[Any, Throwable, DataSource] = + Quill.DataSource.fromPrefix("database") + + /** Quill PostgreSQL context with snake_case naming + * + * Converts Scala camelCase field names to PostgreSQL snake_case columns. + * Example: passwordHash -> password_hash + */ + val quillLayer: ZLayer[DataSource, Nothing, Quill.Postgres[SnakeCase]] = + Quill.Postgres.fromNamingStrategy(SnakeCase) + + /** Combined layer for full Quill PostgreSQL access + * + * Provides both DataSource and Quill context. + * Use this when you need to run queries. + */ + val quillLive: ZLayer[Any, Throwable, Quill.Postgres[SnakeCase]] = + dataSourceLayer >>> quillLayer + +}