Skip to content

Overhaul kite as a pure Kotlin Multiplatform library for the Mite REST API#1

Draft
Copilot wants to merge 2 commits into
mainfrom
copilot/overhaul-kite-repository
Draft

Overhaul kite as a pure Kotlin Multiplatform library for the Mite REST API#1
Copilot wants to merge 2 commits into
mainfrom
copilot/overhaul-kite-repository

Conversation

Copy link
Copy Markdown

Copilot AI commented Feb 22, 2026

Replaces the dated Android-centric shared/ scaffold with a clean, flat KMP library module targeting JVM, iOS, macOS, JS (IR), and wasmJs. Wraps the full Mite REST API with idiomatic Kotlin suspend functions, a DSL for filtering/building resources, and kotlinx-serialization for JSON.

Build & versioning

  • New gradle/libs.versions.toml: Kotlin 2.3.10, Ktor 3.4.0, kotlinx-serialization 1.7.0, kotlinx-datetime 0.6.0, kotlinx-coroutines 1.9.0, Gradle 9.3
  • Root build.gradle.kts stripped to plugins-only; no Android artifacts anywhere

Library module (kite/)

  • MiteConfigdata class(accountName, apiKey)
  • MiteClient — injectable HttpClient constructor + top-level factory that wires ContentNegotiation, defaultRequest (HTTPS host, X-MiteApiKey, Accept, User-Agent: kite/1.0)
  • API groupstimeEntries, projects, customers, services, users as properties; all operations are suspend functions
  • Models@Serializable data classes with @SerialName snake_case mapping; LocalDate/Instant for temporal fields; internal wrapper types handle Mite's {"time_entry": {...}} envelope
  • DSLTimeEntryFilter (query params) and TimeEntryBody (create/update payload) as builder lambdas

Quick start

val mite = MiteClient(MiteConfig("yourcompany", "api-key"))

val entries = mite.timeEntries.list {
    from = LocalDate(2026, 1, 1)
    to   = LocalDate(2026, 1, 31)
    projectId = 42
}

val entry = mite.timeEntries.create {
    minutes   = 90
    note      = "Feature work"
    projectId = 42
}

Tests

MiteClientTest uses Ktor MockEngine to assert correct deserialization, query-parameter encoding, and POST body shape. TimeEntryFilterTest covers DSL field assignment and GroupBy enum values.

Original prompt

Overview

Completely overhaul and re-scaffold the kite repository as a pure Kotlin Multiplatform library that wraps the Mite REST API. The existing scaffold is very old and should be replaced with a clean, modern KMP setup following 2025/2026 best practices.


Goals

  • Pure Kotlin Multiplatform library (no Android app module — this is a library only)
  • Easy-to-use, idiomatic Kotlin API
  • DSL for filtering/querying and creating/updating resources (where it makes sense)
  • kotlinx-serialization for JSON
  • kotlinx-datetime for date/time types
  • Ktor 3.x as the HTTP layer, injected by the consumer (but with a sensible convenience default)
  • Consumers can bring their own HttpClient implementation
  • Ktor types must not leak into the public API

Tech Stack & Versions

Use a Gradle Version Catalog (gradle/libs.versions.toml) with these versions:

Library Version
Kotlin 2.3.10
Ktor 3.4.0
kotlinx-serialization 1.7.0
kotlinx-datetime 0.6.0
kotlinx-coroutines 1.9.0
Gradle wrapper 9.3

Use Kotlin DSL (build.gradle.kts) throughout. Use the Gradle Version Catalog for all dependency declarations.


Project Structure

Replace the existing shared/ module structure with a clean, flat KMP library module. The final layout should be:

kite/
├── gradle/
│   ├── libs.versions.toml          # Version catalog
│   └── wrapper/
│       └── gradle-wrapper.properties
├── kite/                           # The single KMP library module
│   ├── build.gradle.kts
│   └── src/
│       ├── commonMain/kotlin/dev/kite/
│       │   ├── MiteClient.kt           # Main entry point
│       │   ├── MiteConfig.kt           # Configuration (account name, API key)
│       │   ├── api/
│       │   │   ├── TimeEntriesApi.kt
│       │   │   ├── ProjectsApi.kt
│       │   │   ├── CustomersApi.kt
│       │   │   ├── ServicesApi.kt
│       │   │   └── UsersApi.kt
│       │   ├── model/
│       │   │   ├── TimeEntry.kt
│       │   │   ├── Project.kt
│       │   │   ├── Customer.kt
│       │   │   ├── Service.kt
│       │   │   └── User.kt
│       │   └── dsl/
│       │       ├── TimeEntryFilter.kt  # DSL for filtering time entries
│       │       └── TimeEntryBody.kt    # DSL for creating/updating time entries
│       └── commonTest/kotlin/dev/kite/
│           ├── MiteClientTest.kt
│           └── TimeEntryFilterTest.kt
├── build.gradle.kts                # Root build file (just plugins block, no subproject config)
├── settings.gradle.kts             # Includes the `kite` module
└── gradle.properties

Remove the old shared/ module entirely.


KMP Targets

Support the following targets in kite/build.gradle.kts:

  • jvm()
  • iosX64(), iosArm64(), iosSimulatorArm64()
  • macosX64(), macosArm64()
  • js(IR) { browser(); nodejs() }
  • wasmJs { browser(); nodejs() }

No Android target — this is a pure library, not an Android library.


MiteConfig

data class MiteConfig(
    val accountName: String,
    val apiKey: String,
)

MiteClient

The MiteClient should:

  1. Accept an HttpClient parameter (Ktor) — this is the primary constructor
  2. Also provide a convenience top-level factory function MiteClient(config: MiteConfig): MiteClient that creates a sensible default Ktor HttpClient with:
    • ContentNegotiation with json() (kotlinx-serialization)
    • defaultRequest block setting the base URL https://{accountName}.mite.de/, the X-MiteApiKey header, and Accept: application/json
    • A UserAgent plugin or header set to kite/1.0
  3. Expose API groups as properties:
    class MiteClient(private val httpClient: HttpClient) {
        val timeEntries: TimeEntriesApi
        val projects: ProjectsApi
        val customers: CustomersApi
        val services: ServicesApi
        val users: UsersApi
    }

API Interfaces

Implement each API group. All functions should be suspend functions returning the appropriate model type.

TimeEntriesApi

suspend fun list(filter: TimeEntryFilter = TimeEntryFilter()): List<TimeEntry>
suspend fun get(id: Long): TimeEntry
suspend fun create(body: TimeEntryBody.() -> Unit): TimeEntry
suspend fun update(id: Long, body: TimeEntryBody.() -> Unit): TimeEntry
suspend fun delete(id: Long)

ProjectsApi

suspend fun list(): List<Project>
suspend fun listArchived(): List<Project>
suspend fun get(id: Long): Project
suspend fun create(name: String, customerId: Long? = null, note: String? = null): Project
suspend fun update(id: Long, name: String? = null, customerId: Long? = null, note: String? = null): Project
suspend fun delete(id: Long)

CustomersApi

suspend fun list(): List<Customer>
suspend fun listArchived(): List<Customer>
suspend fun get(id: Long): Customer
suspend fun create(name: String, note: String? = null): Customer
suspend fun update(id: Long,...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. [Learn more about Advanced Security.](https://gh.io/cca-advanced-security)

…rapping Mite REST API

Co-authored-by: Bombo <224092+Bombo@users.noreply.github.com>
Copilot AI changed the title [WIP] Overhaul kite repository as pure Kotlin Multiplatform library Overhaul kite as a pure Kotlin Multiplatform library for the Mite REST API Feb 22, 2026
Copilot AI requested a review from Bombo February 22, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants