Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup publishing, dokka & knit #11

Merged
merged 1 commit into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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