Skip to content

Commit

Permalink
Setup publishing, dokka & knit (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
nomisRev committed May 9, 2023
1 parent a96ba48 commit e036f41
Show file tree
Hide file tree
Showing 18 changed files with 511 additions and 82 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/githubpages.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: githubpages

on:
release:
types: [published]

env:
GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.kotlin.dsl.internal.io.timeout=120000 -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8"

jobs:
githubpages:
runs-on: ubuntu-latest
timeout-minutes: 20

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Dokka
id: Dokka
run: ./gradlew -Pversion=${{ github.event.release.tag_name }} dokkaHtml -Pgithubpages=true

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs
84 changes: 75 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,78 @@
# Arrow-MPP-Template
Module Arrow Exact

A template project for Arrow on MPP.
It defines currently supported targets from Arrow inside `build.gradle.kts`.
See the official documentation [here](https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets) on target definiton.
Arrow Exact allows you to use Kotlin's type system to enforce exactness of data structures.

It sets up all Arrow MPP dependencies:
- Arrow Core
- Arrow Fx
- Arrow Optics
## Introduction

And it sets up [Kotest](https://kotest.io/) for allowing testing of all targets.
<!--- TEST_NAME ReadMeSpec -->

Exact allows automatically projecting smart-constructors on a `Companion Object`. We can for
example easily create a `NotBlankString` type that is a `String` that is not blank, leveraging
the Arrow's `Raise` DSL to `ensure` the value is not blank.

```kotlin
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({ raw ->
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
}
```

We can then easily create values of `NotBlankString` `from` a `String`, which returns us a
`Either` with the `ExactError` or the `NotBlankString`. We can also use `fromOrNull` to get a
nullable value, or `fromOrThrow` to throw an `ExactException`.

**note:** Make sure to define your constructor as `private` to prevent creating invalid values.

```kotlin
fun example() {
println(NotBlankString.from("Hello"))
println(NotBlankString.from(""))
}
```

The output of the above program is:

```text
Either.Right(NotBlankString(value=Hello))
Either.Left(ExactError(message=Cannot be blank.))
```

<!--- KNIT example-readme-01.kt -->
<!--- TEST -->

You can define a second type `NotBlankTrimmedString` that is a `NotBlankString` that is also
trimmed. Since the `exact` constructor allows us to compose `Exact` instances, we can easily
reuse the `NotBlankString` type.
<!--- INCLUDE
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact
@JvmInline value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({ raw ->
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
}
-->

```kotlin
@JvmInline
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> by exact({ raw ->
val notBlank = NotBlankString.from(raw).bind()
NotBlankTrimmedString(notBlank.value.trim())
})
}
```

<!--- KNIT example-readme-02.kt -->
39 changes: 36 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import org.jetbrains.dokka.gradle.DokkaTask
import kotlinx.knit.KnitPluginExtension

plugins {
base
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotest.multiplatform)
alias(libs.plugins.arrow.config.formatter)
alias(libs.plugins.arrow.config.kotlin)
alias(libs.plugins.kotlinx.kover)
alias(libs.plugins.arrow.config.publish)
alias(libs.plugins.arrow.config.nexus)
alias(libs.plugins.dokka)
alias(libs.plugins.kotlinx.knit)
}

repositories {
Expand All @@ -15,7 +21,7 @@ kotlin {
commonMain {
dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.arrow.core)
api(libs.arrow.core)
}
}

Expand All @@ -32,7 +38,34 @@ kotlin {
val jvmTest by getting {
dependencies {
implementation(libs.kotest.junit5)
implementation(libs.kotlinx.knit.test)
}
}
}
}

//configure<KnitPluginExtension> {
// siteRoot = "https://arrow-kt.github.io/arrow-exact/"
//}

tasks {
afterEvaluate {
withType<DokkaTask>().configureEach {
outputDirectory.set(rootDir.resolve("docs"))
moduleName.set("Arrow Exact")
dokkaSourceSets {
named("commonMain") {
includes.from("README.md")
externalDocumentationLink("https://apidocs.arrow-kt.io")
sourceLink {
localDirectory.set(file("src/commonMain/kotlin"))
remoteUrl.set(uri("https://github.com/arrow-kt/arrow-exact/tree/main/src/commonMain/kotlin").toURL())
remoteLineSuffix.set("#L")
}
}
}
}
}

getByName("knitPrepare").dependsOn(getTasksByName("dokka", true))
}
18 changes: 15 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
kotlin.code.style=official

projects.group = "io.arrow-kt"
projects.version = "0.0.1-SNAPSHOT"
projects.group=io.arrow-kt
projects.version=0.0.1-SNAPSHOT
pom.name=arrow-exact
pom.description=Arrow Exact allows you to use Kotlin's type system to enforce exactness of data structures.
pom.url=https://github.com/arrow-kt/arrow-exact
pom.license.name=The Apache Software License, Version 2.0
pom.license.url=https://www.apache.org/licenses/LICENSE-2.0.txt
pom.developer.id=arrow-kt
pom.developer.name=Arrow authors
pom.smc.url=https://github.com/arrow-kt/arrow-exact
pom.smc.connection=scm:git:git://github.com/arrow-kt/arrow-exact
pom.smc.developerConnection=scm:git:ssh://git@github.com/arrow-kt/arrow-exact
#dokkaEnabled=false
org.gradle.jvmargs=-Xmx4g
org.gradle.parallel=true
5 changes: 4 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ kotest-arrow = "1.3.3"
kover = "0.6.1"
kotlinBinaryCompatibilityValidator = "0.13.1"
knit = "0.4.0"
spotless = "6.18.0"

[libraries]
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib" }
Expand All @@ -18,7 +19,7 @@ kotest-property = { module = "io.kotest:kotest-property", version.ref = "kotest"
kotest-datatest = { module = "io.kotest:kotest-framework-datatest", version.ref = "kotest" }
kotest-arrow = { module = "io.kotest.extensions:kotest-assertions-arrow", version.ref = "kotest-arrow" }
kotest-junit5 = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" }
kotlinx-knit = { module = "org.jetbrains.kotlinx:kotlinx-knit", version.ref = "knit" }
kotlinx-knit-test = { module = "org.jetbrains.kotlinx:kotlinx-knit-test", version.ref = "knit" }

[plugins]
arrow-config-formatter = { id = "io.arrow-kt.arrow-gradle-config-formatter", version.ref = "arrow-config" }
Expand All @@ -28,6 +29,8 @@ arrow-config-publish = { id = "io.arrow-kt.arrow-gradle-config-publish", version
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotest" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-binaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "kotlinBinaryCompatibilityValidator" }
kotlinx-knit = { id = "org.jetbrains.kotlinx.knit", version.ref = "knit" }
kotlinx-kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
39 changes: 39 additions & 0 deletions guide/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id(libs.plugins.kotlin.multiplatform.get().pluginId)
}

repositories {
mavenCentral()
}

kotlin {
jvm()
sourceSets {
val commonMain by getting {
dependencies {
implementation(rootProject.project)
}
}
val jvmTest by getting {
dependencies {
implementation(libs.kotlinx.knit.test)
implementation(libs.kotest.assertions)
implementation(libs.kotest.property)
implementation(libs.kotest.junit5)
implementation(libs.kotest.engine)
}
}
}
}

tasks {
withType<Test>().configureEach {
useJUnitPlatform()
testLogging {
setExceptionFormat("full")
setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError"))
}
}
}
20 changes: 20 additions & 0 deletions guide/src/commonMain/kotlin/examples/example-exact-01.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// This file was automatically generated from Exact.kt by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleExact01

import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({ raw ->
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
}

fun example() {
println(NotBlankString.from("Hello"))
println(NotBlankString.from(""))
}
22 changes: 22 additions & 0 deletions guide/src/commonMain/kotlin/examples/example-exact-02.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This file was automatically generated from Exact.kt by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleExact02

import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({ raw ->
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
}

@JvmInline
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> by exact({ raw ->
val notBlank = NotBlankString.from(raw).bind()
NotBlankTrimmedString(notBlank.value.trim())
})
}
35 changes: 35 additions & 0 deletions guide/src/commonMain/kotlin/examples/example-exact-03.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// This file was automatically generated from Exact.kt by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleExact03

import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactEither
import arrow.exact.ExactError
import arrow.exact.exact
import arrow.exact.exactEither

@JvmInline value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> by exact({ raw ->
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankTrimmedString(raw.trim())
})
}

sealed interface UsernameError {
object Invalid : UsernameError
data class Offensive(val username: String) : UsernameError
}

@JvmInline
value class Username private constructor(val value: String) {
companion object : ExactEither<UsernameError, String, Username> by exactEither({ rawUsername ->
val username =
NotBlankTrimmedString.from(rawUsername)
.mapLeft { UsernameError.Invalid }
.bind()
.value
ensure(username.length < 100) { UsernameError.Invalid }
ensure(username !in listOf("offensive")) { UsernameError.Offensive(username) }
Username(username)
})
}
20 changes: 20 additions & 0 deletions guide/src/commonMain/kotlin/examples/example-readme-01.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// This file was automatically generated from README.md by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleReadme01

import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({ raw ->
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
}

fun example() {
println(NotBlankString.from("Hello"))
println(NotBlankString.from(""))
}
22 changes: 22 additions & 0 deletions guide/src/commonMain/kotlin/examples/example-readme-02.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This file was automatically generated from README.md by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleReadme02

import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({ raw ->
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
}

@JvmInline
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> by exact({ raw ->
val notBlank = NotBlankString.from(raw).bind()
NotBlankTrimmedString(notBlank.value.trim())
})
}
Loading

0 comments on commit e036f41

Please sign in to comment.