{"id":23895989,"url":"https://github.com/mockative/kontinuity","last_synced_at":"2026-02-03T02:34:13.978Z","repository":{"id":57735871,"uuid":"460417102","full_name":"mockative/Kontinuity","owner":"mockative","description":null,"archived":false,"fork":false,"pushed_at":"2024-11-04T21:21:59.000Z","size":376,"stargazers_count":2,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-05T22:58:56.346Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mockative.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-17T12:01:49.000Z","updated_at":"2024-11-04T21:22:02.000Z","dependencies_parsed_at":"2024-11-04T21:36:33.313Z","dependency_job_id":null,"html_url":"https://github.com/mockative/Kontinuity","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mockative%2FKontinuity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mockative%2FKontinuity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mockative%2FKontinuity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mockative%2FKontinuity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mockative","download_url":"https://codeload.github.com/mockative/Kontinuity/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248252665,"owners_count":21072699,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-04T16:46:25.976Z","updated_at":"2026-02-03T02:34:13.939Z","avatar_url":"https://github.com/mockative.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kontinuity\n\n[ksp]: https://github.com/google/ksp\n\n[![Build](https://github.com/mockative/Kontinuity/actions/workflows/build.yml/badge.svg)](https://github.com/mockative/Kontinuity/actions/workflows/build.yml)\n[![Maven Central](https://img.shields.io/maven-central/v/io.mockative/kontinuity-processor)](https://search.maven.org/artifact/io.mockative/kontinuity-processor)\n\nEffortless use of Kotlin Multiplatform coroutines in Swift, including `suspend` functions and\n`Flow\u003cT\u003e` returning members.\n\n## Installation\n\nKontinuity includes both a core Kotlin library, a [Kotlin Symbol Processor][KSP], and various Swift\nPackage Manager packages, depending on how you want to consume the generated code. Please make sure\nto use the same versions of each individual part.\n\n### Kotlin (Gradle)\n\nIn your Kotlin Multiplatform module, add the following to your __build.gradle.kts__ file:\n\n```kotlin\nplugins {\n    id(\"com.google.devtools.ksp\")\n}\n\nkotlin {\n    sourceSets {\n        val commonMain by getting {\n            dependencies {\n                implementation(\"io.mockative:kontinuity-core:2.0.1\")\n            }\n        }\n    }\n}\n\ndependencies {\n    add(\"kspIos\", \"io.mockative:kontinuity-processor:2.0.1\")\n}\n```\n\n### Swift (Swift Package Manager)\n\nThe Swift libraries are available using Swift Package Manager (SPM), by adding the following to\nyour __Package.swift__ file, or in your Xcode Project's Package Dependencies.\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/mockative/Kontinuity.git\", from: \"\u003cversion\u003e\")\n]\n```\n\n## Usage\n\nFor each Kotlin class or interface annotated with `@Kontinuity`, a wrapper class is generated,\nreferred to as the \"Kontinuity Wrapper\".\n\nGiven a Kotlin interface like the following:\n\n```kotlin\npackage com.app.sample.tasks\n\n@Kontinuity\ninterface TaskService {\n    val tasks: StateFlow\u003cList\u003cTask\u003e\u003e\n\n    suspend fun createTask(task: Task)\n\n    fun close()\n}\n```\n\nA Kontinuity Wrapper will be generated:\n\n```kotlin\npackage com.app.sample.tasks\n\n// The Kontinuity Wrapper class takes the prefix 'K' by default\nopen class KTaskService(private val wrapped: TaskService) {\n    // Coroutine members have their names transformed with the 'K' suffix by default\n    val tasksK: KontinuityStateFlow\u003cTask\u003e\n        get() = wrapped.toKontinuityStateFlow()\n\n    fun refreshK(): KontinuitySuspend\u003cUnit\u003e =\n        kontinuitySuspend { wrapped.refresh() }\n\n    // Simple members don't require a name transformation \n    fun close() =\n        wrapped.close()\n}\n```\n\n### Swift\n\nThe generated Kontinuity Wrapper can be used in Swift through `KontinuityCore` and `KontinuityCombine`.\n\n```swift\nimport KontinuityCore\nimport KontinuityCombine\n\nval kotlinTaskService: TaskService\nval taskService = KTaskService(wrapped: kotlinTaskService)\n\n// Accessing the current value of a StateFlow\nval tasks = getValue(of: taskService.tasksK)\n\n// Subscribing to a Flow\nval subscription = createPublisher(for: taskService.tasksK)\n    .sink { completion in } receiveValue: { tasks in\n        print(\"tasks: \\(tasks)\")\n    } \n\n// Calling a suspend function\nval subscription = createFuture(for: taskService.refreshK())\n    .sink { completion in\n        print(\"refresh: \\(completion)\")\n    } receiveValue: { unit in }\n```\n\n### Name Transformations\n\nKontinuity Wrapper classes have their names transformed from the type they're wrapping, by prefixing\nthe class with `K`. Coroutine members of Kontinuity Wrapper classes also have their names\ntransformed, in order to prevent the Kotlin compiler from suffixing it with `_` when compiling for\niOS/Darwin, which it does to prevent member signature clashes when interfaces are used.\n\nSee [Configuration - Name Transformations](CONFIGURATION.md#name-transformations) for more \ninformation in how to configure Kontinuity.\n\n### Coroutine Scope\n\nBy default, Kontinuity launches all coroutines in a scope using `Dispatchers.Main.immediate`. You \ncan override this behaviour by annotating a top-level property with `@KontinuityScope`. This \nannotation can both be applied to the entire source set (by specifying `default = true`), or to the \n`@Kontinuity` annotated types within a single source file:\n\n```kotlin\n// Specifies the coroutine scope used to launch Kontinuity coroutines of types within this source \n// set(s), unless otherwise overwritten by a file-level @KontinuityScope.\n@SharedImmutable\n@KontinuityScope(default = true)\ninternal val defaultKontinuityScope = CoroutineScope(Dispatchers.Default + SuperviserJob())\n```\n\n```kotlin\n// Specifies the coroutine scope used to launch Kontinuity coroutines of types within this file.\n@SharedImmutable\n@KontinuityScope\ninternal val taskServiceScope = CoroutineScope(Dispatchers.Unconfined + SuperviserJob())\n\ninterface TaskService {\n    // Coroutines launches within this type (and other types in this file) are launched in the \n    // `taskServiceScope`.\n}\n```\n\n## Roadmap\n\n- [ ] Add Swift mock library and generator\n- [X] Add global `@KontinuityScope` annotation to control the default scope through a\n  `@SharedImmutable` global variable.\n- [X] Add type-local `@KontinuityScope` annotation to control the default scope on a per-type basis.\n- [X] ~~Consider rewriting `SharedFlow\u003cT\u003e` wrapper generation to generating 2 properties, one for the \n  flow, one for the value `%MValue`.~~\n    - Implementing this breaks usage of `suspend` functions returning `StateFlow\u003cT\u003e`. \n\n## Credits\n\n[KMP-NativeCoroutines]: https://github.com/rickclephas/KMP-NativeCoroutines\n\nKontinuity is heavily inspired by [rickclephas/KMP-NativeCoroutines][KMP-NativeCoroutines], and is\nessentially a Kotlin Symbol Processor version of that Kotlin Compiler Plugin, born out of a desire \nto have similar features while maintaining compatibility with KSP.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmockative%2Fkontinuity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmockative%2Fkontinuity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmockative%2Fkontinuity/lists"}