diff --git a/.github/workflows/publish-gh-pages.yml b/.github/workflows/publish-gh-pages.yml new file mode 100644 index 0000000..1305908 --- /dev/null +++ b/.github/workflows/publish-gh-pages.yml @@ -0,0 +1,30 @@ +name: Docs for db-messiah-extra + +on: + push: + +permissions: + contents: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up JDK 19 + uses: actions/setup-java@v4 + with: + java-version: 19 + distribution: 'adopt' + + - name: Build documentation + run: ./gradlew dokkaHtml + + - name: Publish documentation + uses: JamesIves/github-pages-deploy-action@releases/v4 + with: + BRANCH: gh-pages + FOLDER: build/dokka/html diff --git a/README.md b/README.md index 348fd4b..e279917 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,27 @@

db-messiah-extra

Extra Utils for Db Messiah, kotlin lib. for enterprise database development

+

+ readme code snippets are + autogenerated + and + tested
+ +15 e2e tests with 100% instruction coverage +



- - + @@ -20,35 +33,39 @@

Get started

```kotlin -implementation("com.urosjarc:db-messiah-extra:0.0.1") +implementation("com.urosjarc:db-messiah-extra-extra:0.0.1") ``` -

DB Serializers

+

Domain

```kotlin -/** SQLITE */ - -val sqliteSerializer = SqliteSerializer( - globalSerializers = BasicTS.sqlite + KotlinxTimeTS.sqlite, - ... +@Serializable +data class MyTable( + @Contextual + val pk: UUID = UUID.randomUUID(), + val instant: kotlinx.datetime.Instant, + val localDate: kotlinx.datetime.LocalDate, + val localTime: kotlinx.datetime.LocalTime, ) -/** POSTGRESQL */ +``` +

DB Serializers

+ +```kotlin val sqliteSerializer = SqliteSerializer( globalSerializers = BasicTS.sqlite + KotlinxTimeTS.sqlite, - ... + tables = listOf(Table(MyTable::pk)), ) ```

JSON Serializers

- ```kotlin /** JSON */ val json = Json { - serializersModule = SerializersModule { + serializersModule = SerializersModule { contextual(InstantJS) contextual(LocalDateJS) contextual(LocalTimeJS) @@ -56,30 +73,89 @@ val json = Json { } } -val jsonStr = json.encodeToString(...) -val obj = json.decodeFromString<...>(...) - -/** KTOR */ -install(ContentNegotiation) { - json(Json { - serializersModule = SerializersModule { - contextual(InstantJS) - contextual(LocalDateJS) - contextual(LocalTimeJS) - contextual(UUIDJS) - } - }) +val dtNow = Clock.System.now().toLocalDateTime(timeZone = TimeZone.UTC) +val myTable = MyTable( + instant = Clock.System.now(), + localDate = dtNow.date, + localTime = dtNow.time +) + +val jsonStr = json.encodeToString(myTable) +val obj = json.decodeFromString(jsonStr) +assert(obj == myTable) + +/** KTOR */ +embeddedServer(Netty, port = 8080, host = "0.0.0.0") { + install(ContentNegotiation) { + json(Json { + serializersModule = SerializersModule { + contextual(InstantJS) + contextual(LocalDateJS) + contextual(LocalTimeJS) + contextual(UUIDJS) + } + }) + } } ``` -

Features

+

Specifications

+ +| Class | COLUMN | Databases | db-messiah-extra | JSON | +|:-------------:|:------------:|:------------------------------------:|:---------------------------:|:-----------:| +| Instant | DATETIME | Sqlite, Mysql, MSSql, Maria, H2, DB2 | KotlinxInstantTS. DATETIME | InstantJS | +| Instant | TIMESTAMP | Derby, Postgres, Oracle | KotlinxInstantTS. TIMESTAMP | InstantJS | +| LocalDateTime | :x: | :x: | :x: | :x: | +| LocalDate | DATE | :white_check_mark: | KotlinxLocalDateTS. DATE | LocalDateJS | +| LocalTime | TIME | :white_check_mark: but Oracle | KotlinxTimeTS.TIME | LocalDateJS | +| LocalTime | NUMBER(8, 0) | Oracle | KotlinxTimeTS. NUMBER8 | LocalTimeJS | +| UUID | db-messiah | db-messiah | db-messiah | UUIDJS | -| Class | COLUMN | Databases | db-messiah-extra | JSON | -|:---------:|:------------:|:------------------------------------:|:---------------------------:|:-----------:| -| Instant | DATETIME | Sqlite, Mysql, MSSql, Maria, H2, DB2 | KotlinxInstantTS. DATETIME | InstantJS | -| Instant | TIMESTAMP | Derby, Postgres, Oracle | KotlinxInstantTS. TIMESTAMP | InstantJS | -| LocalDate | DATE | :white_check_mark: | KotlinxLocalDateTS. DATE | LocalDateJS | -| LocalTime | TIME | :white_check_mark: but Oracle | KotlinxTimeTS.TIME | LocalDateJS | -| LocalTime | NUMBER(8, 0) | Oracle | KotlinxTimeTS. NUMBER8 | LocalTimeJS |> -| UUID | db-messiah | db-messiah | db-messiah | UUIDJS |> +

Arhitecture

+ +```text +src/main/kotlin/com/urosjarc/dbmessiah/extra/ +|-- kotlinx +| |-- InstantJS.kt............| java.time.Instant serializer for kotlinx.serialization +| |-- LocalDateJS.kt..........| java.time.LocalDate serializer for kotlinx.serialization +| |-- LocalTimeJS.kt..........| java.time.LocalTime serializer for kotlinx.serialization +| `-- UUIDJS.kt...............| java.utils.UUID serializer for kotlinx.serialization +`-- serializers + |-- KotlinxInstantTS.kt.....| kotlinx.datetime.Instant type serializer for db-messiah + |-- KotlinxLocalDateTS.kt...| kotlinx.datetime.LocalDate type serializer for db-messiah + |-- KotlinxLocalTimeTS.kt...| kotlinx.datetime.LocalTime type serializer for db-messiah + `-- KotlinxTimeTS.kt........| kotlinx.datetime.Time type serializer for db-messiah +``` + +

Sources

+ +```text +src/ +|-- main...............................| Already described in architecture. +`-- test + |-- kotlin + | |-- impl + | | |-- Test_Contract.kt.......| Testing interface for all db tests. + | | |-- Test_Db2.kt + | | |-- Test_Derby.kt + | | |-- Test_H2.kt + | | |-- Test_Maria.kt + | | |-- Test_Mssql.kt + | | |-- Test_Mysql.kt + | | |-- Test_Oracle.kt + | | |-- Test_Postgresql.kt + | | `-- Test_Sqlite.kt + | |-- Test_InstantJS.kt + | |-- Test_LocalDateJS.kt + | |-- Test_LocalTimeJS.kt + | |-- Test_README.kt.............| Code from where README.md is generated. + | |-- Test_README.md.............| Template from where README.md is generated. + | |-- Test_UUIDJS.kt + | `-- utils + | |-- domain.kt + | |-- Schemas.kt + | `-- Serializers.kt + `-- resources + `-- log4j2.xml +``` diff --git a/build.gradle.kts b/build.gradle.kts index 0aa03bb..0b3f8bd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,5 @@ import org.jetbrains.dokka.DokkaConfiguration.Visibility import java.lang.Thread.sleep -import java.net.URI val GPG_PRIVATE_KEY = System.getenv("GPG_PRIVATE_KEY") val GPG_PRIVATE_PASSWORD = System.getenv("GPG_PRIVATE_PASSWORD") @@ -111,6 +110,12 @@ dependencies { testImplementation("org.apache.logging.log4j:log4j-slf4j2-impl:2.20.0") testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("com.urosjarc:db-messiah:$dbMessiah") + + val ktor_version = "2.3.8" + testImplementation("io.ktor:ktor-server-core-jvm:$ktor_version") + testImplementation("io.ktor:ktor-server-netty-jvm:$ktor_version") + testImplementation("io.ktor:ktor-server-content-negotiation:$ktor_version") + testImplementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") } tasks.test { @@ -166,3 +171,43 @@ publishing { } } + +tasks.register("readme") { + group = "verification" + description = "Create README.md tests." + this.tasks = listOf("test") + + doLast { + val templateLines = File("./src/test/kotlin/Test_README.kt").readLines() + var readme = File("./src/test/kotlin/Test_README.md").readText() + + val dependencies = mutableListOf( + "implementation(\"${project.group}:${project.name}-extra:$version\")", + ) + + val readmeMap: MutableList>> = mutableListOf( + "// START 'Dependencies'" to dependencies, + ) + + + var active = false + var indent = "" + templateLines.forEach { + if (it.contains("// START '")) { + indent = it.split("//").first() + active = true + readmeMap.add(it.replaceFirst(indent, "") to mutableListOf()) + } else if (it.contains("// STOP")) { + active = false + } else if (active) { + readmeMap.last().second.add(it.replaceFirst(indent, "")) + } + } + + readmeMap.forEach { (key, value) -> + readme = readme.replace(oldValue = key, newValue = value.joinToString("\n")) + } + + File("README.md").writeText(readme) + } +} diff --git a/src/test/kotlin/Test_README.kt b/src/test/kotlin/Test_README.kt new file mode 100644 index 0000000..7d26c1a --- /dev/null +++ b/src/test/kotlin/Test_README.kt @@ -0,0 +1,114 @@ +import com.urosjarc.dbmessiah.domain.Table +import com.urosjarc.dbmessiah.extra.kotlinx.InstantJS +import com.urosjarc.dbmessiah.extra.kotlinx.LocalDateJS +import com.urosjarc.dbmessiah.extra.kotlinx.LocalTimeJS +import com.urosjarc.dbmessiah.extra.kotlinx.UUIDJS +import com.urosjarc.dbmessiah.extra.serializers.KotlinxTimeTS +import com.urosjarc.dbmessiah.impl.sqlite.SqliteSerializer +import com.urosjarc.dbmessiah.impl.sqlite.SqliteService +import com.urosjarc.dbmessiah.serializers.BasicTS +import io.ktor.serialization.kotlinx.json.* +import io.ktor.server.application.* +import io.ktor.server.engine.* +import io.ktor.server.netty.* +import io.ktor.server.plugins.contentnegotiation.* +import kotlinx.datetime.Clock +import kotlinx.datetime.LocalDate +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime +import kotlinx.serialization.Contextual +import kotlinx.serialization.Serializable +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import kotlinx.serialization.modules.SerializersModule +import kotlinx.serialization.modules.contextual +import java.util.* +import kotlin.test.Test + +// START 'Domain' +@Serializable +data class MyTable( + @Contextual + val pk: UUID = UUID.randomUUID(), + val instant: kotlinx.datetime.Instant, + val localDate: kotlinx.datetime.LocalDate, + val localTime: kotlinx.datetime.LocalTime, +) + +// START 'DB Serializers' +val sqliteSerializer = SqliteSerializer( + globalSerializers = BasicTS.sqlite + KotlinxTimeTS.sqlite, + tables = listOf(Table(MyTable::pk)), +) +// STOP + +val config = Properties().apply { + this["jdbcUrl"] = "jdbc:sqlite::memory:" + this["username"] = "root" + this["password"] = "root" +} + +val sqlite = SqliteService( + config = config, + ser = sqliteSerializer +) + +fun main() { + sqlite.autocommit { + it.table.create() + val dateTime = Clock.System.now().toLocalDateTime(timeZone = TimeZone.UTC) + val myTable = MyTable( + instant = Clock.System.now(), + localDate = dateTime.date, + localTime = dateTime.time + ) + it.row.insert(row = myTable) + val myTables = it.table.select() + println(myTables.first().pk == myTable.pk) + } + // START 'JSON Serializers' + /** JSON */ + + val json = Json { + serializersModule = SerializersModule { + contextual(InstantJS) + contextual(LocalDateJS) + contextual(LocalTimeJS) + contextual(UUIDJS) + } + } + + + val dtNow = Clock.System.now().toLocalDateTime(timeZone = TimeZone.UTC) + val myTable = MyTable( + instant = Clock.System.now(), + localDate = dtNow.date, + localTime = dtNow.time + ) + + val jsonStr = json.encodeToString(myTable) + val obj = json.decodeFromString(jsonStr) + assert(obj == myTable) + + /** KTOR */ + embeddedServer(Netty, port = 8080, host = "0.0.0.0") { + install(ContentNegotiation) { + json(Json { + serializersModule = SerializersModule { + contextual(InstantJS) + contextual(LocalDateJS) + contextual(LocalTimeJS) + contextual(UUIDJS) + } + }) + } + } + // STOP +} + +class Test_README { + @Test + fun `test README`() { + main() + } +} diff --git a/src/test/kotlin/Test_README.md b/src/test/kotlin/Test_README.md new file mode 100644 index 0000000..6803b4e --- /dev/null +++ b/src/test/kotlin/Test_README.md @@ -0,0 +1,115 @@ +

db-messiah-extra

+

Extra Utils for Db Messiah, kotlin lib. for enterprise database development

+

+ readme code snippets are + autogenerated + and + tested
+ +15 e2e tests with 100% instruction coverage +

+
+
+
+

db-messiah

Kotlin lib. for enterprise database development

+ +

Get started

+

Specifications

+

Arhitecture

+

Documentation

+

db-analyser

GUI for db analysis, to help you create complex JOIN statements for SQL or db-messiah.

+ + + + + +
+

db-messiah

+

Kotlin lib. for enterprise database development

+
+

Get started

+

Specifications

+

Arhitecture

+

Documentation

+
+

db-analyser

+

GUI for db analysis, to help you create complex JOIN statements for SQL or db-messiah. +

+
+
+ +

Get started

+ +```kotlin +// START 'Dependencies' +``` + +

Domain

+ +```kotlin +// START 'Domain' +``` + +

DB Serializers

+ +```kotlin +// START 'DB Serializers' +``` + +

JSON Serializers

+ +```kotlin +// START 'JSON Serializers' +``` + +

Specifications

+ +| Class | COLUMN | Databases | db-messiah-extra | JSON | +|:-------------:|:------------:|:------------------------------------:|:---------------------------:|:-----------:| +| Instant | DATETIME | Sqlite, Mysql, MSSql, Maria, H2, DB2 | KotlinxInstantTS. DATETIME | InstantJS | +| Instant | TIMESTAMP | Derby, Postgres, Oracle | KotlinxInstantTS. TIMESTAMP | InstantJS | +| LocalDateTime | :x: | :x: | :x: | :x: | +| LocalDate | DATE | :white_check_mark: | KotlinxLocalDateTS. DATE | LocalDateJS | +| LocalTime | TIME | :white_check_mark: but Oracle | KotlinxTimeTS.TIME | LocalDateJS | +| LocalTime | NUMBER(8, 0) | Oracle | KotlinxTimeTS. NUMBER8 | LocalTimeJS | +| UUID | db-messiah | db-messiah | db-messiah | UUIDJS | + +

Arhitecture

+ +```text +src/main/kotlin/com/urosjarc/dbmessiah/extra/ +|-- kotlinx +| |-- InstantJS.kt............| java.time.Instant serializer for kotlinx.serialization +| |-- LocalDateJS.kt..........| java.time.LocalDate serializer for kotlinx.serialization +| |-- LocalTimeJS.kt..........| java.time.LocalTime serializer for kotlinx.serialization +| `-- UUIDJS.kt...............| java.utils.UUID serializer for kotlinx.serialization +`-- serializers + |-- KotlinxInstantTS.kt.....| kotlinx.datetime.Instant type serializer for db-messiah + |-- KotlinxLocalDateTS.kt...| kotlinx.datetime.LocalDate type serializer for db-messiah + |-- KotlinxLocalTimeTS.kt...| kotlinx.datetime.LocalTime type serializer for db-messiah + `-- KotlinxTimeTS.kt........| kotlinx.datetime.Time type serializer for db-messiah +``` + +

Sources

+ +```text +src/ +|-- main...............................| Already described in architecture. +`-- test + |-- kotlin + | |-- impl + | | |-- Test_Contract.kt.......| Testing interface for all db tests. + | | |-- Test_Db2.kt + | | |-- Test_Derby.kt + | | |-- Test_H2.kt + | | |-- Test_Maria.kt + | | |-- Test_Mssql.kt + | | |-- Test_Mysql.kt + | | |-- Test_Oracle.kt + | | |-- Test_Postgresql.kt + | | `-- Test_Sqlite.kt + | |-- Test_InstantJS.kt + | |-- Test_LocalDateJS.kt + | |-- Test_LocalTimeJS.kt + | |-- Test_README.kt.............| Code from where README.md is generated. + | |-- Test_README.md.............| Template from where README.md is generated. + | |-- Test_UUIDJS.kt + | `-- utils + | |-- domain.kt + | |-- Schemas.kt + | `-- Serializers.kt + `-- resources + `-- log4j2.xml +```