add kdocs to repos

This commit is contained in:
2026-05-21 20:09:54 +06:00
parent a1bfe4c478
commit 249c14a93d
21 changed files with 909 additions and 7 deletions

View File

@@ -53,6 +53,12 @@ interface ReadKeyValueRepo<Key, Value> : Repo {
*/
suspend fun contains(key: Key): Boolean
/**
* Returns all key-value pairs in the repository as a [Map].
* Default implementation iterates all pages using [keys] and [get].
*
* @return Map of all [Key] to [Value] entries in the repository
*/
suspend fun getAll(): Map<Key, Value> = getAllByWithNextPaging(maxPagePagination()) {
keys(it).let {
it.changeResultsUnchecked(
@@ -111,22 +117,48 @@ interface WriteKeyValueRepo<Key, Value> : Repo {
}
typealias WriteStandardKeyValueRepo<Key,Value> = WriteKeyValueRepo<Key, Value>
/**
* Vararg overload of [WriteKeyValueRepo.set] accepting pairs.
*
* @param toSet Key-value pairs to set
*/
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.set(
vararg toSet: Pair<Key, Value>
) = set(toSet.toMap())
/**
* List overload of [WriteKeyValueRepo.set] accepting a list of pairs.
*
* @param toSet List of key-value pairs to set
*/
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.set(
toSet: List<Pair<Key, Value>>
) = set(toSet.toMap())
/**
* Single-entry overload of [WriteKeyValueRepo.set].
*
* @param k Key to set
* @param v Value to associate with [k]
*/
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.set(
k: Key, v: Value
) = set(k to v)
/**
* Vararg overload of [WriteKeyValueRepo.unset].
*
* @param k Keys to remove
*/
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.unset(
vararg k: Key
) = unset(k.toList())
/**
* Vararg overload of [WriteKeyValueRepo.unsetWithValues].
*
* @param v Values whose associated keys should be removed
*/
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.unsetWithValues(
vararg v: Value
) = unsetWithValues(v.toList())
@@ -160,6 +192,14 @@ interface KeyValueRepo<Key, Value> : ReadKeyValueRepo<Key, Value>, WriteKeyValue
}
typealias StandardKeyValueRepo<Key,Value> = KeyValueRepo<Key, Value>
/**
* Delegate-based implementation of [KeyValueRepo] that composes separate read and write delegates.
*
* @param Key The type of keys in the repository
* @param Value The type of values in the repository
* @param readDelegate Delegate providing all [ReadKeyValueRepo] operations
* @param writeDelegate Delegate providing all [WriteKeyValueRepo] operations
*/
class DelegateBasedKeyValueRepo<Key, Value>(
readDelegate: ReadKeyValueRepo<Key, Value>,
writeDelegate: WriteKeyValueRepo<Key, Value>

View File

@@ -177,38 +177,89 @@ interface WriteKeyValuesRepo<Key, Value> : Repo {
*/
typealias WriteOneToManyKeyValueRepo<Key,Value> = WriteKeyValuesRepo<Key, Value>
/**
* List-of-pairs overload of [WriteKeyValuesRepo.add].
*
* @param keysAndValues List of key to list-of-values pairs to add
*/
suspend inline fun <Key, Value, REPO : WriteKeyValuesRepo<Key, Value>> REPO.add(
keysAndValues: List<Pair<Key, List<Value>>>
) = add(keysAndValues.toMap())
/**
* Vararg overload of [WriteKeyValuesRepo.add].
*
* @param keysAndValues Key to list-of-values pairs to add
*/
suspend inline fun <Key, Value, REPO : WriteKeyValuesRepo<Key, Value>> REPO.add(
vararg keysAndValues: Pair<Key, List<Value>>
) = add(keysAndValues.toMap())
/**
* Single-key overload of [WriteKeyValuesRepo.add] accepting a list of values.
*
* @param k Key to add values to
* @param v List of values to add
*/
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.add(
k: Key, v: List<Value>
) = add(mapOf(k to v))
/**
* Single-key vararg overload of [WriteKeyValuesRepo.add].
*
* @param k Key to add values to
* @param v Values to add
*/
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.add(
k: Key, vararg v: Value
) = add(k, v.toList())
/**
* List-of-pairs overload of [WriteKeyValuesRepo.set].
*
* @param keysAndValues List of key to list-of-values pairs to set
*/
suspend inline fun <Key, Value, REPO : WriteKeyValuesRepo<Key, Value>> REPO.set(
keysAndValues: List<Pair<Key, List<Value>>>
) = set(keysAndValues.toMap())
/**
* Vararg overload of [WriteKeyValuesRepo.set].
*
* @param keysAndValues Key to list-of-values pairs to set
*/
suspend inline fun <Key, Value, REPO : WriteKeyValuesRepo<Key, Value>> REPO.set(
vararg keysAndValues: Pair<Key, List<Value>>
) = set(keysAndValues.toMap())
/**
* Single-key overload of [WriteKeyValuesRepo.set] accepting a list of values.
*
* @param k Key to set values for
* @param v List of values to set
*/
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.set(
k: Key, v: List<Value>
) = set(mapOf(k to v))
/**
* Single-key vararg overload of [WriteKeyValuesRepo.set].
*
* @param k Key to set values for
* @param v Values to set
*/
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.set(
k: Key, vararg v: Value
) = set(k, v.toList())
/**
* Full one-to-many key-values repository combining read and write capabilities.
* Provides default implementations for [clearWithValue], [removeWithValue], and [set].
*
* @param Key The type used as the key in all operations
* @param Value The type of values associated with keys
*/
interface KeyValuesRepo<Key, Value> : ReadKeyValuesRepo<Key, Value>, WriteKeyValuesRepo<Key, Value> {
override suspend fun clearWithValue(v: Value) {
doWithPagination {
@@ -247,6 +298,14 @@ interface KeyValuesRepo<Key, Value> : ReadKeyValuesRepo<Key, Value>, WriteKeyVal
}
typealias OneToManyKeyValueRepo<Key,Value> = KeyValuesRepo<Key, Value>
/**
* Delegate-based implementation of [KeyValuesRepo] that composes separate read and write delegates.
*
* @param Key The type of keys in the repository
* @param Value The type of values associated with keys
* @param readDelegate Delegate providing all [ReadKeyValuesRepo] operations
* @param writeDelegate Delegate providing all [WriteKeyValuesRepo] operations
*/
class DelegateBasedKeyValuesRepo<Key, Value>(
readDelegate: ReadKeyValuesRepo<Key, Value>,
writeDelegate: WriteKeyValuesRepo<Key, Value>
@@ -254,19 +313,41 @@ class DelegateBasedKeyValuesRepo<Key, Value>(
ReadKeyValuesRepo<Key, Value> by readDelegate,
WriteKeyValuesRepo<Key, Value> by writeDelegate
/**
* List-of-pairs overload of [WriteKeyValuesRepo.remove].
*
* @param keysAndValues List of key to list-of-values pairs to remove
*/
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.remove(
keysAndValues: List<Pair<Key, List<Value>>>
) = remove(keysAndValues.toMap())
/**
* Vararg overload of [WriteKeyValuesRepo.remove].
*
* @param keysAndValues Key to list-of-values pairs to remove
*/
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.remove(
vararg keysAndValues: Pair<Key, List<Value>>
) = remove(keysAndValues.toMap())
/**
* Single-key overload of [WriteKeyValuesRepo.remove] accepting a list of values.
*
* @param k Key to remove values from
* @param v List of values to remove
*/
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.remove(
k: Key,
v: List<Value>
) = remove(mapOf(k to v))
/**
* Single-key vararg overload of [WriteKeyValuesRepo.remove].
*
* @param k Key to remove values from
* @param v Values to remove
*/
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.remove(
k: Key,
vararg v: Value

View File

@@ -7,11 +7,51 @@ import dev.inmo.micro_utils.pagination.utils.getAllWithCurrentPaging
import dev.inmo.micro_utils.repos.pagination.maxPagePagination
import kotlinx.coroutines.flow.Flow
/**
* Read-only part of a standard CRUD repository.
*
* @param ObjectType The type of objects stored in the repository
* @param IdType The type of identifiers used to reference stored objects
*/
interface ReadCRUDRepo<ObjectType, IdType> : Repo {
/**
* Returns a paginated list of all objects in the repository.
*
* @param pagination Pagination parameters (page number and size)
* @return [PaginationResult] containing objects for the requested page
*/
suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType>
/**
* Returns a paginated list of all IDs in the repository.
*
* @param pagination Pagination parameters (page number and size)
* @return [PaginationResult] containing IDs for the requested page
*/
suspend fun getIdsByPagination(pagination: Pagination): PaginationResult<IdType>
/**
* Returns the object associated with the given [id], or null if not found.
*
* @param id The identifier of the object to retrieve
* @return The object with the given [id], or null if absent
*/
suspend fun getById(id: IdType): ObjectType?
/**
* Returns true if an object with the given [id] exists in the repository.
*
* @param id The identifier to check
* @return true if the object exists, false otherwise
*/
suspend fun contains(id: IdType): Boolean
/**
* Returns all objects in the repository as a map of ID to object.
* Default implementation iterates all pages using [getIdsByPagination] and [getById].
*
* @return Map of all [IdType] to [ObjectType] entries in the repository
*/
suspend fun getAll(): Map<IdType, ObjectType> = getAllWithCurrentPaging(maxPagePagination()) {
getIdsByPagination(it).let {
it.changeResultsUnchecked(
@@ -20,58 +60,164 @@ interface ReadCRUDRepo<ObjectType, IdType> : Repo {
}
}.toMap()
/**
* Returns the total count of objects stored in the repository.
*
* @return Total number of objects
*/
suspend fun count(): Long
}
typealias ReadStandardCRUDRepo<ObjectType, IdType> = ReadCRUDRepo<ObjectType, IdType>
/**
* Type alias representing a pair of ID and updated value, used in batch update operations.
*
* @param IdType The type of the identifier
* @param ValueType The type of the input value
*/
typealias UpdatedValuePair<IdType, ValueType> = Pair<IdType, ValueType>
/**
* Returns the ID component of an [UpdatedValuePair].
*/
val <IdType> UpdatedValuePair<IdType, *>.id
get() = first
/**
* Returns the value component of an [UpdatedValuePair].
*/
val <ValueType> UpdatedValuePair<*, ValueType>.value
get() = second
/**
* Write part of a standard CRUD repository.
* Provides create, update, and delete operations with reactive flows for change notifications.
*
* @param ObjectType The type of objects stored in the repository
* @param IdType The type of identifiers used to reference stored objects
* @param InputValueType The type of input data used to create or update objects
*/
interface WriteCRUDRepo<ObjectType, IdType, InputValueType> : Repo {
/**
* Flow that emits each newly created object after a successful [create] call.
*/
val newObjectsFlow: Flow<ObjectType>
/**
* Flow that emits each updated object after a successful [update] call.
*/
val updatedObjectsFlow: Flow<ObjectType>
/**
* Flow that emits the ID of each deleted object after a successful [deleteById] call.
*/
val deletedObjectsIdsFlow: Flow<IdType>
/**
* Creates new objects from the given list of input values.
* Successfully created objects must be emitted via [newObjectsFlow].
*
* @param values List of input values to create objects from
* @return List of created [ObjectType] instances
*/
suspend fun create(values: List<InputValueType>): List<ObjectType>
/**
* Updates the object identified by [id] with the given [value].
* Successfully updated object must be emitted via [updatedObjectsFlow].
*
* @param id The identifier of the object to update
* @param value The new input value
* @return The updated [ObjectType], or null if the object was not found
*/
suspend fun update(id: IdType, value: InputValueType): ObjectType?
/**
* Batch-updates objects using the given list of ID-value pairs.
* Successfully updated objects must be emitted via [updatedObjectsFlow].
*
* @param values List of [UpdatedValuePair] entries mapping IDs to new input values
* @return List of successfully updated [ObjectType] instances
*/
suspend fun update(values: List<UpdatedValuePair<IdType, InputValueType>>): List<ObjectType>
/**
* Deletes objects with the given list of IDs.
* Successfully deleted IDs must be emitted via [deletedObjectsIdsFlow].
*
* @param ids List of identifiers of objects to delete
*/
suspend fun deleteById(ids: List<IdType>)
}
typealias WriteStandardCRUDRepo<ObjectType, IdType, InputValueType> = WriteCRUDRepo<ObjectType, IdType, InputValueType>
/**
* Just mirroring [WriteCRUDRepo.newObjectsFlow] to be same as in KV repos
* Mirrors [WriteCRUDRepo.newObjectsFlow] under the name [onNewObjects] for consistency with KV repos naming.
*/
val <ObjectType> WriteCRUDRepo<ObjectType, *, *>.onNewObjects: Flow<ObjectType>
get() = newObjectsFlow
/**
* Just mirroring [WriteCRUDRepo.updatedObjectsFlow] to be same as in KV repos
* Mirrors [WriteCRUDRepo.updatedObjectsFlow] under the name [onUpdatedObjects] for consistency with KV repos naming.
*/
val <ObjectType> WriteCRUDRepo<ObjectType, *, *>.onUpdatedObjects: Flow<ObjectType>
get() = updatedObjectsFlow
/**
* Just mirroring [WriteCRUDRepo.deletedObjectsIdsFlow] to be same as in KV repos
* Mirrors [WriteCRUDRepo.deletedObjectsIdsFlow] under the name [onDeletedObjectsIds] for consistency with KV repos naming.
*/
val <IdType> WriteCRUDRepo<*, IdType, *>.onDeletedObjectsIds: Flow<IdType>
get() = deletedObjectsIdsFlow
/**
* Vararg overload of [WriteCRUDRepo.create] for convenience.
*
* @param values Input values to create objects from
* @return List of created [ObjectType] instances
*/
suspend fun <ObjectType, IdType, InputValueType> WriteCRUDRepo<ObjectType, IdType, InputValueType>.create(
vararg values: InputValueType
): List<ObjectType> = create(values.toList())
/**
* Vararg overload of [WriteCRUDRepo.update] for convenience.
*
* @param values ID-value pairs to update
* @return List of successfully updated [ObjectType] instances
*/
suspend fun <ObjectType, IdType, InputValueType> WriteCRUDRepo<ObjectType, IdType, InputValueType>.update(
vararg values: UpdatedValuePair<IdType, InputValueType>
): List<ObjectType> = update(values.toList())
/**
* Vararg overload of [WriteCRUDRepo.deleteById] for convenience.
*
* @param ids Identifiers of objects to delete
*/
suspend fun <ObjectType, IdType, InputValueType> WriteCRUDRepo<ObjectType, IdType, InputValueType>.deleteById(
vararg ids: IdType
) = deleteById(ids.toList())
/**
* Full CRUD repository combining read and write capabilities.
*
* @param ObjectType The type of objects stored in the repository
* @param IdType The type of identifiers used to reference stored objects
* @param InputValueType The type of input data used to create or update objects
*/
interface CRUDRepo<ObjectType, IdType, InputValueType> : ReadCRUDRepo<ObjectType, IdType>,
WriteCRUDRepo<ObjectType, IdType, InputValueType>
typealias StandardCRUDRepo<ObjectType, IdType, InputValueType> = CRUDRepo<ObjectType, IdType, InputValueType>
/**
* Delegate-based implementation of [CRUDRepo] that composes separate read and write delegates.
*
* @param ObjectType The type of objects stored in the repository
* @param IdType The type of identifiers used to reference stored objects
* @param InputValueType The type of input data used to create or update objects
* @param readDelegate Delegate providing all [ReadCRUDRepo] operations
* @param writeDelegate Delegate providing all [WriteCRUDRepo] operations
*/
class DelegateBasedCRUDRepo<ObjectType, IdType, InputValueType>(
readDelegate: ReadCRUDRepo<ObjectType, IdType>,
writeDelegate: WriteCRUDRepo<ObjectType, IdType, InputValueType>

View File

@@ -7,14 +7,38 @@ import dev.inmo.micro_utils.repos.KeyValueRepo
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
import dev.inmo.micro_utils.repos.unset
/**
* Computes the difference between all entries in this [ReadKeyValueRepo] and the given [other] map.
*
* @param Id The type of keys
* @param Registered The type of values
* @param other The map to compare against
* @return [MapDiff] describing added, removed, and changed entries
*/
suspend fun <Id, Registered> ReadKeyValueRepo<Id, Registered>.diff(other: Map<Id, Registered>): MapDiff<Id, Registered> {
return getAll().diff(other)
}
/**
* Computes the difference between this map and all entries in the given [ReadKeyValueRepo].
*
* @param Id The type of keys
* @param Registered The type of values
* @param other The repository to compare against
* @return [MapDiff] describing added, removed, and changed entries
*/
suspend fun <Id, Registered> Map<Id, Registered>.diff(other: ReadKeyValueRepo<Id, Registered>): MapDiff<Id, Registered> {
return diff(other.getAll())
}
/**
* Applies the given [diff] to this [KeyValueRepo]: removes entries in [MapDiff.removed],
* updates entries in [MapDiff.changed], and adds entries in [MapDiff.added].
*
* @param Id The type of keys
* @param Registered The type of values
* @param diff The diff to apply
*/
suspend fun <Id, Registered> KeyValueRepo<Id, Registered>.applyDiff(diff: MapDiff<Id, Registered>) {
unset(diff.removed.map { it.key })
set(
@@ -24,10 +48,24 @@ suspend fun <Id, Registered> KeyValueRepo<Id, Registered>.applyDiff(diff: MapDif
)
}
/**
* Computes the diff between this [KeyValueRepo] and [other], then applies the diff to this repo.
*
* @param Id The type of keys
* @param Registered The type of values
* @param other The target map state to synchronize to
*/
suspend fun <Id, Registered> KeyValueRepo<Id, Registered>.applyDiff(other: Map<Id, Registered>) {
applyDiff(diff(other))
}
/**
* Computes the diff between this [MutableMap] and the given [ReadKeyValueRepo], then applies the diff to this map.
*
* @param Id The type of keys
* @param Registered The type of values
* @param other The repository whose state to synchronize to
*/
suspend fun <Id, Registered> MutableMap<Id, Registered>.applyDiff(other: ReadKeyValueRepo<Id, Registered>) {
applyDiff(diff(other))
}
}

View File

@@ -5,14 +5,38 @@ import dev.inmo.micro_utils.common.applyDiff
import dev.inmo.micro_utils.common.diff
import dev.inmo.micro_utils.repos.*
/**
* Computes the difference between all entries in this [ReadKeyValuesRepo] and the given [other] map.
*
* @param Id The type of keys
* @param Registered The type of values
* @param other The map to compare against
* @return [MapDiff] describing added, removed, and changed key-to-list entries
*/
suspend fun <Id, Registered> ReadKeyValuesRepo<Id, Registered>.diff(other: Map<Id, List<Registered>>): MapDiff<Id, List<Registered>> {
return getAll().diff(other)
}
/**
* Computes the difference between this map and all entries in the given [ReadKeyValuesRepo].
*
* @param Id The type of keys
* @param Registered The type of values
* @param other The repository to compare against
* @return [MapDiff] describing added, removed, and changed key-to-list entries
*/
suspend fun <Id, Registered> Map<Id, List<Registered>>.diff(other: ReadKeyValuesRepo<Id, Registered>): MapDiff<Id, List<Registered>> {
return diff(other.getAll())
}
/**
* Applies the given [diff] to this [KeyValuesRepo]: clears keys in [MapDiff.removed],
* sets entries in [MapDiff.changed] and [MapDiff.added].
*
* @param Id The type of keys
* @param Registered The type of values
* @param diff The diff to apply
*/
suspend fun <Id, Registered> KeyValuesRepo<Id, Registered>.applyDiff(diff: MapDiff<Id, List<Registered>>) {
diff.removed.forEach {
clear(it.key)
@@ -24,10 +48,24 @@ suspend fun <Id, Registered> KeyValuesRepo<Id, Registered>.applyDiff(diff: MapDi
)
}
/**
* Computes the diff between this [KeyValuesRepo] and [other], then applies the diff to this repo.
*
* @param Id The type of keys
* @param Registered The type of values
* @param other The target map state to synchronize to
*/
suspend fun <Id, Registered> KeyValuesRepo<Id, Registered>.applyDiff(other: Map<Id, List<Registered>>) {
applyDiff(diff(other))
}
/**
* Computes the diff between this [MutableMap] and the given [ReadKeyValuesRepo], then applies the diff to this map.
*
* @param Id The type of keys
* @param Registered The type of values
* @param other The repository whose state to synchronize to
*/
suspend fun <Id, Registered> MutableMap<Id, List<Registered>>.applyDiff(other: ReadKeyValuesRepo<Id, Registered>) {
applyDiff(diff(other))
}
}

View File

@@ -5,6 +5,18 @@ import dev.inmo.micro_utils.repos.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
/**
* Read-only key-value repository adapter that applies type mapping via [MapperRepo].
* Converts outer (From) key/value types to inner (To) types before delegating to [to],
* and converts results back from inner to outer types.
*
* @param FromKey The outer key type exposed by this repo
* @param FromValue The outer value type exposed by this repo
* @param ToKey The inner key type used by the underlying [to] repo
* @param ToValue The inner value type used by the underlying [to] repo
* @param to The underlying [ReadKeyValueRepo] to delegate operations to
* @param mapper The [MapperRepo] providing bidirectional key/value type conversions
*/
open class MapperReadKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
private val to: ReadKeyValueRepo<ToKey, ToValue>,
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
@@ -62,11 +74,34 @@ open class MapperReadKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
override suspend fun count(): Long = to.count()
}
/**
* Wraps this [ReadKeyValueRepo] with a [MapperRepo] to expose a mapped [ReadKeyValueRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param mapper The [MapperRepo] providing bidirectional type conversions
* @return [MapperReadKeyValueRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <FromKey, FromValue, ToKey, ToValue> ReadKeyValueRepo<ToKey, ToValue>.withMapper(
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
): ReadKeyValueRepo<FromKey, FromValue> = MapperReadKeyValueRepo(this, mapper)
/**
* Wraps this [ReadKeyValueRepo] with inline conversion lambdas to expose a mapped [ReadKeyValueRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param keyFromToTo Converts outer key to inner key; defaults to unchecked cast
* @param valueFromToTo Converts outer value to inner value; defaults to unchecked cast
* @param keyToToFrom Converts inner key to outer key; defaults to unchecked cast
* @param valueToToFrom Converts inner value to outer value; defaults to unchecked cast
* @return [MapperReadKeyValueRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValueRepo<ToKey, ToValue>.withMapper(
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
@@ -77,6 +112,18 @@ inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue>
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
)
/**
* Write-only key-value repository adapter that applies type mapping via [MapperRepo].
* Converts outer (From) key/value types to inner (To) types before delegating writes to [to],
* and maps emitted flow values back from inner to outer types.
*
* @param FromKey The outer key type exposed by this repo
* @param FromValue The outer value type exposed by this repo
* @param ToKey The inner key type used by the underlying [to] repo
* @param ToValue The inner value type used by the underlying [to] repo
* @param to The underlying [WriteKeyValueRepo] to delegate operations to
* @param mapper The [MapperRepo] providing bidirectional key/value type conversions
*/
open class MapperWriteKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
private val to: WriteKeyValueRepo<ToKey, ToValue>,
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
@@ -105,11 +152,34 @@ open class MapperWriteKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
)
}
/**
* Wraps this [WriteKeyValueRepo] with a [MapperRepo] to expose a mapped [WriteKeyValueRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param mapper The [MapperRepo] providing bidirectional type conversions
* @return [MapperWriteKeyValueRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <FromKey, FromValue, ToKey, ToValue> WriteKeyValueRepo<ToKey, ToValue>.withMapper(
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
): WriteKeyValueRepo<FromKey, FromValue> = MapperWriteKeyValueRepo(this, mapper)
/**
* Wraps this [WriteKeyValueRepo] with inline conversion lambdas to expose a mapped [WriteKeyValueRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param keyFromToTo Converts outer key to inner key; defaults to unchecked cast
* @param valueFromToTo Converts outer value to inner value; defaults to unchecked cast
* @param keyToToFrom Converts inner key to outer key; defaults to unchecked cast
* @param valueToToFrom Converts inner value to outer value; defaults to unchecked cast
* @return [MapperWriteKeyValueRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValueRepo<ToKey, ToValue>.withMapper(
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
@@ -120,6 +190,17 @@ inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue>
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
)
/**
* Full key-value repository adapter that applies type mapping via [MapperRepo].
* Composes [MapperReadKeyValueRepo] and [MapperWriteKeyValueRepo] for read and write delegation.
*
* @param FromKey The outer key type exposed by this repo
* @param FromValue The outer value type exposed by this repo
* @param ToKey The inner key type used by the underlying [to] repo
* @param ToValue The inner value type used by the underlying [to] repo
* @param to The underlying [KeyValueRepo] to delegate operations to
* @param mapper The [MapperRepo] providing bidirectional key/value type conversions
*/
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
open class MapperKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
private val to: KeyValueRepo<ToKey, ToValue>,
@@ -133,11 +214,34 @@ open class MapperKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
}
}
/**
* Wraps this [KeyValueRepo] with a [MapperRepo] to expose a mapped [KeyValueRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param mapper The [MapperRepo] providing bidirectional type conversions
* @return [MapperKeyValueRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <FromKey, FromValue, ToKey, ToValue> KeyValueRepo<ToKey, ToValue>.withMapper(
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
): KeyValueRepo<FromKey, FromValue> = MapperKeyValueRepo(this, mapper)
/**
* Wraps this [KeyValueRepo] with inline conversion lambdas to expose a mapped [KeyValueRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param keyFromToTo Converts outer key to inner key; defaults to unchecked cast
* @param valueFromToTo Converts outer value to inner value; defaults to unchecked cast
* @param keyToToFrom Converts inner key to outer key; defaults to unchecked cast
* @param valueToToFrom Converts inner value to outer value; defaults to unchecked cast
* @return [MapperKeyValueRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValueRepo<ToKey, ToValue>.withMapper(
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },

View File

@@ -5,6 +5,18 @@ import dev.inmo.micro_utils.repos.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
/**
* Read-only one-to-many key-values repository adapter that applies type mapping via [MapperRepo].
* Converts outer (From) key/value types to inner (To) types before delegating to [to],
* and converts results back from inner to outer types.
*
* @param FromKey The outer key type exposed by this repo
* @param FromValue The outer value type exposed by this repo
* @param ToKey The inner key type used by the underlying [to] repo
* @param ToValue The inner value type used by the underlying [to] repo
* @param to The underlying [ReadKeyValuesRepo] to delegate operations to
* @param mapper The [MapperRepo] providing bidirectional key/value type conversions
*/
open class MapperReadKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
private val to: ReadKeyValuesRepo<ToKey, ToValue>,
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
@@ -56,11 +68,34 @@ open class MapperReadKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
override suspend fun count(k: FromKey): Long = to.count(k.toOutKey())
}
/**
* Wraps this [ReadKeyValuesRepo] with a [MapperRepo] to expose a mapped [ReadKeyValuesRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param mapper The [MapperRepo] providing bidirectional type conversions
* @return [MapperReadKeyValuesRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <FromKey, FromValue, ToKey, ToValue> ReadKeyValuesRepo<ToKey, ToValue>.withMapper(
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
): ReadKeyValuesRepo<FromKey, FromValue> = MapperReadKeyValuesRepo(this, mapper)
/**
* Wraps this [ReadKeyValuesRepo] with inline conversion lambdas to expose a mapped [ReadKeyValuesRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param keyFromToTo Converts outer key to inner key; defaults to unchecked cast
* @param valueFromToTo Converts outer value to inner value; defaults to unchecked cast
* @param keyToToFrom Converts inner key to outer key; defaults to unchecked cast
* @param valueToToFrom Converts inner value to outer value; defaults to unchecked cast
* @return [MapperReadKeyValuesRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValuesRepo<ToKey, ToValue>.withMapper(
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
@@ -71,6 +106,18 @@ inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue>
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
)
/**
* Write-only one-to-many key-values repository adapter that applies type mapping via [MapperRepo].
* Converts outer (From) key/value types to inner (To) types before delegating writes to [to],
* and maps emitted flow values back from inner to outer types.
*
* @param FromKey The outer key type exposed by this repo
* @param FromValue The outer value type exposed by this repo
* @param ToKey The inner key type used by the underlying [to] repo
* @param ToValue The inner value type used by the underlying [to] repo
* @param to The underlying [WriteKeyValuesRepo] to delegate operations to
* @param mapper The [MapperRepo] providing bidirectional key/value type conversions
*/
open class MapperWriteKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
private val to: WriteKeyValuesRepo<ToKey, ToValue>,
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
@@ -109,11 +156,34 @@ open class MapperWriteKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
override suspend fun clearWithValue(v: FromValue) = to.clearWithValue(v.toOutValue())
}
/**
* Wraps this [WriteKeyValuesRepo] with a [MapperRepo] to expose a mapped [WriteKeyValuesRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param mapper The [MapperRepo] providing bidirectional type conversions
* @return [MapperWriteKeyValuesRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <FromKey, FromValue, ToKey, ToValue> WriteKeyValuesRepo<ToKey, ToValue>.withMapper(
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
): WriteKeyValuesRepo<FromKey, FromValue> = MapperWriteKeyValuesRepo(this, mapper)
/**
* Wraps this [WriteKeyValuesRepo] with inline conversion lambdas to expose a mapped [WriteKeyValuesRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param keyFromToTo Converts outer key to inner key; defaults to unchecked cast
* @param valueFromToTo Converts outer value to inner value; defaults to unchecked cast
* @param keyToToFrom Converts inner key to outer key; defaults to unchecked cast
* @param valueToToFrom Converts inner value to outer value; defaults to unchecked cast
* @return [MapperWriteKeyValuesRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValuesRepo<ToKey, ToValue>.withMapper(
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
@@ -124,6 +194,17 @@ inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue>
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
)
/**
* Full one-to-many key-values repository adapter that applies type mapping via [MapperRepo].
* Composes [MapperReadKeyValuesRepo] and [MapperWriteKeyValuesRepo] for read and write delegation.
*
* @param FromKey The outer key type exposed by this repo
* @param FromValue The outer value type exposed by this repo
* @param ToKey The inner key type used by the underlying [to] repo
* @param ToValue The inner value type used by the underlying [to] repo
* @param to The underlying [KeyValuesRepo] to delegate operations to
* @param mapper The [MapperRepo] providing bidirectional key/value type conversions
*/
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
open class MapperKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
private val to: KeyValuesRepo<ToKey, ToValue>,
@@ -133,11 +214,34 @@ open class MapperKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
ReadKeyValuesRepo<FromKey, FromValue> by MapperReadKeyValuesRepo(to, mapper),
WriteKeyValuesRepo<FromKey, FromValue> by MapperWriteKeyValuesRepo(to, mapper)
/**
* Wraps this [KeyValuesRepo] with a [MapperRepo] to expose a mapped [KeyValuesRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param mapper The [MapperRepo] providing bidirectional type conversions
* @return [MapperKeyValuesRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <FromKey, FromValue, ToKey, ToValue> KeyValuesRepo<ToKey, ToValue>.withMapper(
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
): KeyValuesRepo<FromKey, FromValue> = MapperKeyValuesRepo(this, mapper)
/**
* Wraps this [KeyValuesRepo] with inline conversion lambdas to expose a mapped [KeyValuesRepo].
*
* @param FromKey The outer key type
* @param FromValue The outer value type
* @param ToKey The inner key type
* @param ToValue The inner value type
* @param keyFromToTo Converts outer key to inner key; defaults to unchecked cast
* @param valueFromToTo Converts outer value to inner value; defaults to unchecked cast
* @param keyToToFrom Converts inner key to outer key; defaults to unchecked cast
* @param valueToToFrom Converts inner value to outer value; defaults to unchecked cast
* @return [MapperKeyValuesRepo] wrapping this repo
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValuesRepo<ToKey, ToValue>.withMapper(
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },

View File

@@ -5,6 +5,17 @@ import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
/**
* Retrieves all key-value pairs from a [ReadKeyValueRepo] by iterating pages starting from [pagination].
* Uses [methodCaller] to fetch each page of keys, then resolves each key to its value via [ReadKeyValueRepo.get].
*
* @param Key The type of keys in the repository
* @param Value The type of values in the repository
* @param REPO The specific repository type
* @param pagination The starting pagination parameters
* @param methodCaller A function that fetches a page of keys from the repository
* @return List of all key-value pairs across all pages; entries with null values are excluded
*/
suspend inline fun <Key, Value, REPO : ReadKeyValueRepo<Key, Value>> REPO.getAll(
pagination: Pagination,
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
@@ -16,6 +27,16 @@ suspend inline fun <Key, Value, REPO : ReadKeyValueRepo<Key, Value>> REPO.getAll
)
}
/**
* Retrieves all key-value pairs from a [ReadKeyValueRepo] by iterating all pages.
* Uses [maxPagePagination] as the starting pagination and [methodCaller] to fetch each page of keys.
*
* @param Key The type of keys in the repository
* @param Value The type of values in the repository
* @param REPO The specific repository type
* @param methodCaller A function that fetches a page of keys from the repository
* @return List of all key-value pairs across all pages; entries with null values are excluded
*/
suspend inline fun <Key, Value, REPO : ReadKeyValueRepo<Key, Value>> REPO.getAll(
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
crossinline methodCaller: suspend REPO.(Pagination) -> PaginationResult<Key>

View File

@@ -5,6 +5,17 @@ import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
/**
* Retrieves all key-to-list-of-values pairs from a [ReadKeyValuesRepo] by iterating pages starting from [pagination].
* Uses [methodCaller] to fetch each page of keys, then resolves all values per key via [ReadKeyValuesRepo.getAll].
*
* @param Key The type of keys in the repository
* @param Value The type of values associated with keys
* @param REPO The specific repository type
* @param pagination The starting pagination parameters
* @param methodCaller A function that fetches a page of keys from the repository
* @return List of key-to-list-of-values pairs across all pages
*/
suspend inline fun <Key, Value, REPO : ReadKeyValuesRepo<Key, Value>> REPO.getAll(
pagination: Pagination,
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
@@ -18,6 +29,16 @@ suspend inline fun <Key, Value, REPO : ReadKeyValuesRepo<Key, Value>> REPO.getAl
)
}
/**
* Retrieves all key-to-list-of-values pairs from a [ReadKeyValuesRepo] by iterating all pages.
* Uses [maxPagePagination] as the starting pagination and [methodCaller] to fetch each page of keys.
*
* @param Key The type of keys in the repository
* @param Value The type of values associated with keys
* @param REPO The specific repository type
* @param methodCaller A function that fetches a page of keys from the repository
* @return List of key-to-list-of-values pairs across all pages
*/
suspend inline fun <Key, Value, REPO : ReadKeyValuesRepo<Key, Value>> REPO.getAll(
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
crossinline methodCaller: suspend REPO.(Pagination) -> PaginationResult<Key>

View File

@@ -7,4 +7,11 @@ import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
import kotlin.js.JsName
import kotlin.jvm.JvmName
/**
* Wraps this [ReadKeyValueRepo] as a [ReadCRUDFromKeyValueRepo], exposing CRUD read operations.
*
* @param K The type of keys (used as IDs in the CRUD repo)
* @param V The type of values (used as objects in the CRUD repo)
* @return [ReadCRUDFromKeyValueRepo] delegating to this repo
*/
fun <K, V> ReadKeyValueRepo<K, V>.asReadCRUDRepo() = ReadCRUDFromKeyValueRepo(this)

View File

@@ -5,6 +5,14 @@ import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.ReadCRUDRepo
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
/**
* Adapter that exposes a [ReadKeyValueRepo] as a [ReadCRUDRepo].
* Maps CRUD read operations to the underlying key-value repository operations.
*
* @param RegisteredType The type of objects stored in the repository
* @param IdType The type of identifiers (keys) used to reference stored objects
* @param original The underlying [ReadKeyValueRepo] to delegate operations to
*/
open class ReadCRUDFromKeyValueRepo<RegisteredType, IdType>(
protected open val original: ReadKeyValueRepo<IdType, RegisteredType>
) : ReadCRUDRepo<RegisteredType, IdType> {

View File

@@ -8,8 +8,32 @@ import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
import kotlin.js.JsName
import kotlin.jvm.JvmName
/**
* Wraps this [ReadKeyValuesRepo] as a [ReadKeyValueFromKeyValuesRepo],
* exposing each key mapped to a [List] of all associated values.
*
* @param K The type of keys
* @param V The type of individual values
* @return [ReadKeyValueFromKeyValuesRepo] delegating to this repo
*/
fun <K, V> ReadKeyValuesRepo<K, V>.asReadKeyValueRepo() = ReadKeyValueFromKeyValuesRepo(this)
/**
* Wraps this [KeyValuesRepo] as a [KeyValueFromKeyValuesRepo],
* exposing a full read-write key-value interface where each key maps to a [List] of values.
*
* @param K The type of keys
* @param V The type of individual values
* @return [KeyValueFromKeyValuesRepo] delegating to this repo
*/
fun <K, V> KeyValuesRepo<K, V>.asKeyValueRepo() = KeyValueFromKeyValuesRepo(this)
/**
* Wraps this [ReadCRUDRepo] as a [ReadKeyValueFromCRUDRepo],
* exposing CRUD IDs as keys and CRUD objects as values in a [ReadKeyValueRepo].
*
* @param K The type of CRUD IDs (used as keys)
* @param V The type of CRUD objects (used as values)
* @return [ReadKeyValueFromCRUDRepo] delegating to this repo
*/
fun <K, V> ReadCRUDRepo<K, V>.asReadKeyValueRepo() = ReadKeyValueFromCRUDRepo(this)

View File

@@ -18,6 +18,16 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.merge
/**
* Full read-write adapter that exposes a [KeyValuesRepo] as a [KeyValueRepo] mapping each key to a [List] of values.
* Extends [ReadKeyValueFromKeyValuesRepo] with write operations delegated to the underlying [KeyValuesRepo].
* [onNewValue] merges [KeyValuesRepo.onNewValue] and [KeyValuesRepo.onValueRemoved] and emits the updated list per key;
* [onValueRemoved] mirrors [KeyValuesRepo.onDataCleared].
*
* @param Key The type of keys
* @param Value The type of individual values in the one-to-many repo
* @param original The underlying [KeyValuesRepo] to delegate operations to
*/
open class KeyValueFromKeyValuesRepo<Key, Value>(
private val original: KeyValuesRepo<Key, Value>
) : KeyValueRepo<Key, List<Value>>, ReadKeyValueFromKeyValuesRepo<Key, Value>(original) {

View File

@@ -15,6 +15,15 @@ import dev.inmo.micro_utils.repos.pagination.getAll
import dev.inmo.micro_utils.repos.transforms.kvs.ReadKeyValuesFromKeyValueRepo
import kotlin.jvm.JvmInline
/**
* Inline value class adapter that exposes a [ReadCRUDRepo] as a [ReadKeyValueRepo].
* Maps key-value read operations to the underlying CRUD repository operations,
* treating CRUD IDs as keys and CRUD objects as values.
*
* @param Key The type of keys (maps to [ReadCRUDRepo] ID type)
* @param Value The type of values (maps to [ReadCRUDRepo] object type)
* @param original The underlying [ReadCRUDRepo] to delegate operations to
*/
@JvmInline
value class ReadKeyValueFromCRUDRepo<Key, Value>(
private val original: ReadCRUDRepo<Value, Key>

View File

@@ -12,6 +12,14 @@ import dev.inmo.micro_utils.repos.ReadKeyValueRepo
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
import dev.inmo.micro_utils.repos.transforms.kvs.ReadKeyValuesFromKeyValueRepo
/**
* Adapter that exposes a [ReadKeyValuesRepo] as a [ReadKeyValueRepo] mapping each key to a [List] of values.
* Each key's associated list of values is retrieved via [ReadKeyValuesRepo.getAll].
*
* @param Key The type of keys
* @param Value The type of individual values in the one-to-many repo
* @param original The underlying [ReadKeyValuesRepo] to delegate operations to
*/
open class ReadKeyValueFromKeyValuesRepo<Key, Value>(
private val original: ReadKeyValuesRepo<Key, Value>
) : ReadKeyValueRepo<Key, List<Value>> {

View File

@@ -5,17 +5,51 @@ import dev.inmo.micro_utils.repos.ReadKeyValueRepo
import kotlin.js.JsName
import kotlin.jvm.JvmName
/**
* Wraps this [ReadKeyValueRepo] (mapping keys to iterables) as a [ReadKeyValuesFromKeyValueRepo],
* exposing a one-to-many read interface.
*
* @param K The type of keys
* @param V The type of individual values within each iterable
* @param VI The iterable type storing multiple values per key
* @return [ReadKeyValuesFromKeyValueRepo] delegating to this repo
*/
fun <K, V, VI : Iterable<V>> ReadKeyValueRepo<K, VI>.asReadKeyValuesRepo() = ReadKeyValuesFromKeyValueRepo(this)
/**
* Wraps this [KeyValueRepo] (mapping keys to iterables) as a [KeyValuesFromKeyValueRepo],
* exposing a full one-to-many read-write interface.
*
* @param K The type of keys
* @param V The type of individual values within each iterable
* @param VI The iterable type storing multiple values per key
* @param listToValuesIterable Converter from [List] of values to [VI] used when persisting changes
* @return [KeyValuesFromKeyValueRepo] delegating to this repo
*/
fun <K, V, VI : Iterable<V>> KeyValueRepo<K, VI>.asKeyValuesRepo(
listToValuesIterable: suspend (List<V>) -> VI
): KeyValuesFromKeyValueRepo<K, V, VI> = KeyValuesFromKeyValueRepo(this, listToValuesIterable)
/**
* Wraps this [KeyValueRepo] (mapping keys to [List]s) as a [KeyValuesFromKeyValueRepo].
* Uses identity conversion for the list iterable.
*
* @param K The type of keys
* @param V The type of individual values
* @return [KeyValuesFromKeyValueRepo] delegating to this repo with [List] as the iterable type
*/
@JvmName("asListKeyValuesRepo")
@JsName("asListKeyValuesRepo")
fun <K, V> KeyValueRepo<K, List<V>>.asKeyValuesRepo(): KeyValuesFromKeyValueRepo<K, V, List<V>> = asKeyValuesRepo { it }
/**
* Wraps this [KeyValueRepo] (mapping keys to [Set]s) as a [KeyValuesFromKeyValueRepo].
* Converts lists to sets when persisting changes, ensuring value uniqueness per key.
*
* @param K The type of keys
* @param V The type of individual values
* @return [KeyValuesFromKeyValueRepo] delegating to this repo with [Set] as the iterable type
*/
@JvmName("asSetKeyValuesRepo")
@JsName("asSetKeyValuesRepo")
fun <K, V> KeyValueRepo<K, Set<V>>.asKeyValuesRepo(): KeyValuesFromKeyValueRepo<K, V, Set<V>> = asKeyValuesRepo { it.toSet() }

View File

@@ -12,6 +12,17 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlin.js.JsName
import kotlin.jvm.JvmName
/**
* Full read-write adapter that exposes a [KeyValueRepo] storing iterables as a [KeyValuesRepo].
* Extends [ReadKeyValuesFromKeyValueRepo] with write operations: add, remove, clear.
* Emits [onNewValue] and [onValueRemoved] for individual value changes; [onDataCleared] mirrors [KeyValueRepo.onValueRemoved].
*
* @param Key The type of keys
* @param Value The type of individual values within each iterable
* @param ValuesIterable The iterable type storing multiple values per key
* @param original The underlying [KeyValueRepo] mapping keys to iterables of values
* @param listToValuesIterable Converter from [List] of values to [ValuesIterable] used when persisting changes
*/
open class KeyValuesFromKeyValueRepo<Key, Value, ValuesIterable : Iterable<Value>>(
private val original: KeyValueRepo<Key, ValuesIterable>,
private val listToValuesIterable: suspend (List<Value>) -> ValuesIterable

View File

@@ -11,6 +11,15 @@ import dev.inmo.micro_utils.pagination.utils.paginate
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
/**
* Adapter that exposes a [ReadKeyValueRepo] storing iterables as a [ReadKeyValuesRepo].
* Each key maps to a [ValuesIterable] in the underlying repo, which is exposed as a one-to-many relationship.
*
* @param Key The type of keys
* @param Value The type of individual values within each iterable
* @param ValuesIterable The iterable type storing multiple values per key
* @param original The underlying [ReadKeyValueRepo] mapping keys to iterables of values
*/
open class ReadKeyValuesFromKeyValueRepo<Key, Value, ValuesIterable : Iterable<Value>>(
private val original: ReadKeyValueRepo<Key, ValuesIterable>
) : ReadKeyValuesRepo<Key, Value> {

View File

@@ -3,6 +3,14 @@ package dev.inmo.micro_utils.repos.versions
import dev.inmo.micro_utils.repos.KeyValueRepo
import dev.inmo.micro_utils.repos.set
/**
* [StandardVersionsRepoProxy] implementation backed by a [KeyValueRepo] mapping table names to version numbers.
* Stores and retrieves per-table version integers using [keyValueStore] with table names as keys.
*
* @param T The type of the underlying database or storage object
* @param keyValueStore [KeyValueRepo] used to persist table-name-to-version mappings
* @param database The underlying database or storage object exposed via [StandardVersionsRepoProxy.database]
*/
class KeyValueBasedVersionsRepoProxy<T>(
private val keyValueStore: KeyValueRepo<String, Int>,
override val database: T

View File

@@ -2,13 +2,43 @@ package dev.inmo.micro_utils.repos.versions
import dev.inmo.micro_utils.repos.Repo
/**
* Proxy interface providing low-level access to a versioned database [T].
* Implementations store and retrieve per-table version numbers using a backing storage.
*
* @param T The type of the underlying database or storage object
*/
interface StandardVersionsRepoProxy<T> : Repo {
/**
* The underlying database or storage object used for version tracking.
*/
val database: T
/**
* Returns the current version number for the given [tableName], or null if no version is stored.
*
* @param tableName Name of the table whose version to retrieve
* @return Stored version number, or null if the table has not been versioned yet
*/
suspend fun getTableVersion(tableName: String): Int?
/**
* Persists the given [version] number for the given [tableName].
*
* @param tableName Name of the table whose version to update
* @param version New version number to store
*/
suspend fun updateTableVersion(tableName: String, version: Int)
}
/**
* Standard implementation of [VersionsRepo] that delegates version storage to a [StandardVersionsRepoProxy].
* On [setTableVersion]: calls [StandardVersionsRepoProxy.database].[onCreate] if the table has no version yet,
* then iterates [onUpdate] for each version step until the target [version] is reached.
*
* @param T The type of the underlying database or storage object
* @param proxy The [StandardVersionsRepoProxy] used to read and write version numbers
*/
class StandardVersionsRepo<T>(
private val proxy: StandardVersionsRepoProxy<T>
) : VersionsRepo<T> {
@@ -30,4 +60,4 @@ class StandardVersionsRepo<T>(
proxy.updateTableVersion(tableName, currentVersion)
}
}
}
}