mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2026-05-21 15:27:33 +00:00
Compare commits
8 Commits
0.29.2
...
renovate/g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4887da0cd5 | ||
| 45bff98a2c | |||
| 249c14a93d | |||
| a1bfe4c478 | |||
| bfe293c0b9 | |||
| 772dde7d5e | |||
| 3c272fa259 | |||
| b6a433caa6 |
151
AGENTS.md
Normal file
151
AGENTS.md
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
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
|
||||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,5 +1,19 @@
|
|||||||
# Changelog
|
# 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
|
## 0.29.2
|
||||||
|
|
||||||
* `Versions`:
|
* `Versions`:
|
||||||
|
|||||||
@@ -18,5 +18,5 @@ crypto_js_version=4.1.1
|
|||||||
# Project data
|
# Project data
|
||||||
|
|
||||||
group=dev.inmo
|
group=dev.inmo
|
||||||
version=0.29.2
|
version=0.29.3
|
||||||
android_code_version=312
|
android_code_version=313
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
[versions]
|
[versions]
|
||||||
|
|
||||||
kt = "2.3.20"
|
kt = "2.3.21"
|
||||||
kt-serialization = "1.11.0"
|
kt-serialization = "1.11.0"
|
||||||
kt-coroutines = "1.10.2"
|
kt-coroutines = "1.11.0"
|
||||||
|
|
||||||
kotlinx-browser = "0.5.0"
|
kotlinx-browser = "0.5.0"
|
||||||
|
|
||||||
kslog = "1.6.1"
|
kslog = "1.6.1"
|
||||||
|
|
||||||
jb-compose = "1.10.3"
|
jb-compose = "1.11.0"
|
||||||
jb-compose-material3 = "1.10.0-alpha05"
|
jb-compose-material3 = "1.11.0-alpha07"
|
||||||
jb-compose-icons = "1.7.8"
|
jb-compose-icons = "1.7.8"
|
||||||
jb-exposed = "1.2.0"
|
jb-exposed = "1.3.0"
|
||||||
jb-dokka = "2.2.0"
|
jb-dokka = "2.2.0"
|
||||||
|
|
||||||
sqlite = "3.53.0.0"
|
sqlite = "3.53.1.0"
|
||||||
|
|
||||||
korlibs = "5.4.0"
|
korlibs = "5.4.0"
|
||||||
uuid = "0.8.4"
|
uuid = "0.8.4"
|
||||||
|
|
||||||
ktor = "3.4.2"
|
ktor = "3.5.0"
|
||||||
|
|
||||||
gh-release = "2.5.2"
|
gh-release = "2.5.2"
|
||||||
|
|
||||||
@@ -27,11 +27,11 @@ koin = "4.2.1"
|
|||||||
|
|
||||||
okio = "3.17.0"
|
okio = "3.17.0"
|
||||||
|
|
||||||
ksp = "2.3.6"
|
ksp = "2.3.8"
|
||||||
kotlin-poet = "2.3.0"
|
kotlin-poet = "2.3.0"
|
||||||
|
|
||||||
versions = "0.53.0"
|
versions = "0.54.0"
|
||||||
nmcp = "1.4.4"
|
nmcp = "1.5.0"
|
||||||
|
|
||||||
android-gradle = "8.12.+"
|
android-gradle = "8.12.+"
|
||||||
dexcount = "4.0.0"
|
dexcount = "4.0.0"
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
6
gradle/wrapper/gradle-wrapper.properties
vendored
6
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,9 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
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
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
295
gradlew
vendored
295
gradlew
vendored
@@ -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");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with 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
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# 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
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
app_path=$0
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
# Need this for daisy-chained symlinks.
|
||||||
ls=`ls -ld "$PRG"`
|
while
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
[ -h "$app_path" ]
|
||||||
PRG="$link"
|
do
|
||||||
else
|
ls=$( ls -ld "$app_path" )
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
link=${ls#*' -> '}
|
||||||
fi
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >/dev/null
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
# This is normally unused
|
||||||
APP_BASE_NAME=`basename "$0"`
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
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.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD=maximum
|
||||||
|
|
||||||
warn () {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
die () {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
# OS specific support (must be 'true' or 'false').
|
||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
nonstop=false
|
nonstop=false
|
||||||
case "`uname`" in
|
case "$( uname )" in #(
|
||||||
CYGWIN* )
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
cygwin=true
|
Darwin* ) darwin=true ;; #(
|
||||||
;;
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
Darwin* )
|
NONSTOP* ) nonstop=true ;;
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
NONSTOP* )
|
|
||||||
nonstop=true
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
else
|
else
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
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."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD="java"
|
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.
|
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
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
case $MAX_FD in #(
|
||||||
if [ $? -eq 0 ] ; then
|
max*)
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
MAX_FD="$MAX_FD_LIMIT"
|
# shellcheck disable=SC2039,SC3045
|
||||||
fi
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
ulimit -n $MAX_FD
|
warn "Could not query maximum file descriptor limit"
|
||||||
if [ $? -ne 0 ] ; then
|
esac
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
case $MAX_FD in #(
|
||||||
fi
|
'' | soft) :;; #(
|
||||||
else
|
*)
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
fi
|
# shellcheck disable=SC2039,SC3045
|
||||||
fi
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
# 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" ;;
|
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Escape application args
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
save () {
|
# * args from the command line
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
# * the main class name
|
||||||
echo " "
|
# * -classpath
|
||||||
}
|
# * -D...appname settings
|
||||||
APP_ARGS=`save "$@"`
|
# * --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
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
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" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
76
gradlew.bat
vendored
76
gradlew.bat
vendored
@@ -13,19 +13,22 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
setlocal EnableExtensions
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@@ -40,65 +43,40 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
"%COMSPEC%" /c exit 1
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
"%COMSPEC%" /c exit 1
|
||||||
|
|
||||||
: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=%*
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@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
|
:exitWithErrorLevel
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||||
|
|
||||||
: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
|
|
||||||
|
|||||||
@@ -53,6 +53,12 @@ interface ReadKeyValueRepo<Key, Value> : Repo {
|
|||||||
*/
|
*/
|
||||||
suspend fun contains(key: Key): Boolean
|
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()) {
|
suspend fun getAll(): Map<Key, Value> = getAllByWithNextPaging(maxPagePagination()) {
|
||||||
keys(it).let {
|
keys(it).let {
|
||||||
it.changeResultsUnchecked(
|
it.changeResultsUnchecked(
|
||||||
@@ -111,22 +117,48 @@ interface WriteKeyValueRepo<Key, Value> : Repo {
|
|||||||
}
|
}
|
||||||
typealias WriteStandardKeyValueRepo<Key,Value> = WriteKeyValueRepo<Key, Value>
|
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(
|
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.set(
|
||||||
vararg toSet: Pair<Key, Value>
|
vararg toSet: Pair<Key, Value>
|
||||||
) = set(toSet.toMap())
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.set(
|
||||||
toSet: List<Pair<Key, Value>>
|
toSet: List<Pair<Key, Value>>
|
||||||
) = set(toSet.toMap())
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.set(
|
||||||
k: Key, v: Value
|
k: Key, v: Value
|
||||||
) = set(k to v)
|
) = set(k to v)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vararg overload of [WriteKeyValueRepo.unset].
|
||||||
|
*
|
||||||
|
* @param k Keys to remove
|
||||||
|
*/
|
||||||
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.unset(
|
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.unset(
|
||||||
vararg k: Key
|
vararg k: Key
|
||||||
) = unset(k.toList())
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValueRepo<Key, Value>.unsetWithValues(
|
||||||
vararg v: Value
|
vararg v: Value
|
||||||
) = unsetWithValues(v.toList())
|
) = unsetWithValues(v.toList())
|
||||||
@@ -160,6 +192,14 @@ interface KeyValueRepo<Key, Value> : ReadKeyValueRepo<Key, Value>, WriteKeyValue
|
|||||||
}
|
}
|
||||||
typealias StandardKeyValueRepo<Key,Value> = KeyValueRepo<Key, Value>
|
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>(
|
class DelegateBasedKeyValueRepo<Key, Value>(
|
||||||
readDelegate: ReadKeyValueRepo<Key, Value>,
|
readDelegate: ReadKeyValueRepo<Key, Value>,
|
||||||
writeDelegate: WriteKeyValueRepo<Key, Value>
|
writeDelegate: WriteKeyValueRepo<Key, Value>
|
||||||
|
|||||||
@@ -177,38 +177,89 @@ interface WriteKeyValuesRepo<Key, Value> : Repo {
|
|||||||
*/
|
*/
|
||||||
typealias WriteOneToManyKeyValueRepo<Key,Value> = WriteKeyValuesRepo<Key, Value>
|
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(
|
suspend inline fun <Key, Value, REPO : WriteKeyValuesRepo<Key, Value>> REPO.add(
|
||||||
keysAndValues: List<Pair<Key, List<Value>>>
|
keysAndValues: List<Pair<Key, List<Value>>>
|
||||||
) = add(keysAndValues.toMap())
|
) = 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(
|
suspend inline fun <Key, Value, REPO : WriteKeyValuesRepo<Key, Value>> REPO.add(
|
||||||
vararg keysAndValues: Pair<Key, List<Value>>
|
vararg keysAndValues: Pair<Key, List<Value>>
|
||||||
) = add(keysAndValues.toMap())
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.add(
|
||||||
k: Key, v: List<Value>
|
k: Key, v: List<Value>
|
||||||
) = add(mapOf(k to v))
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.add(
|
||||||
k: Key, vararg v: Value
|
k: Key, vararg v: Value
|
||||||
) = add(k, v.toList())
|
) = 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(
|
suspend inline fun <Key, Value, REPO : WriteKeyValuesRepo<Key, Value>> REPO.set(
|
||||||
keysAndValues: List<Pair<Key, List<Value>>>
|
keysAndValues: List<Pair<Key, List<Value>>>
|
||||||
) = set(keysAndValues.toMap())
|
) = 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(
|
suspend inline fun <Key, Value, REPO : WriteKeyValuesRepo<Key, Value>> REPO.set(
|
||||||
vararg keysAndValues: Pair<Key, List<Value>>
|
vararg keysAndValues: Pair<Key, List<Value>>
|
||||||
) = set(keysAndValues.toMap())
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.set(
|
||||||
k: Key, v: List<Value>
|
k: Key, v: List<Value>
|
||||||
) = set(mapOf(k to v))
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.set(
|
||||||
k: Key, vararg v: Value
|
k: Key, vararg v: Value
|
||||||
) = set(k, v.toList())
|
) = 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> {
|
interface KeyValuesRepo<Key, Value> : ReadKeyValuesRepo<Key, Value>, WriteKeyValuesRepo<Key, Value> {
|
||||||
override suspend fun clearWithValue(v: Value) {
|
override suspend fun clearWithValue(v: Value) {
|
||||||
doWithPagination {
|
doWithPagination {
|
||||||
@@ -247,6 +298,14 @@ interface KeyValuesRepo<Key, Value> : ReadKeyValuesRepo<Key, Value>, WriteKeyVal
|
|||||||
}
|
}
|
||||||
typealias OneToManyKeyValueRepo<Key,Value> = KeyValuesRepo<Key, Value>
|
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>(
|
class DelegateBasedKeyValuesRepo<Key, Value>(
|
||||||
readDelegate: ReadKeyValuesRepo<Key, Value>,
|
readDelegate: ReadKeyValuesRepo<Key, Value>,
|
||||||
writeDelegate: WriteKeyValuesRepo<Key, Value>
|
writeDelegate: WriteKeyValuesRepo<Key, Value>
|
||||||
@@ -254,19 +313,41 @@ class DelegateBasedKeyValuesRepo<Key, Value>(
|
|||||||
ReadKeyValuesRepo<Key, Value> by readDelegate,
|
ReadKeyValuesRepo<Key, Value> by readDelegate,
|
||||||
WriteKeyValuesRepo<Key, Value> by writeDelegate
|
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(
|
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.remove(
|
||||||
keysAndValues: List<Pair<Key, List<Value>>>
|
keysAndValues: List<Pair<Key, List<Value>>>
|
||||||
) = remove(keysAndValues.toMap())
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.remove(
|
||||||
vararg keysAndValues: Pair<Key, List<Value>>
|
vararg keysAndValues: Pair<Key, List<Value>>
|
||||||
) = remove(keysAndValues.toMap())
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.remove(
|
||||||
k: Key,
|
k: Key,
|
||||||
v: List<Value>
|
v: List<Value>
|
||||||
) = remove(mapOf(k to v))
|
) = 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(
|
suspend inline fun <Key, Value> WriteKeyValuesRepo<Key, Value>.remove(
|
||||||
k: Key,
|
k: Key,
|
||||||
vararg v: Value
|
vararg v: Value
|
||||||
|
|||||||
@@ -7,11 +7,51 @@ import dev.inmo.micro_utils.pagination.utils.getAllWithCurrentPaging
|
|||||||
import dev.inmo.micro_utils.repos.pagination.maxPagePagination
|
import dev.inmo.micro_utils.repos.pagination.maxPagePagination
|
||||||
import kotlinx.coroutines.flow.Flow
|
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 {
|
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>
|
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>
|
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?
|
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
|
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()) {
|
suspend fun getAll(): Map<IdType, ObjectType> = getAllWithCurrentPaging(maxPagePagination()) {
|
||||||
getIdsByPagination(it).let {
|
getIdsByPagination(it).let {
|
||||||
it.changeResultsUnchecked(
|
it.changeResultsUnchecked(
|
||||||
@@ -20,58 +60,164 @@ interface ReadCRUDRepo<ObjectType, IdType> : Repo {
|
|||||||
}
|
}
|
||||||
}.toMap()
|
}.toMap()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total count of objects stored in the repository.
|
||||||
|
*
|
||||||
|
* @return Total number of objects
|
||||||
|
*/
|
||||||
suspend fun count(): Long
|
suspend fun count(): Long
|
||||||
}
|
}
|
||||||
typealias ReadStandardCRUDRepo<ObjectType, IdType> = ReadCRUDRepo<ObjectType, IdType>
|
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>
|
typealias UpdatedValuePair<IdType, ValueType> = Pair<IdType, ValueType>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ID component of an [UpdatedValuePair].
|
||||||
|
*/
|
||||||
val <IdType> UpdatedValuePair<IdType, *>.id
|
val <IdType> UpdatedValuePair<IdType, *>.id
|
||||||
get() = first
|
get() = first
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value component of an [UpdatedValuePair].
|
||||||
|
*/
|
||||||
val <ValueType> UpdatedValuePair<*, ValueType>.value
|
val <ValueType> UpdatedValuePair<*, ValueType>.value
|
||||||
get() = second
|
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 {
|
interface WriteCRUDRepo<ObjectType, IdType, InputValueType> : Repo {
|
||||||
|
/**
|
||||||
|
* Flow that emits each newly created object after a successful [create] call.
|
||||||
|
*/
|
||||||
val newObjectsFlow: Flow<ObjectType>
|
val newObjectsFlow: Flow<ObjectType>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flow that emits each updated object after a successful [update] call.
|
||||||
|
*/
|
||||||
val updatedObjectsFlow: Flow<ObjectType>
|
val updatedObjectsFlow: Flow<ObjectType>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flow that emits the ID of each deleted object after a successful [deleteById] call.
|
||||||
|
*/
|
||||||
val deletedObjectsIdsFlow: Flow<IdType>
|
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>
|
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?
|
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>
|
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>)
|
suspend fun deleteById(ids: List<IdType>)
|
||||||
}
|
}
|
||||||
typealias WriteStandardCRUDRepo<ObjectType, IdType, InputValueType> = WriteCRUDRepo<ObjectType, IdType, InputValueType>
|
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>
|
val <ObjectType> WriteCRUDRepo<ObjectType, *, *>.onNewObjects: Flow<ObjectType>
|
||||||
get() = newObjectsFlow
|
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>
|
val <ObjectType> WriteCRUDRepo<ObjectType, *, *>.onUpdatedObjects: Flow<ObjectType>
|
||||||
get() = updatedObjectsFlow
|
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>
|
val <IdType> WriteCRUDRepo<*, IdType, *>.onDeletedObjectsIds: Flow<IdType>
|
||||||
get() = deletedObjectsIdsFlow
|
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(
|
suspend fun <ObjectType, IdType, InputValueType> WriteCRUDRepo<ObjectType, IdType, InputValueType>.create(
|
||||||
vararg values: InputValueType
|
vararg values: InputValueType
|
||||||
): List<ObjectType> = create(values.toList())
|
): 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(
|
suspend fun <ObjectType, IdType, InputValueType> WriteCRUDRepo<ObjectType, IdType, InputValueType>.update(
|
||||||
vararg values: UpdatedValuePair<IdType, InputValueType>
|
vararg values: UpdatedValuePair<IdType, InputValueType>
|
||||||
): List<ObjectType> = update(values.toList())
|
): 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(
|
suspend fun <ObjectType, IdType, InputValueType> WriteCRUDRepo<ObjectType, IdType, InputValueType>.deleteById(
|
||||||
vararg ids: IdType
|
vararg ids: IdType
|
||||||
) = deleteById(ids.toList())
|
) = 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>,
|
interface CRUDRepo<ObjectType, IdType, InputValueType> : ReadCRUDRepo<ObjectType, IdType>,
|
||||||
WriteCRUDRepo<ObjectType, IdType, InputValueType>
|
WriteCRUDRepo<ObjectType, IdType, InputValueType>
|
||||||
typealias StandardCRUDRepo<ObjectType, IdType, InputValueType> = CRUDRepo<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>(
|
class DelegateBasedCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||||
readDelegate: ReadCRUDRepo<ObjectType, IdType>,
|
readDelegate: ReadCRUDRepo<ObjectType, IdType>,
|
||||||
writeDelegate: WriteCRUDRepo<ObjectType, IdType, InputValueType>
|
writeDelegate: WriteCRUDRepo<ObjectType, IdType, InputValueType>
|
||||||
|
|||||||
@@ -7,14 +7,38 @@ import dev.inmo.micro_utils.repos.KeyValueRepo
|
|||||||
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
|
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
|
||||||
import dev.inmo.micro_utils.repos.unset
|
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> {
|
suspend fun <Id, Registered> ReadKeyValueRepo<Id, Registered>.diff(other: Map<Id, Registered>): MapDiff<Id, Registered> {
|
||||||
return getAll().diff(other)
|
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> {
|
suspend fun <Id, Registered> Map<Id, Registered>.diff(other: ReadKeyValueRepo<Id, Registered>): MapDiff<Id, Registered> {
|
||||||
return diff(other.getAll())
|
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>) {
|
suspend fun <Id, Registered> KeyValueRepo<Id, Registered>.applyDiff(diff: MapDiff<Id, Registered>) {
|
||||||
unset(diff.removed.map { it.key })
|
unset(diff.removed.map { it.key })
|
||||||
set(
|
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>) {
|
suspend fun <Id, Registered> KeyValueRepo<Id, Registered>.applyDiff(other: Map<Id, Registered>) {
|
||||||
applyDiff(diff(other))
|
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>) {
|
suspend fun <Id, Registered> MutableMap<Id, Registered>.applyDiff(other: ReadKeyValueRepo<Id, Registered>) {
|
||||||
applyDiff(diff(other))
|
applyDiff(diff(other))
|
||||||
}
|
}
|
||||||
@@ -5,14 +5,38 @@ import dev.inmo.micro_utils.common.applyDiff
|
|||||||
import dev.inmo.micro_utils.common.diff
|
import dev.inmo.micro_utils.common.diff
|
||||||
import dev.inmo.micro_utils.repos.*
|
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>> {
|
suspend fun <Id, Registered> ReadKeyValuesRepo<Id, Registered>.diff(other: Map<Id, List<Registered>>): MapDiff<Id, List<Registered>> {
|
||||||
return getAll().diff(other)
|
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>> {
|
suspend fun <Id, Registered> Map<Id, List<Registered>>.diff(other: ReadKeyValuesRepo<Id, Registered>): MapDiff<Id, List<Registered>> {
|
||||||
return diff(other.getAll())
|
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>>) {
|
suspend fun <Id, Registered> KeyValuesRepo<Id, Registered>.applyDiff(diff: MapDiff<Id, List<Registered>>) {
|
||||||
diff.removed.forEach {
|
diff.removed.forEach {
|
||||||
clear(it.key)
|
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>>) {
|
suspend fun <Id, Registered> KeyValuesRepo<Id, Registered>.applyDiff(other: Map<Id, List<Registered>>) {
|
||||||
applyDiff(diff(other))
|
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>) {
|
suspend fun <Id, Registered> MutableMap<Id, List<Registered>>.applyDiff(other: ReadKeyValuesRepo<Id, Registered>) {
|
||||||
applyDiff(diff(other))
|
applyDiff(diff(other))
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,18 @@ import dev.inmo.micro_utils.repos.*
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
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>(
|
open class MapperReadKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: ReadKeyValueRepo<ToKey, ToValue>,
|
private val to: ReadKeyValueRepo<ToKey, ToValue>,
|
||||||
mapper: MapperRepo<FromKey, FromValue, 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()
|
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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <FromKey, FromValue, ToKey, ToValue> ReadKeyValueRepo<ToKey, ToValue>.withMapper(
|
inline fun <FromKey, FromValue, ToKey, ToValue> ReadKeyValueRepo<ToKey, ToValue>.withMapper(
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
): ReadKeyValueRepo<FromKey, FromValue> = MapperReadKeyValueRepo(this, mapper)
|
): 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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValueRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValueRepo<ToKey, ToValue>.withMapper(
|
||||||
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
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)
|
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>(
|
open class MapperWriteKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: WriteKeyValueRepo<ToKey, ToValue>,
|
private val to: WriteKeyValueRepo<ToKey, ToValue>,
|
||||||
mapper: MapperRepo<FromKey, FromValue, 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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <FromKey, FromValue, ToKey, ToValue> WriteKeyValueRepo<ToKey, ToValue>.withMapper(
|
inline fun <FromKey, FromValue, ToKey, ToValue> WriteKeyValueRepo<ToKey, ToValue>.withMapper(
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
): WriteKeyValueRepo<FromKey, FromValue> = MapperWriteKeyValueRepo(this, mapper)
|
): 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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValueRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValueRepo<ToKey, ToValue>.withMapper(
|
||||||
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
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)
|
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")
|
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
||||||
open class MapperKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
open class MapperKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: KeyValueRepo<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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <FromKey, FromValue, ToKey, ToValue> KeyValueRepo<ToKey, ToValue>.withMapper(
|
inline fun <FromKey, FromValue, ToKey, ToValue> KeyValueRepo<ToKey, ToValue>.withMapper(
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
): KeyValueRepo<FromKey, FromValue> = MapperKeyValueRepo(this, mapper)
|
): 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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValueRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValueRepo<ToKey, ToValue>.withMapper(
|
||||||
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
|
|||||||
@@ -5,6 +5,18 @@ import dev.inmo.micro_utils.repos.*
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
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>(
|
open class MapperReadKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: ReadKeyValuesRepo<ToKey, ToValue>,
|
private val to: ReadKeyValuesRepo<ToKey, ToValue>,
|
||||||
mapper: MapperRepo<FromKey, FromValue, 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())
|
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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <FromKey, FromValue, ToKey, ToValue> ReadKeyValuesRepo<ToKey, ToValue>.withMapper(
|
inline fun <FromKey, FromValue, ToKey, ToValue> ReadKeyValuesRepo<ToKey, ToValue>.withMapper(
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
): ReadKeyValuesRepo<FromKey, FromValue> = MapperReadKeyValuesRepo(this, mapper)
|
): 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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValuesRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValuesRepo<ToKey, ToValue>.withMapper(
|
||||||
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
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)
|
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>(
|
open class MapperWriteKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: WriteKeyValuesRepo<ToKey, ToValue>,
|
private val to: WriteKeyValuesRepo<ToKey, ToValue>,
|
||||||
mapper: MapperRepo<FromKey, FromValue, 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())
|
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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <FromKey, FromValue, ToKey, ToValue> WriteKeyValuesRepo<ToKey, ToValue>.withMapper(
|
inline fun <FromKey, FromValue, ToKey, ToValue> WriteKeyValuesRepo<ToKey, ToValue>.withMapper(
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
): WriteKeyValuesRepo<FromKey, FromValue> = MapperWriteKeyValuesRepo(this, mapper)
|
): 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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValuesRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValuesRepo<ToKey, ToValue>.withMapper(
|
||||||
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
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)
|
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")
|
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
||||||
open class MapperKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
open class MapperKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: KeyValuesRepo<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),
|
ReadKeyValuesRepo<FromKey, FromValue> by MapperReadKeyValuesRepo(to, mapper),
|
||||||
WriteKeyValuesRepo<FromKey, FromValue> by MapperWriteKeyValuesRepo(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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <FromKey, FromValue, ToKey, ToValue> KeyValuesRepo<ToKey, ToValue>.withMapper(
|
inline fun <FromKey, FromValue, ToKey, ToValue> KeyValuesRepo<ToKey, ToValue>.withMapper(
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
): KeyValuesRepo<FromKey, FromValue> = MapperKeyValuesRepo(this, mapper)
|
): 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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValuesRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValuesRepo<ToKey, ToValue>.withMapper(
|
||||||
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
|
|||||||
@@ -5,6 +5,17 @@ import dev.inmo.micro_utils.pagination.*
|
|||||||
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
|
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
|
||||||
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
|
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(
|
suspend inline fun <Key, Value, REPO : ReadKeyValueRepo<Key, Value>> REPO.getAll(
|
||||||
pagination: Pagination,
|
pagination: Pagination,
|
||||||
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
|
@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(
|
suspend inline fun <Key, Value, REPO : ReadKeyValueRepo<Key, Value>> REPO.getAll(
|
||||||
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
|
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
|
||||||
crossinline methodCaller: suspend REPO.(Pagination) -> PaginationResult<Key>
|
crossinline methodCaller: suspend REPO.(Pagination) -> PaginationResult<Key>
|
||||||
|
|||||||
@@ -5,6 +5,17 @@ import dev.inmo.micro_utils.pagination.*
|
|||||||
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
|
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
|
||||||
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
|
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(
|
suspend inline fun <Key, Value, REPO : ReadKeyValuesRepo<Key, Value>> REPO.getAll(
|
||||||
pagination: Pagination,
|
pagination: Pagination,
|
||||||
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
|
@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(
|
suspend inline fun <Key, Value, REPO : ReadKeyValuesRepo<Key, Value>> REPO.getAll(
|
||||||
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
|
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")
|
||||||
crossinline methodCaller: suspend REPO.(Pagination) -> PaginationResult<Key>
|
crossinline methodCaller: suspend REPO.(Pagination) -> PaginationResult<Key>
|
||||||
|
|||||||
@@ -7,4 +7,11 @@ import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
|
|||||||
import kotlin.js.JsName
|
import kotlin.js.JsName
|
||||||
import kotlin.jvm.JvmName
|
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)
|
fun <K, V> ReadKeyValueRepo<K, V>.asReadCRUDRepo() = ReadCRUDFromKeyValueRepo(this)
|
||||||
|
|||||||
@@ -5,6 +5,14 @@ import dev.inmo.micro_utils.pagination.PaginationResult
|
|||||||
import dev.inmo.micro_utils.repos.ReadCRUDRepo
|
import dev.inmo.micro_utils.repos.ReadCRUDRepo
|
||||||
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
|
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>(
|
open class ReadCRUDFromKeyValueRepo<RegisteredType, IdType>(
|
||||||
protected open val original: ReadKeyValueRepo<IdType, RegisteredType>
|
protected open val original: ReadKeyValueRepo<IdType, RegisteredType>
|
||||||
) : ReadCRUDRepo<RegisteredType, IdType> {
|
) : ReadCRUDRepo<RegisteredType, IdType> {
|
||||||
|
|||||||
@@ -8,8 +8,32 @@ import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
|
|||||||
import kotlin.js.JsName
|
import kotlin.js.JsName
|
||||||
import kotlin.jvm.JvmName
|
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)
|
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)
|
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)
|
fun <K, V> ReadCRUDRepo<K, V>.asReadKeyValueRepo() = ReadKeyValueFromCRUDRepo(this)
|
||||||
|
|||||||
@@ -18,6 +18,16 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import kotlinx.coroutines.flow.merge
|
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>(
|
open class KeyValueFromKeyValuesRepo<Key, Value>(
|
||||||
private val original: KeyValuesRepo<Key, Value>
|
private val original: KeyValuesRepo<Key, Value>
|
||||||
) : KeyValueRepo<Key, List<Value>>, ReadKeyValueFromKeyValuesRepo<Key, Value>(original) {
|
) : KeyValueRepo<Key, List<Value>>, ReadKeyValueFromKeyValuesRepo<Key, Value>(original) {
|
||||||
|
|||||||
@@ -15,6 +15,15 @@ import dev.inmo.micro_utils.repos.pagination.getAll
|
|||||||
import dev.inmo.micro_utils.repos.transforms.kvs.ReadKeyValuesFromKeyValueRepo
|
import dev.inmo.micro_utils.repos.transforms.kvs.ReadKeyValuesFromKeyValueRepo
|
||||||
import kotlin.jvm.JvmInline
|
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
|
@JvmInline
|
||||||
value class ReadKeyValueFromCRUDRepo<Key, Value>(
|
value class ReadKeyValueFromCRUDRepo<Key, Value>(
|
||||||
private val original: ReadCRUDRepo<Value, Key>
|
private val original: ReadCRUDRepo<Value, Key>
|
||||||
|
|||||||
@@ -12,6 +12,14 @@ import dev.inmo.micro_utils.repos.ReadKeyValueRepo
|
|||||||
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
|
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
|
||||||
import dev.inmo.micro_utils.repos.transforms.kvs.ReadKeyValuesFromKeyValueRepo
|
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>(
|
open class ReadKeyValueFromKeyValuesRepo<Key, Value>(
|
||||||
private val original: ReadKeyValuesRepo<Key, Value>
|
private val original: ReadKeyValuesRepo<Key, Value>
|
||||||
) : ReadKeyValueRepo<Key, List<Value>> {
|
) : ReadKeyValueRepo<Key, List<Value>> {
|
||||||
|
|||||||
@@ -5,17 +5,51 @@ import dev.inmo.micro_utils.repos.ReadKeyValueRepo
|
|||||||
import kotlin.js.JsName
|
import kotlin.js.JsName
|
||||||
import kotlin.jvm.JvmName
|
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)
|
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(
|
fun <K, V, VI : Iterable<V>> KeyValueRepo<K, VI>.asKeyValuesRepo(
|
||||||
listToValuesIterable: suspend (List<V>) -> VI
|
listToValuesIterable: suspend (List<V>) -> VI
|
||||||
): KeyValuesFromKeyValueRepo<K, V, VI> = KeyValuesFromKeyValueRepo(this, listToValuesIterable)
|
): 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")
|
@JvmName("asListKeyValuesRepo")
|
||||||
@JsName("asListKeyValuesRepo")
|
@JsName("asListKeyValuesRepo")
|
||||||
fun <K, V> KeyValueRepo<K, List<V>>.asKeyValuesRepo(): KeyValuesFromKeyValueRepo<K, V, List<V>> = asKeyValuesRepo { it }
|
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")
|
@JvmName("asSetKeyValuesRepo")
|
||||||
@JsName("asSetKeyValuesRepo")
|
@JsName("asSetKeyValuesRepo")
|
||||||
fun <K, V> KeyValueRepo<K, Set<V>>.asKeyValuesRepo(): KeyValuesFromKeyValueRepo<K, V, Set<V>> = asKeyValuesRepo { it.toSet() }
|
fun <K, V> KeyValueRepo<K, Set<V>>.asKeyValuesRepo(): KeyValuesFromKeyValueRepo<K, V, Set<V>> = asKeyValuesRepo { it.toSet() }
|
||||||
|
|||||||
@@ -12,6 +12,17 @@ import kotlinx.coroutines.flow.asSharedFlow
|
|||||||
import kotlin.js.JsName
|
import kotlin.js.JsName
|
||||||
import kotlin.jvm.JvmName
|
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>>(
|
open class KeyValuesFromKeyValueRepo<Key, Value, ValuesIterable : Iterable<Value>>(
|
||||||
private val original: KeyValueRepo<Key, ValuesIterable>,
|
private val original: KeyValueRepo<Key, ValuesIterable>,
|
||||||
private val listToValuesIterable: suspend (List<Value>) -> ValuesIterable
|
private val listToValuesIterable: suspend (List<Value>) -> ValuesIterable
|
||||||
|
|||||||
@@ -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.ReadKeyValueRepo
|
||||||
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
|
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>>(
|
open class ReadKeyValuesFromKeyValueRepo<Key, Value, ValuesIterable : Iterable<Value>>(
|
||||||
private val original: ReadKeyValueRepo<Key, ValuesIterable>
|
private val original: ReadKeyValueRepo<Key, ValuesIterable>
|
||||||
) : ReadKeyValuesRepo<Key, Value> {
|
) : ReadKeyValuesRepo<Key, Value> {
|
||||||
|
|||||||
@@ -3,6 +3,14 @@ package dev.inmo.micro_utils.repos.versions
|
|||||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||||
import dev.inmo.micro_utils.repos.set
|
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>(
|
class KeyValueBasedVersionsRepoProxy<T>(
|
||||||
private val keyValueStore: KeyValueRepo<String, Int>,
|
private val keyValueStore: KeyValueRepo<String, Int>,
|
||||||
override val database: T
|
override val database: T
|
||||||
|
|||||||
@@ -2,13 +2,43 @@ package dev.inmo.micro_utils.repos.versions
|
|||||||
|
|
||||||
import dev.inmo.micro_utils.repos.Repo
|
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 {
|
interface StandardVersionsRepoProxy<T> : Repo {
|
||||||
|
/**
|
||||||
|
* The underlying database or storage object used for version tracking.
|
||||||
|
*/
|
||||||
val database: T
|
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?
|
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)
|
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>(
|
class StandardVersionsRepo<T>(
|
||||||
private val proxy: StandardVersionsRepoProxy<T>
|
private val proxy: StandardVersionsRepoProxy<T>
|
||||||
) : VersionsRepo<T> {
|
) : VersionsRepo<T> {
|
||||||
|
|||||||
Reference in New Issue
Block a user