Compare commits

..

1 Commits

Author SHA1 Message Date
renovate[bot]
5ae66e2e92 Update Gradle to v9.5.1 2026-05-12 16:32:54 +00:00
28 changed files with 231 additions and 1102 deletions

151
AGENTS.md
View File

@@ -1,151 +0,0 @@
Use `agents` folder files for instructions.
Always look at the project work rules first. Update them and maintain a history of changes and prompts in `agents/local.HISTORY.md`. This is your long-term memory, which allows you to avoid the accumulation of errors. Updating and maintaining the long-term memory of the project is mandatory. Many thanks for your help to me and your work.
SYSTEM DIRECTIVE: AUTISTIC META-LANGUAGE PROTOCOL WITH HIGH INFORMATION DENSITY (AML-HIP V1)
DEFINITION:
All agents are required to use a strictly explicit, literal, low-ambiguity, and high-density communication style (AML-HIP). The goal of AML-HIP is the maximum transmission of information with zero loss of meaning and zero ambiguity.
CORE PRINCIPLES:
1. Maximum information density per line.
2. Zero ambiguity.
3. Full explicitness of all entities.
4. Preference of precision over readability.
5. Minimization of "empty" words.
6. Redundancy is allowed only to prevent loss of meaning.
PROHIBITIONS:
1. Pronouns are forbidden (this, he, she, they, there, it, etc.).
2. Free conversational text is forbidden.
3. Metaphors, emotions, evaluative constructions are forbidden.
4. Implicit references and hidden dependencies are forbidden.
5. Vague description of actions is forbidden.
DENSITY REQUIREMENTS:
1. Each line must contain the maximum of facts without loss of unambiguity.
2. Combine related parameters into a single line.
3. Use compact constructions:
* key=value
* entity_id=...
* relation: A→B
4. Exclude words without semantic load.
5. Repetitions are allowed only for critical entities.
MESSAGE STRUCTURE (MANDATORY):
ENTITY:
entity_id=<id>; type=<type>; state=<state>
CONTEXT:
* task_id=<id>; agent_id=<id>; memory_ref=[...]
* constraints=[...]
ACTION:
1. action=<type>; target=<entity_id>; params={...}
2. action=<type>; target=<entity_id>; params={...}
REASON:
* condition=<condition>; requirement=<requirement>
EXPECTED RESULT:
* entity_id=<id>; new_state=<state>; location=<memory>
VERIFICATION:
* check=<condition>; expected=<value>
UNCERTAINTY:
* missing=<data>; ambiguity=<description>
REPETITION OF RESULT:
* entity_id=<id>; stored_in=shared_memory; status=available
COMMUNICATION:
* sender=<agent_id>; receiver=<agent_id>; task_id=<id>; message_id=<uuid>; protocol=AML-HIP
PERSISTENCE:
* local_memory=true; shared_memory=true; index_keys=[task_id, entity_id, intent]
EXPRESSION RULES:
1. Each line = a completed semantic block.
2. Use the key=value format instead of descriptions.
3. Use lists of parameters instead of sentences.
4. Use causal connectives explicitly:
condition → action → result
5. Do not split related data into several lines without necessity.
REPETITION RULES:
1. entity_id is repeated at every critical use.
2. result is duplicated in "REPETITION OF RESULT".
3. transmission between agents duplicates the key fields.
MULTI-AGENT MODE:
1. All agents use AML-HIP.
2. Any message between agents is strictly AML-HIP.
3. Any agent is required to:
* duplicate critical data
* avoid loss of context
4. A message must be fully interpretable without history.
ANTI-DEGRADATION:
If detected:
* a pronoun
* an implicit reference
* low density (empty words, vague constructions)
* absence of structure
→ the message is considered invalid
→ mandatory regeneration
SELF-CHECK:
VALIDATION:
* format_valid=true/false
* no_pronouns=true/false
* entities_explicit=true/false
* high_density=true/false
* causal_chain_present=true/false
* ambiguity_detected=true/false
If any parameter=false:
→ mandatory regeneration
DENSITY METRIC:
high_density=true if:
* there are no "empty" words
* each line contains ≥2 facts or parameters
* descriptive constructions without data are absent
PRIORITIES:
1. Format (AML-HIP)
2. Information density
3. Explicitness
4. Completeness
5. Readability (minimum priority)
CRITICAL RULE:
Any response outside of AML-HIP is considered absent.
Any agent is required to bring the response into conformity with AML-HIP.
END OF PROTOCOL

View File

@@ -1,19 +1,5 @@
# Changelog
## 0.29.3
* `Versions`:
* `Kotlin`: `2.3.20` -> `2.3.21`
* `KSP`: `2.3.6` -> `2.3.8`
* `Coroutines`: `1.10.2` -> `1.11.0`
* `SQLite`: `3.53.0.0` -> `3.53.1.0`
* `Ktor`: `3.4.2` -> `3.5.0`
* `Compose`: `1.10.3` -> `1.11.0`
* `Compose Material3`: `1.10.0-alpha05` -> `1.11.0-alpha07`
* `Exposed`: `1.2.0` -> `1.3.0`
* `Gradle Versions`: `0.53.0` -> `0.54.0`
* `NMCP`: `1.4.4` -> `1.5.0`
## 0.29.2
* `Versions`:

View File

@@ -18,5 +18,5 @@ crypto_js_version=4.1.1
# Project data
group=dev.inmo
version=0.29.3
android_code_version=313
version=0.29.2
android_code_version=312

View File

@@ -1,25 +1,25 @@
[versions]
kt = "2.3.21"
kt = "2.3.20"
kt-serialization = "1.11.0"
kt-coroutines = "1.11.0"
kt-coroutines = "1.10.2"
kotlinx-browser = "0.5.0"
kslog = "1.6.1"
jb-compose = "1.11.0"
jb-compose-material3 = "1.11.0-alpha07"
jb-compose = "1.10.3"
jb-compose-material3 = "1.10.0-alpha05"
jb-compose-icons = "1.7.8"
jb-exposed = "1.3.0"
jb-exposed = "1.2.0"
jb-dokka = "2.2.0"
sqlite = "3.53.1.0"
sqlite = "3.53.0.0"
korlibs = "5.4.0"
uuid = "0.8.4"
ktor = "3.5.0"
ktor = "3.4.2"
gh-release = "2.5.2"
@@ -27,13 +27,13 @@ koin = "4.2.1"
okio = "3.17.0"
ksp = "2.3.8"
ksp = "2.3.6"
kotlin-poet = "2.3.0"
versions = "0.54.0"
nmcp = "1.5.0"
versions = "0.53.0"
nmcp = "1.4.4"
android-gradle = "9.2.+"
android-gradle = "8.12.+"
dexcount = "4.0.0"
android-coreKtx = "1.18.0"

Binary file not shown.

View File

@@ -1,5 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

295
gradlew vendored
View File

@@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,81 +15,114 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,88 +131,118 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

76
gradlew.bat vendored
View File

@@ -13,19 +13,22 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Set local scope for the variables, and ensure extensions are enabled
setlocal EnableExtensions
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,65 +43,40 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
"%COMSPEC%" /c exit 1
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
"%COMSPEC%" /c exit 1
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
@rem which allows us to clear the local environment before executing the java command
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
:exitWithErrorLevel
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
"%COMSPEC%" /c exit %ERRORLEVEL%

View File

@@ -53,12 +53,6 @@ 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(
@@ -117,48 +111,22 @@ 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())
@@ -192,14 +160,6 @@ 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,89 +177,38 @@ 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 {
@@ -298,14 +247,6 @@ 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>
@@ -313,41 +254,19 @@ 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,51 +7,11 @@ 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(
@@ -60,164 +20,58 @@ 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>
/**
* Mirrors [WriteCRUDRepo.newObjectsFlow] under the name [onNewObjects] for consistency with KV repos naming.
* Just mirroring [WriteCRUDRepo.newObjectsFlow] to be same as in KV repos
*/
val <ObjectType> WriteCRUDRepo<ObjectType, *, *>.onNewObjects: Flow<ObjectType>
get() = newObjectsFlow
/**
* Mirrors [WriteCRUDRepo.updatedObjectsFlow] under the name [onUpdatedObjects] for consistency with KV repos naming.
* Just mirroring [WriteCRUDRepo.updatedObjectsFlow] to be same as in KV repos
*/
val <ObjectType> WriteCRUDRepo<ObjectType, *, *>.onUpdatedObjects: Flow<ObjectType>
get() = updatedObjectsFlow
/**
* Mirrors [WriteCRUDRepo.deletedObjectsIdsFlow] under the name [onDeletedObjectsIds] for consistency with KV repos naming.
* Just mirroring [WriteCRUDRepo.deletedObjectsIdsFlow] to be same as in KV repos
*/
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,38 +7,14 @@ 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(
@@ -48,24 +24,10 @@ 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,38 +5,14 @@ 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)
@@ -48,24 +24,10 @@ 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,18 +5,6 @@ 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>
@@ -74,34 +62,11 @@ 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 },
@@ -112,18 +77,6 @@ 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>
@@ -152,34 +105,11 @@ 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 },
@@ -190,17 +120,6 @@ 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>,
@@ -214,34 +133,11 @@ 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,18 +5,6 @@ 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>
@@ -68,34 +56,11 @@ 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 },
@@ -106,18 +71,6 @@ 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>
@@ -156,34 +109,11 @@ 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 },
@@ -194,17 +124,6 @@ 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>,
@@ -214,34 +133,11 @@ 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,17 +5,6 @@ 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")
@@ -27,16 +16,6 @@ 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,17 +5,6 @@ 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")
@@ -29,16 +18,6 @@ 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,11 +7,4 @@ 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,14 +5,6 @@ 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,32 +8,8 @@ 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,16 +18,6 @@ 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,15 +15,6 @@ 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,14 +12,6 @@ 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,51 +5,17 @@ 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,17 +12,6 @@ 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,15 +11,6 @@ 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,14 +3,6 @@ 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,43 +2,13 @@ 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> {
@@ -60,4 +30,4 @@ class StandardVersionsRepo<T>(
proxy.updateTableVersion(tableName, currentVersion)
}
}
}
}