{"id":13611613,"url":"https://github.com/skydoves/sealedx","last_synced_at":"2025-10-26T01:15:12.750Z","repository":{"id":56736531,"uuid":"523987434","full_name":"skydoves/sealedx","owner":"skydoves","description":"🎲 Kotlin Symbol Processor that auto-generates extensive sealed classes and interfaces for Android and Kotlin.","archived":false,"fork":false,"pushed_at":"2025-05-15T16:02:52.000Z","size":280,"stargazers_count":343,"open_issues_count":0,"forks_count":12,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-19T20:10:06.162Z","etag":null,"topics":["android","extensive","kotlin-symbol-processing","ksp","sealed-class","selaed-interface","skydoves"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skydoves.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"skydoves","custom":["https://www.paypal.me/skydoves","https://www.buymeacoffee.com/skydoves"]}},"created_at":"2022-08-12T07:00:03.000Z","updated_at":"2025-05-17T01:52:26.000Z","dependencies_parsed_at":"2025-05-19T20:10:15.865Z","dependency_job_id":"5bd47f0d-3975-4341-a8cd-cedccf28b545","html_url":"https://github.com/skydoves/sealedx","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/skydoves/sealedx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2Fsealedx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2Fsealedx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2Fsealedx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2Fsealedx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skydoves","download_url":"https://codeload.github.com/skydoves/sealedx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2Fsealedx/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267644707,"owners_count":24120866,"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","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["android","extensive","kotlin-symbol-processing","ksp","sealed-class","selaed-interface","skydoves"],"created_at":"2024-08-01T19:01:58.931Z","updated_at":"2025-10-26T01:15:07.706Z","avatar_url":"https://github.com/skydoves.png","language":"Kotlin","readme":"\u003ch1 align=\"center\"\u003eSealedX\u003c/h1\u003e\u003c/br\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://devlibrary.withgoogle.com/products/android/repos/skydoves-sealedx\"\u003e\u003cimg alt=\"Google\" src=\"https://skydoves.github.io/badges/google-devlib.svg\"/\u003e\u003c/a\u003e\u003cbr\u003e\n  \u003ca href=\"https://opensource.org/licenses/Apache-2.0\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/badge/License-Apache%202.0-blue.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://android-arsenal.com/api?level=21\"\u003e\u003cimg alt=\"API\" src=\"https://img.shields.io/badge/API-21%2B-brightgreen.svg?style=flat\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/skydoves/sealedx/actions/workflows/android.yml\"\u003e\u003cimg alt=\"Build Status\" \n  src=\"https://github.com/skydoves/sealedx/actions/workflows/android.yml/badge.svg\"/\u003e\u003c/a\u003e\n   \u003ca href=\"https://androidweekly.net/issues/issue-531\"\u003e\u003cimg alt=\"Android Weekly\" src=\"https://skydoves.github.io/badges/android-weekly.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/skydoves\"\u003e\u003cimg alt=\"Profile\" src=\"https://skydoves.github.io/badges/skydoves.svg\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n🎲 Kotlin Symbol Processor to auto-generate extensive sealed classes and interfaces for Android and Kotlin.\u003cbr\u003e\u003cbr\u003e\n\u003c/p\u003e\n\n## Why SealedX?\n\nSealedX generates extensive sealed classes \u0026 interfaces based on common sealed classes for each different model. You can reduce writing repeated sealed classes for every different model by auto-generating based on KSP ([Kotlin Symbol Processor](https://kotlinlang.org/docs/ksp-overview.html)).\u003cbr\u003e\u003cbr\u003e\nYou can massively reduce writing repeated files such as `_UiState` sealed interfaces if your project is based on MVI architecture.\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/24237865/184303312-9df53e1e-9ec2-448c-9d93-3a7265ada7ec.png\" width=\"760\"/\u003e\n\u003c/p\u003e\n\n## Use Cases\n\nIf you want to learn more about how to migrate and use cases, check out the repositories below:\n\n- **[WhatsApp Clone Compose](https://github.com/GetStream/whatsApp-clone-compose/pull/1)**\n- **[Now in Android](https://github.com/advocacies/nowinandroid/pull/1)**\n\n## Gradle Setup\n\nTo use [KSP (Kotlin Symbol Processing)](https://kotlinlang.org/docs/ksp-quickstart.html) and SealedX library in your project, you need to follow steps below.\n\n### 1. Enable KSP in your module\n\nAdd the KSP plugin below into your **module**'s `build.gradle` file:\n\n\u003cdetails open\u003e\n  \u003csummary\u003eKotlin (KTS)\u003c/summary\u003e\n\n```kotlin\nplugins {\n    id(\"com.google.devtools.ksp\") version \"2.1.20-2.0.1\"\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGroovy\u003c/summary\u003e\n\n```kotlin\nplugins {\n    id(\"com.google.devtools.ksp\") version \"2.1.20-2.0.1\"\n}\n```\n\u003c/details\u003e\n\n\u003e **Note**: Make sure your current Kotlin version and [KSP version](https://github.com/google/ksp/releases) is the same.\n\n### 2. Add SealedX dependencies\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.skydoves/sealedx-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.github.skydoves%22%20AND%20a:%22sealedx-core%22)\n\nAdd the dependency below into your **module**'s `build.gradle` file:\n\n```gradle\ndependencies {\n    implementation(\"com.github.skydoves:sealedx-core:1.0.4\")\n    ksp(\"com.github.skydoves:sealedx-processor:1.0.4\")\n}\n```\n\n### 3. Add KSP source path\n\nTo access generated codes from KSP, you need to set up the source path like the below into your **module**'s `build.gradle` file:\n\n\u003cdetails open\u003e\n  \u003csummary\u003eAndroid Kotlin (KTS)\u003c/summary\u003e\n\n```kotlin\nkotlin {\n  sourceSets.configureEach {\n    kotlin.srcDir(\"$buildDir/generated/ksp/$name/kotlin/\")\n  }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eAndroid Groovy\u003c/summary\u003e\n\n```gradle\nandroid {\n    applicationVariants.all { variant -\u003e\n        kotlin.sourceSets {\n            def name = variant.name\n            getByName(name) {\n                kotlin.srcDir(\"build/generated/ksp/$name/kotlin\")\n            }\n        }\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ePure Kotlin (KTS)\u003c/summary\u003e\n\n```gradle\nkotlin {\n    sourceSets.main {\n        kotlin.srcDir(\"build/generated/ksp/main/kotlin\")\n    }\n    sourceSets.test {\n        kotlin.srcDir(\"build/generated/ksp/test/kotlin\")\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ePure Kotlin Groovy\u003c/summary\u003e\n\n```gradle\nkotlin {\n    sourceSets {\n        main.kotlin.srcDirs += 'build/generated/ksp/main/kotlin'\n        test.kotlin.srcDirs += 'build/generated/ksp/test/kotlin'\n    }\n}\n```\n\u003c/details\u003e\n\n## Usage\n\n### ExtensiveSealed\n\n`@ExtensiveSealed` annotation is the main trigger of the Kotlin Symbol Processor to run a sealed-extensive processor on compile time. \n- `@ExtensiveSealed` must be annotated to sealed classes or interfaces, which should be a common model to generate extensive sealed classes and interfaces. \n- `@ExtensiveSealed` receives an array of `@ExtensiveModel` annotations, which include the extensive model types. \n- If you build your project, extensive sealed classes or interfaces will be generated based on those extensive models.\n\nLet's see a common `UiState` sealed interface below that is annotated with `@ExtensiveSealed` annotation:\n\n```kotlin\n@ExtensiveSealed(\n  models = [\n    ExtensiveModel(Poster::class),\n    ExtensiveModel(PosterDetails::class)\n  ]\n)\nsealed interface UiState {\n  data class Success(val data: Extensive) : UiState\n  object Loading : UiState\n  object Error : UiState\n}\n```\n\nThe example codes above will generate `PosterUiState` and `PosterDetailsUiState` sealed interfaces below: \u003cbr\u003e\n\n**PosterUiState (generated)**:\n\n```kotlin\npublic sealed interface PosterUiState {\n  public object Error : PosterUiState\n\n  public object Loading : PosterUiState\n\n  public data class Success(\n    public val `data`: Poster,\n  ) : PosterUiState\n}\n```\n\n**PosterDetailsUiState (generated)**:\n\n```kotlin\npublic sealed interface PosterDetailsUiState {\n  public object Error : PosterDetailsUiState\n\n  public object Loading : PosterDetailsUiState\n\n  public data class Success(\n    public val `data`: PosterDetails,\n  ) : PosterDetailsUiState\n}\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee further sealed class examples\u003c/summary\u003e\n\nIn the case of the sealed classes, it's not different fundamentally from sealed interface examples.\n\n```kotlin\n@ExtensiveSealed(\n  models = [ ExtensiveModel(type = Poster::class) ]\n)\nsealed class UiState {\n  data class Success(val data: Extensive) : UiState()\n  object Loading : UiState()\n  object Error : UiState()\n}\n```\n\nThe example codes above will generate the `PosterUiState` sealed class below: \u003cbr\u003e\n\n**PosterUiState (generated)**:\n\n```kotlin\npublic sealed class PosterUiState {\n  public object Error : PosterUiState()\n\n  public object Loading : PosterUiState()\n\n  public data class Success(\n    public val `data`: Poster,\n  ) : PosterUiState()\n}\n```\n\u003c/details\u003e\n\n### ExtensiveModel\n\n`@ExtensiveModel` annotation class contains information on extensive models like model type and a custom name, which decides the name of generated classes.\nBasically, (the simple name of the `type`) + (the name of common sealed classes) will be used to name of generated classes, but you can modify the prefix with the `name` parameter like the example below:\n\n```kotlin\n@ExtensiveSealed(\n  models = [ ExtensiveModel(type = PosterExtensive::class, name = \"Movie\") ]\n)\nsealed interface UiState {\n  data class Success(val data: Extensive) : UiState\n  object Loading : UiState\n  object Error : UiState\n}\n```\n\nThe example codes above will generate `MovieUiState` file instead of `PosterExtensiveUiState` like the below:\n\n**MovieUiState (generated)**:\n\n```kotlin\npublic sealed interface MovieUiState {\n  public object Error : MovieUiState\n\n  public object Loading : MovieUiState\n\n  public data class Success(\n    public val `data`: PosterExtensive,\n  ) : MovieUiState\n}\n```\n\n#### Collection type in @ExtensiveModel\n\nBasically, you can't set a collection type like a `List` to the `type` parameter of the `@ExtensiveModel` annotation.\nSo if you need to set a collection type as an extensive model, you need to write a wrapper class like the below:\n\n```kotlin\ndata class PosterExtensive(\n  val posters: List\u003cPoster\u003e\n)\n\n@ExtensiveSealed(\n  models = [ ExtensiveModel(type = PosterExtensive::class) ]\n)\nsealed interface UiState {\n    ..\n}\n```\n\n### Extensive\n\n`Extensive` is an interface that is used to represent extensive model types of sealed classes and interfaces. \nWhen you need to use an extensive model type in your primary constructor of data class, you can use the `Extensive` extensive type on your common sealed classes and interfaces. \nIt will be replaced by the extensive model type on compile time.\n\n```kotlin\n@ExtensiveSealed(\n  models = [ ExtensiveModel(type = PosterExtensive::class) ]\n)\nsealed interface UiState {\n  // You need to use the Extensive type if you want to use an extensive model type in the generated code.\n  data class Success(val data: Extensive) : UiState\n  ..\n}\n```\n\nThe example codes above will generate `PosterExtensiveUiState` sealed interface like the below:\n\n**PosterExtensiveUiState (generated)**:\n\n```kotlin\npublic sealed interface PosterExtensiveUiState {\n  public object Error : PosterExtensiveUiState\n\n  public object Loading : PosterExtensiveUiState\n\n  public data class Success(\n    public val `data`: PosterExtensive,\n  ) : PosterExtensiveUiState\n}\n```\n\nAs you can see from the example above, the `Extensive` interface type will be replaced with the extensive model by the SealedX processor on compile time.\n\n## Find this repository useful? :heart:\nSupport it by joining __[stargazers](https://github.com/skydoves/sealedx/stargazers)__ for this repository. :star: \u003cbr\u003e\nAlso, __[follow me](https://github.com/skydoves)__ on GitHub for my next creations! 🤩\n\n# License\n```xml\nDesigned and developed by 2022 skydoves (Jaewoong Eum)\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","funding_links":["https://github.com/sponsors/skydoves","https://www.paypal.me/skydoves","https://www.buymeacoffee.com/skydoves"],"categories":["Kotlin"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskydoves%2Fsealedx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskydoves%2Fsealedx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskydoves%2Fsealedx/lists"}