Rafael Diaz
07/07/2025, 5:25 PM@Replicate.Model(variants = [DtoVariant.DATA, DtoVariant.PATCH, DtoVariant.CREATE])
private interface V1 : UserAccount {
val name: Pair<String, String> // this is included in all the variants
@Replicate.Property(include = [DtoVariant.DATA])
val id: Int
@Replicate.Property(exclude = [DtoVariant.CREATE])
val banReason: String?
}
Now say you have Version 2 of User Account (notice we have nominal typing turned on which is another feature):
@OptIn(ExperimentalUuidApi::class)
@Replicate.Model(
variants = [DtoVariant.DATA, DtoVariant.PATCH],
nominalTyping = NominalTyping.ENABLED
)
private interface V2 : UserAccount {
val firstName: String
val lastName: String
@Replicate.Property(include = [DtoVariant.DATA], nominalTyping = NominalTyping.DISABLED)
val id: Uuid
}
I will continue the rest in a thread so this message doesn't get too long.Rafael Diaz
07/07/2025, 5:26 PM// Generated by KReplica. Do not edit.
@file:OptIn(ExperimentalUuidApi::class)
package io.availe
import io.availe.models.Patchable
import <http://kotlin.Int|kotlin.Int>
import kotlin.OptIn
import kotlin.Pair
import kotlin.String
import kotlin.jvm.JvmInline
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
/**
* A sealed interface hierarchy representing all versions of the UserAccount data model.
*/
public sealed interface UserAccountSchema {
public sealed interface DataVariant : UserAccountSchema
public sealed interface PatchRequestVariant : UserAccountSchema
public sealed interface CreateRequestVariant : UserAccountSchema
/**
* --------------------------
* | Version 1 (V1) |
* --------------------------
*/
public sealed interface V1 : UserAccountSchema {
public data class Data(
public val name: Pair<String, String>,
public val id: Int,
public val banReason: String?,
public val schemaVersion: Int = 1,
) : V1,
DataVariant
public data class PatchRequest(
public val name: Patchable<Pair<String, String>> = Patchable.Unchanged,
public val banReason: Patchable<String?> = Patchable.Unchanged,
public val schemaVersion: Patchable<Int> = Patchable.Unchanged,
) : V1,
PatchRequestVariant
public data class CreateRequest(
public val name: Pair<String, String>,
public val schemaVersion: Int = 1,
) : V1,
CreateRequestVariant
}
/**
* --------------------------
* | Version 2 (V2) |
* --------------------------
*/
public sealed interface V2 : UserAccountSchema {
public data class Data(
public val firstName: UserAccountFirstName,
public val lastName: UserAccountLastName,
public val id: Uuid,
public val schemaVersion: UserAccountSchemaVersion = UserAccountSchemaVersion(2),
) : V2,
DataVariant
public data class PatchRequest(
public val firstName: Patchable<UserAccountFirstName> = Patchable.Unchanged,
public val lastName: Patchable<UserAccountLastName> = Patchable.Unchanged,
public val schemaVersion: Patchable<UserAccountSchemaVersion> = Patchable.Unchanged,
) : V2,
PatchRequestVariant
}
}
/**
* SHARED VALUE CLASSES
*
* Type-safe wrappers for properties that are consistent across versions.
*/
@JvmInline
public value class UserAccountFirstName(
public val `value`: String,
)
@JvmInline
public value class UserAccountLastName(
public val `value`: String,
)
@JvmInline
public value class UserAccountSchemaVersion(
public val `value`: Int,
)
Rafael Diaz
07/07/2025, 5:28 PMfun handleUser(user: UserAccountSchema.V1) {
when(user) {
is UserAccountSchema.V1.Data -> TODO()
is UserAccountSchema.V1.CreateRequest -> TODO()
is UserAccountSchema.V1.PatchRequest -> TODO()
}
}
Or say I want to target every data variant:
fun handleUser(user: UserAccountSchema.DataVariant) {
when(user) {
is UserAccountSchema.V1.Data -> TODO()
is UserAccountSchema.V2.Data -> TODO()
}
}
Or perhaps I only want a single instance:
fun handleUser(user: UserAccountSchema.V1.Data) {
print(user.id)
}
Rafael Diaz
07/07/2025, 5:31 PMReplicate.Apply
supports (more info in the docs).
It does also have support for serialization, There's a few caveats due to the interface approach but that's fully explained in the docs.
Link to repo (again):
https://github.com/AvaileDev/KReplica