mirror of
				https://github.com/InsanusMokrassar/MicroUtils.git
				synced 2025-10-31 12:10:29 +00:00 
			
		
		
		
	Compare commits
	
		
			63 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c6eab182f6 | |||
| 3e3fbd97eb | |||
| feb695caa7 | |||
| 1bd46d9651 | |||
| 32eabb6b36 | |||
| 9bfe6dc6d8 | |||
| 3f366aeea4 | |||
| 4338fd46f2 | |||
| 36974f5b49 | |||
| d48f767408 | |||
| bd2558e852 | |||
| 9f7c963cd5 | |||
| 2db0eadbfe | |||
| 580c7b8842 | |||
| 88fba347ea | |||
| c8c5255e62 | |||
| 01a1a2760a | |||
| 6d34df8d48 | |||
| b124ea65e1 | |||
| f3214347a9 | |||
| 6b8724b59f | |||
| ac3e378edf | |||
| 5d31fd1c91 | |||
| 046fe1ec08 | |||
| 721873c843 | |||
| f6ffbfc10a | |||
| 4e91649e0a | |||
| 4f7f8abec4 | |||
| 6370562dbc | |||
| 94e2e67522 | |||
| 1d8330015d | |||
| e5017b0258 | |||
| cd412ca31b | |||
| d2b6473095 | |||
| ab42507275 | |||
| dcef844e20 | |||
| 3244708c1b | |||
| 73ac1f1741 | |||
| f104e9f352 | |||
| 393c9a7d06 | |||
| ea497ea488 | |||
|  | 5add89cad0 | ||
| 2db447d2ef | |||
| 31c83813e6 | |||
| 27483a282d | |||
| 48b816aa22 | |||
| 0065f94f52 | |||
| ccc0002eb2 | |||
| 15a2eee141 | |||
| b9faac71e5 | |||
| 0a4465de33 | |||
| f9dfd09628 | |||
| 8638d7afce | |||
| 8311793a43 | |||
| 0d552cfcd2 | |||
| 4b0f20dbd1 | |||
| cf531c949d | |||
| ba5c5f17d5 | |||
| 35825ad9b7 | |||
| b1eb26a89e | |||
| c9d04b6698 | |||
| 496133e014 | |||
| f2857ee2be | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -14,3 +14,6 @@ local.properties | |||||||
| kotlin-js-store | kotlin-js-store | ||||||
|  |  | ||||||
| publishing.sh | publishing.sh | ||||||
|  |  | ||||||
|  | local.* | ||||||
|  | local/ | ||||||
|   | |||||||
							
								
								
									
										109
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,5 +1,114 @@ | |||||||
| # Changelog | # Changelog | ||||||
|  |  | ||||||
|  | ## 0.20.49 | ||||||
|  |  | ||||||
|  | * `Repos`: | ||||||
|  |     * `Common`: | ||||||
|  |         * All `Repo`s get `diff` extensions | ||||||
|  |         * `KeyValueRepo` and `KeyValuesRepo` get `applyDiff` extension | ||||||
|  |         * Add new extensions `on*` flows for crud repos | ||||||
|  |  | ||||||
|  | ## 0.20.48 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Android Core KTX`: `1.13.0` -> `1.13.1` | ||||||
|  |     * `AndroidX Fragment`: `1.6.2` -> `1.7.0` | ||||||
|  |  | ||||||
|  | ## 0.20.47 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Exposed`: `0.49.0` -> `0.50.0` | ||||||
|  |  | ||||||
|  | ## 0.20.46 | ||||||
|  |  | ||||||
|  | * `Common`: | ||||||
|  |     * Now this repo depends on `klock` | ||||||
|  |     * Add new object-serializer `DateTimeSerializer` for `klock` serializer | ||||||
|  |  | ||||||
|  | ## 0.20.45 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Android Core KTX`: `1.12.0` -> `1.13.0` | ||||||
|  |  | ||||||
|  | ## 0.20.44 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Compose`: `1.6.1` -> `1.6.2` | ||||||
|  |     * `Koin`: `3.5.4` -> `3.5.6` | ||||||
|  |  | ||||||
|  | ## 0.20.43 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Ktor`: `2.3.9` -> `2.3.10` | ||||||
|  |     * `Koin`: `3.5.3` -> `3.5.4` | ||||||
|  |  | ||||||
|  | ## 0.20.42 | ||||||
|  |  | ||||||
|  | * `Repos`: | ||||||
|  |     * `Generator`: | ||||||
|  |         * Improvements | ||||||
|  |  | ||||||
|  | ## 0.20.41 | ||||||
|  |  | ||||||
|  | * `Repos`: | ||||||
|  |     * `Exposed`: | ||||||
|  |         * `AbstractExposedKeyValueRepo`, `ExposedKeyValueRepo`, `AbstractExposedKeyValuesRepo`, `ExposedKeyValuesRepo` got opportunity to setup some part of their flows | ||||||
|  |  | ||||||
|  | ## 0.20.40 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `KSLog`: `1.3.2` -> `1.3.3` | ||||||
|  |     * `Exposed`: `0.48.0` -> `0.49.0` | ||||||
|  |     * `UUID`: `0.8.2` -> `0.8.4` | ||||||
|  |  | ||||||
|  | ## 0.20.39 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Kotlin`: `1.9.22` -> `1.9.23` | ||||||
|  |     * `Korlibs`: `5.3.2` -> `5.4.0` | ||||||
|  |     * `Okio`: `3.8.0` -> `3.9.0` | ||||||
|  |     * `Compose`: `1.6.0` -> `1.6.1` | ||||||
|  |     * `ComposeMaterial3`: `1.2.0` -> `1.2.1` | ||||||
|  |  | ||||||
|  | ## 0.20.38 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Ktor`: `2.3.8` -> `2.3.9` | ||||||
|  |  | ||||||
|  | ## 0.20.37 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Compose`: `1.5.12` -> `1.6.0` | ||||||
|  |     * `Exposed`: `0.47.0` -> `0.48.0` | ||||||
|  |  | ||||||
|  | ## 0.20.36 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Serialization`: `1.6.2` -> `1.6.3` | ||||||
|  |     * `Korlibs`: `5.3.1` -> `5.3.2` | ||||||
|  | * `Repos`: | ||||||
|  |     * `Cache`: | ||||||
|  |         * Improve work and functionality of `actualizeAll` and subsequent functions | ||||||
|  |         * All internal repos `invalidate`/`actualizeAll` now use common `actualizeAll` functions | ||||||
|  |  | ||||||
|  | ## 0.20.35 | ||||||
|  |  | ||||||
|  | * `Versions`: | ||||||
|  |     * `Coroutines`: `1.7.3` -> `1.8.0` | ||||||
|  |     * `Material3`: `1.1.2` -> `1.2.0` | ||||||
|  |  | ||||||
|  | ## 0.20.34 | ||||||
|  |  | ||||||
|  | * `Repos`: | ||||||
|  |     * `Common`: | ||||||
|  |         * Improve default `set` realization of `KeyValuesRepo` | ||||||
|  |  | ||||||
|  | ## 0.20.33 | ||||||
|  |  | ||||||
|  | * `Colors` | ||||||
|  |     * `Common`: | ||||||
|  |         * Add opportunity to use `HEXAColor` with `ahex` colors | ||||||
|  |  | ||||||
| ## 0.20.32 | ## 0.20.32 | ||||||
|  |  | ||||||
| * `Versions`: | * `Versions`: | ||||||
|   | |||||||
| @@ -12,16 +12,30 @@ import kotlin.math.floor | |||||||
|  * * Red (0.5 capacity): `0xff000088u` |  * * Red (0.5 capacity): `0xff000088u` | ||||||
|  * |  * | ||||||
|  * Anyway it is recommended to use |  * Anyway it is recommended to use | ||||||
|  |  * | ||||||
|  |  * @param hexaUInt rgba [UInt] in format `0xFFEEBBAA` where FF - red, EE - green, BB - blue` and AA - alpha | ||||||
|  */ |  */ | ||||||
| @Serializable | @Serializable | ||||||
| @JvmInline | @JvmInline | ||||||
| value class HEXAColor ( | value class HEXAColor ( | ||||||
|     val uint: UInt |     val hexaUInt: UInt | ||||||
| ) : Comparable<HEXAColor> { | ) : Comparable<HEXAColor> { | ||||||
|  |     /** | ||||||
|  |      * @returns [hexaUInt] as a string with format `#FFEEBBAA` where FF - red, EE - green, BB - blue and AA - alpha | ||||||
|  |      */ | ||||||
|     val hexa: String |     val hexa: String | ||||||
|         get() = "#${uint.toString(16).padStart(8, '0')}" |         get() = "#${hexaUInt.toString(16).padStart(8, '0')}" | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @returns [hexaUInt] as a string with format `#FFEEBB` where FF - red, EE - green and BB - blue | ||||||
|  |      */ | ||||||
|     val hex: String |     val hex: String | ||||||
|         get() = hexa.take(7) |         get() = hexa.take(7) | ||||||
|  |     /** | ||||||
|  |      * @returns [hexaUInt] as a string with format `#AAFFEEBB` where AA - alpha, FF - red, EE - green and BB - blue | ||||||
|  |      */ | ||||||
|  |     val ahex: String | ||||||
|  |         get() = "#${a.toString(16).padStart(2, '2')}${hex.drop(1)}" | ||||||
|     val rgba: String |     val rgba: String | ||||||
|         get() = "rgba($r,$g,$b,${aOfOne.toString().take(5)})" |         get() = "rgba($r,$g,$b,${aOfOne.toString().take(5)})" | ||||||
|     val rgb: String |     val rgb: String | ||||||
| @@ -30,21 +44,25 @@ value class HEXAColor ( | |||||||
|         get() = "#${r.shortPart()}${g.shortPart()}${b.shortPart()}" |         get() = "#${r.shortPart()}${g.shortPart()}${b.shortPart()}" | ||||||
|     val shortHexa: String |     val shortHexa: String | ||||||
|         get() = "$shortHex${a.shortPart()}" |         get() = "$shortHex${a.shortPart()}" | ||||||
|  |     val rgbUInt: UInt | ||||||
|  |         get() = (hexaUInt / 256u) | ||||||
|     val rgbInt: Int |     val rgbInt: Int | ||||||
|         get() = (uint shr 2).toInt() |         get() = rgbUInt.toInt() | ||||||
|  |     val ahexUInt | ||||||
|  |         get() = (a * 0x1000000).toUInt() + rgbUInt | ||||||
|  |  | ||||||
|     val r: Int |     val r: Int | ||||||
|         get() = ((uint and 0xff000000u) / 0x1000000u).toInt() |         get() = ((hexaUInt and 0xff000000u) / 0x1000000u).toInt() | ||||||
|     val g: Int |     val g: Int | ||||||
|         get() = ((uint and 0x00ff0000u) / 0x10000u).toInt() |         get() = ((hexaUInt and 0x00ff0000u) / 0x10000u).toInt() | ||||||
|     val b: Int |     val b: Int | ||||||
|         get() = ((uint and 0x0000ff00u) / 0x100u).toInt() |         get() = ((hexaUInt and 0x0000ff00u) / 0x100u).toInt() | ||||||
|     val a: Int |     val a: Int | ||||||
|         get() = ((uint and 0x000000ffu)).toInt() |         get() = ((hexaUInt and 0x000000ffu)).toInt() | ||||||
|     val aOfOne: Float |     val aOfOne: Float | ||||||
|         get() = a.toFloat() / (0xff) |         get() = a.toFloat() / (0xff) | ||||||
|     init { |     init { | ||||||
|         require(uint in 0u ..0xffffffffu) |         require(hexaUInt in 0u ..0xffffffffu) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     constructor(r: Int, g: Int, b: Int, a: Int) : this( |     constructor(r: Int, g: Int, b: Int, a: Int) : this( | ||||||
| @@ -64,7 +82,7 @@ value class HEXAColor ( | |||||||
|         return hexa |         return hexa | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun compareTo(other: HEXAColor): Int = (uint - other.uint).coerceIn(Int.MIN_VALUE.toUInt(), Int.MAX_VALUE.toLong().toUInt()).toInt() |     override fun compareTo(other: HEXAColor): Int = (hexaUInt - other.hexaUInt).coerceIn(Int.MIN_VALUE.toUInt(), Int.MAX_VALUE.toLong().toUInt()).toInt() | ||||||
|  |  | ||||||
|     fun copy( |     fun copy( | ||||||
|         r: Int = this.r, |         r: Int = this.r, | ||||||
| @@ -121,6 +139,21 @@ value class HEXAColor ( | |||||||
|             else -> color |             else -> color | ||||||
|         }.lowercase().toUInt(16).let(::HEXAColor) |         }.lowercase().toUInt(16).let(::HEXAColor) | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * Creates [HEXAColor] from [uint] presume it is in format `0xFFEEBBAA` where FF - red, EE - green, BB - blue` and AA - alpha | ||||||
|  |          */ | ||||||
|  |         fun fromHexa(uint: UInt) = HEXAColor(uint) | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * Creates [HEXAColor] from [uint] presume it is in format `0xAAFFEEBB` where AA - alpha, FF - red, EE - green and BB - blue` | ||||||
|  |          */ | ||||||
|  |         fun fromAhex(uint: UInt) = HEXAColor( | ||||||
|  |             a = ((uint and 0xff000000u) / 0x1000000u).toInt(), | ||||||
|  |             r = ((uint and 0x00ff0000u) / 0x10000u).toInt(), | ||||||
|  |             g = ((uint and 0x0000ff00u) / 0x100u).toInt(), | ||||||
|  |             b = ((uint and 0x000000ffu)).toInt() | ||||||
|  |         ) | ||||||
|  |  | ||||||
|         /** |         /** | ||||||
|          * Parsing color from [color] |          * Parsing color from [color] | ||||||
|          * |          * | ||||||
|   | |||||||
| @@ -13,6 +13,9 @@ class HexColorTests { | |||||||
|         val shortHexa: String, |         val shortHexa: String, | ||||||
|         val hex: String, |         val hex: String, | ||||||
|         val hexa: String, |         val hexa: String, | ||||||
|  |         val ahex: String, | ||||||
|  |         val ahexUInt: UInt, | ||||||
|  |         val rgbUInt: UInt, | ||||||
|         val rgb: String, |         val rgb: String, | ||||||
|         val rgba: String, |         val rgba: String, | ||||||
|         val r: Int, |         val r: Int, | ||||||
| @@ -24,11 +27,14 @@ class HexColorTests { | |||||||
|     val testColors: List<TestColor> |     val testColors: List<TestColor> | ||||||
|         get() = listOf( |         get() = listOf( | ||||||
|             TestColor( |             TestColor( | ||||||
|                 color = HEXAColor(uint = 0xff0000ffu), |                 color = HEXAColor(hexaUInt = 0xff0000ffu), | ||||||
|                 shortHex = "#f00", |                 shortHex = "#f00", | ||||||
|                 shortHexa = "#f00f", |                 shortHexa = "#f00f", | ||||||
|                 hex = "#ff0000", |                 hex = "#ff0000", | ||||||
|                 hexa = "#ff0000ff", |                 hexa = "#ff0000ff", | ||||||
|  |                 ahex = "#ffff0000", | ||||||
|  |                 ahexUInt = 0xffff0000u, | ||||||
|  |                 rgbUInt = 0xff0000u, | ||||||
|                 rgb = "rgb(255,0,0)", |                 rgb = "rgb(255,0,0)", | ||||||
|                 rgba = "rgba(255,0,0,1.0)", |                 rgba = "rgba(255,0,0,1.0)", | ||||||
|                 r = 0xff, |                 r = 0xff, | ||||||
| @@ -38,11 +44,14 @@ class HexColorTests { | |||||||
|                 "rgba(255,0,0,1)", |                 "rgba(255,0,0,1)", | ||||||
|             ), |             ), | ||||||
|             TestColor( |             TestColor( | ||||||
|                 color = HEXAColor(uint = 0x00ff00ffu), |                 color = HEXAColor(hexaUInt = 0x00ff00ffu), | ||||||
|                 shortHex = "#0f0", |                 shortHex = "#0f0", | ||||||
|                 shortHexa = "#0f0f", |                 shortHexa = "#0f0f", | ||||||
|                 hex = "#00ff00", |                 hex = "#00ff00", | ||||||
|                 hexa = "#00ff00ff", |                 hexa = "#00ff00ff", | ||||||
|  |                 ahex = "#ff00ff00", | ||||||
|  |                 ahexUInt = 0xff00ff00u, | ||||||
|  |                 rgbUInt = 0x00ff00u, | ||||||
|                 rgb = "rgb(0,255,0)", |                 rgb = "rgb(0,255,0)", | ||||||
|                 rgba = "rgba(0,255,0,1.0)", |                 rgba = "rgba(0,255,0,1.0)", | ||||||
|                 r = 0x00, |                 r = 0x00, | ||||||
| @@ -57,6 +66,9 @@ class HexColorTests { | |||||||
|                 shortHexa = "#00ff", |                 shortHexa = "#00ff", | ||||||
|                 hex = "#0000ff", |                 hex = "#0000ff", | ||||||
|                 hexa = "#0000ffff", |                 hexa = "#0000ffff", | ||||||
|  |                 ahex = "#ff0000ff", | ||||||
|  |                 ahexUInt = 0xff0000ffu, | ||||||
|  |                 rgbUInt = 0x0000ffu, | ||||||
|                 rgb = "rgb(0,0,255)", |                 rgb = "rgb(0,0,255)", | ||||||
|                 rgba = "rgba(0,0,255,1.0)", |                 rgba = "rgba(0,0,255,1.0)", | ||||||
|                 r = 0x00, |                 r = 0x00, | ||||||
| @@ -71,6 +83,9 @@ class HexColorTests { | |||||||
|                 shortHexa = "#f008", |                 shortHexa = "#f008", | ||||||
|                 hex = "#ff0000", |                 hex = "#ff0000", | ||||||
|                 hexa = "#ff000088", |                 hexa = "#ff000088", | ||||||
|  |                 ahex = "#88ff0000", | ||||||
|  |                 ahexUInt = 0x88ff0000u, | ||||||
|  |                 rgbUInt = 0xff0000u, | ||||||
|                 rgb = "rgb(255,0,0)", |                 rgb = "rgb(255,0,0)", | ||||||
|                 rgba = "rgba(255,0,0,0.533)", |                 rgba = "rgba(255,0,0,0.533)", | ||||||
|                 r = 0xff, |                 r = 0xff, | ||||||
| @@ -84,6 +99,9 @@ class HexColorTests { | |||||||
|                 shortHexa = "#0f08", |                 shortHexa = "#0f08", | ||||||
|                 hex = "#00ff00", |                 hex = "#00ff00", | ||||||
|                 hexa = "#00ff0088", |                 hexa = "#00ff0088", | ||||||
|  |                 ahex = "#8800ff00", | ||||||
|  |                 ahexUInt = 0x8800ff00u, | ||||||
|  |                 rgbUInt = 0x00ff00u, | ||||||
|                 rgb = "rgb(0,255,0)", |                 rgb = "rgb(0,255,0)", | ||||||
|                 rgba = "rgba(0,255,0,0.533)", |                 rgba = "rgba(0,255,0,0.533)", | ||||||
|                 r = 0x00, |                 r = 0x00, | ||||||
| @@ -97,6 +115,9 @@ class HexColorTests { | |||||||
|                 shortHexa = "#00f8", |                 shortHexa = "#00f8", | ||||||
|                 hex = "#0000ff", |                 hex = "#0000ff", | ||||||
|                 hexa = "#0000ff88", |                 hexa = "#0000ff88", | ||||||
|  |                 ahex = "#880000ff", | ||||||
|  |                 ahexUInt = 0x880000ffu, | ||||||
|  |                 rgbUInt = 0x0000ffu, | ||||||
|                 rgb = "rgb(0,0,255)", |                 rgb = "rgb(0,0,255)", | ||||||
|                 rgba = "rgba(0,0,255,0.533)", |                 rgba = "rgba(0,0,255,0.533)", | ||||||
|                 r = 0x00, |                 r = 0x00, | ||||||
| @@ -110,6 +131,9 @@ class HexColorTests { | |||||||
|                 shortHexa = "#f002", |                 shortHexa = "#f002", | ||||||
|                 hex = "#ff0000", |                 hex = "#ff0000", | ||||||
|                 hexa = "#ff000022", |                 hexa = "#ff000022", | ||||||
|  |                 ahex = "#22ff0000", | ||||||
|  |                 ahexUInt = 0x22ff0000u, | ||||||
|  |                 rgbUInt = 0xff0000u, | ||||||
|                 rgb = "rgb(255,0,0)", |                 rgb = "rgb(255,0,0)", | ||||||
|                 rgba = "rgba(255,0,0,0.133)", |                 rgba = "rgba(255,0,0,0.133)", | ||||||
|                 r = 0xff, |                 r = 0xff, | ||||||
| @@ -123,6 +147,9 @@ class HexColorTests { | |||||||
|                 shortHexa = "#0f02", |                 shortHexa = "#0f02", | ||||||
|                 hex = "#00ff00", |                 hex = "#00ff00", | ||||||
|                 hexa = "#00ff0022", |                 hexa = "#00ff0022", | ||||||
|  |                 ahex = "#2200ff00", | ||||||
|  |                 ahexUInt = 0x2200ff00u, | ||||||
|  |                 rgbUInt = 0x00ff00u, | ||||||
|                 rgb = "rgb(0,255,0)", |                 rgb = "rgb(0,255,0)", | ||||||
|                 rgba = "rgba(0,255,0,0.133)", |                 rgba = "rgba(0,255,0,0.133)", | ||||||
|                 r = 0x00, |                 r = 0x00, | ||||||
| @@ -136,6 +163,9 @@ class HexColorTests { | |||||||
|                 shortHexa = "#00f2", |                 shortHexa = "#00f2", | ||||||
|                 hex = "#0000ff", |                 hex = "#0000ff", | ||||||
|                 hexa = "#0000ff22", |                 hexa = "#0000ff22", | ||||||
|  |                 ahex = "#220000ff", | ||||||
|  |                 ahexUInt = 0x220000ffu, | ||||||
|  |                 rgbUInt = 0x0000ffu, | ||||||
|                 rgb = "rgb(0,0,255)", |                 rgb = "rgb(0,0,255)", | ||||||
|                 rgba = "rgba(0,0,255,0.133)", |                 rgba = "rgba(0,0,255,0.133)", | ||||||
|                 r = 0x00, |                 r = 0x00, | ||||||
| @@ -150,6 +180,9 @@ class HexColorTests { | |||||||
|         testColors.forEach { |         testColors.forEach { | ||||||
|             assertEquals(it.hex, it.color.hex) |             assertEquals(it.hex, it.color.hex) | ||||||
|             assertEquals(it.hexa, it.color.hexa) |             assertEquals(it.hexa, it.color.hexa) | ||||||
|  |             assertEquals(it.ahex, it.color.ahex) | ||||||
|  |             assertEquals(it.rgbUInt, it.color.rgbUInt) | ||||||
|  |             assertEquals(it.ahexUInt, it.color.ahexUInt) | ||||||
|             assertEquals(it.shortHex, it.color.shortHex) |             assertEquals(it.shortHex, it.color.shortHex) | ||||||
|             assertEquals(it.shortHexa, it.color.shortHexa) |             assertEquals(it.shortHexa, it.color.shortHexa) | ||||||
|             assertEquals(it.rgb, it.color.rgb) |             assertEquals(it.rgb, it.color.rgb) | ||||||
| @@ -158,6 +191,7 @@ class HexColorTests { | |||||||
|             assertEquals(it.g, it.color.g) |             assertEquals(it.g, it.color.g) | ||||||
|             assertEquals(it.b, it.color.b) |             assertEquals(it.b, it.color.b) | ||||||
|             assertEquals(it.a, it.color.a) |             assertEquals(it.a, it.color.a) | ||||||
|  |             assertEquals(it.color, HEXAColor.fromAhex(it.ahexUInt)) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -167,7 +201,7 @@ class HexColorTests { | |||||||
|             assertEquals(it.color.copy(aOfOne = 1f), HEXAColor.parseStringColor(it.hex)) |             assertEquals(it.color.copy(aOfOne = 1f), HEXAColor.parseStringColor(it.hex)) | ||||||
|             assertEquals(it.color, HEXAColor.parseStringColor(it.hexa)) |             assertEquals(it.color, HEXAColor.parseStringColor(it.hexa)) | ||||||
|             assertEquals(it.color.copy(aOfOne = 1f), HEXAColor.parseStringColor(it.rgb)) |             assertEquals(it.color.copy(aOfOne = 1f), HEXAColor.parseStringColor(it.rgb)) | ||||||
|             assertTrue(it.color.uint.toInt() - HEXAColor.parseStringColor(it.rgba).uint.toInt() in -0x1 .. 0x1, ) |             assertTrue(it.color.hexaUInt.toInt() - HEXAColor.parseStringColor(it.rgba).hexaUInt.toInt() in -0x1 .. 0x1, ) | ||||||
|             assertEquals(it.color.copy(aOfOne = 1f), HEXAColor.parseStringColor(it.shortHex)) |             assertEquals(it.color.copy(aOfOne = 1f), HEXAColor.parseStringColor(it.shortHex)) | ||||||
|             assertEquals(it.color.copy(a = floor(it.color.a.toFloat() / 16).toInt() * 0x10), HEXAColor.parseStringColor(it.shortHexa)) |             assertEquals(it.color.copy(a = floor(it.color.a.toFloat() / 16).toInt() * 0x10), HEXAColor.parseStringColor(it.shortHexa)) | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -8,6 +8,11 @@ apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64ProjectPresetPath" | |||||||
|  |  | ||||||
| kotlin { | kotlin { | ||||||
|     sourceSets { |     sourceSets { | ||||||
|  |         commonMain { | ||||||
|  |             dependencies { | ||||||
|  |                 api libs.klock | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         jvmMain { |         jvmMain { | ||||||
|             dependencies { |             dependencies { | ||||||
|                 api project(":micro_utils.coroutines") |                 api project(":micro_utils.coroutines") | ||||||
|   | |||||||
| @@ -0,0 +1,23 @@ | |||||||
|  | package dev.inmo.micro_utils.common | ||||||
|  |  | ||||||
|  | import korlibs.time.DateTime | ||||||
|  | import kotlinx.serialization.KSerializer | ||||||
|  | import kotlinx.serialization.Serializer | ||||||
|  | import kotlinx.serialization.builtins.serializer | ||||||
|  | import kotlinx.serialization.descriptors.SerialDescriptor | ||||||
|  | import kotlinx.serialization.encoding.Decoder | ||||||
|  | import kotlinx.serialization.encoding.Encoder | ||||||
|  |  | ||||||
|  | @Serializer(DateTime::class) | ||||||
|  | object DateTimeSerializer : KSerializer<DateTime> { | ||||||
|  |     override val descriptor: SerialDescriptor | ||||||
|  |         get() = Double.serializer().descriptor | ||||||
|  |  | ||||||
|  |     override fun deserialize(decoder: Decoder): DateTime { | ||||||
|  |         return DateTime(decoder.decodeDouble()) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun serialize(encoder: Encoder, value: DateTime) { | ||||||
|  |         encoder.encodeDouble(value.unixMillis) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -15,5 +15,5 @@ crypto_js_version=4.1.1 | |||||||
| # Project data | # Project data | ||||||
|  |  | ||||||
| group=dev.inmo | group=dev.inmo | ||||||
| version=0.20.32 | version=0.20.49 | ||||||
| android_code_version=238 | android_code_version=255 | ||||||
|   | |||||||
| @@ -1,41 +1,41 @@ | |||||||
| [versions] | [versions] | ||||||
|  |  | ||||||
| kt = "1.9.22" | kt = "1.9.23" | ||||||
| kt-serialization = "1.6.2" | kt-serialization = "1.6.3" | ||||||
| kt-coroutines = "1.7.3" | kt-coroutines = "1.8.0" | ||||||
|  |  | ||||||
| kslog = "1.3.2" | kslog = "1.3.3" | ||||||
|  |  | ||||||
| jb-compose = "1.5.12" | jb-compose = "1.6.2" | ||||||
| jb-exposed = "0.47.0" | jb-exposed = "0.50.0" | ||||||
| jb-dokka = "1.9.10" | jb-dokka = "1.9.20" | ||||||
|  |  | ||||||
| korlibs = "5.3.1" | korlibs = "5.4.0" | ||||||
| uuid = "0.8.2" | uuid = "0.8.4" | ||||||
|  |  | ||||||
| ktor = "2.3.8" | ktor = "2.3.10" | ||||||
|  |  | ||||||
| gh-release = "2.5.2" | gh-release = "2.5.2" | ||||||
|  |  | ||||||
| koin = "3.5.3" | koin = "3.5.6" | ||||||
|  |  | ||||||
| okio = "3.8.0" | okio = "3.9.0" | ||||||
|  |  | ||||||
| ksp = "1.9.22-1.0.17" | ksp = "1.9.23-1.0.20" | ||||||
| kotlin-poet = "1.16.0" | kotlin-poet = "1.16.0" | ||||||
|  |  | ||||||
| versions = "0.51.0" | versions = "0.51.0" | ||||||
|  |  | ||||||
| android-gradle = "8.2.2" | android-gradle = "8.4.0" | ||||||
| dexcount = "4.0.0" | dexcount = "4.0.0" | ||||||
|  |  | ||||||
| android-coreKtx = "1.12.0" | android-coreKtx = "1.13.1" | ||||||
| android-recyclerView = "1.3.2" | android-recyclerView = "1.3.2" | ||||||
| android-appCompat = "1.6.1" | android-appCompat = "1.6.1" | ||||||
| android-fragment = "1.6.2" | android-fragment = "1.7.0" | ||||||
| android-espresso = "3.5.1" | android-espresso = "3.5.1" | ||||||
| android-test = "1.1.5" | android-test = "1.1.5" | ||||||
| android-compose-material3 = "1.1.2" | android-compose-material3 = "1.2.1" | ||||||
|  |  | ||||||
| android-props-minSdk = "21" | android-props-minSdk = "21" | ||||||
| android-props-compileSdk = "34" | android-props-compileSdk = "34" | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | |||||||
| distributionBase=GRADLE_USER_HOME | distributionBase=GRADLE_USER_HOME | ||||||
| distributionPath=wrapper/dists | distributionPath=wrapper/dists | ||||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip | ||||||
| zipStoreBase=GRADLE_USER_HOME | zipStoreBase=GRADLE_USER_HOME | ||||||
| zipStorePath=wrapper/dists | zipStorePath=wrapper/dists | ||||||
|   | |||||||
| @@ -12,7 +12,6 @@ kotlin { | |||||||
|             dependencies { |             dependencies { | ||||||
|                 api internalProject("micro_utils.common") |                 api internalProject("micro_utils.common") | ||||||
|                 api libs.kt.serialization.cbor |                 api libs.kt.serialization.cbor | ||||||
|                 api libs.klock |  | ||||||
|                 api libs.uuid |                 api libs.uuid | ||||||
|                 api libs.ktor.io |                 api libs.ktor.io | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import dev.inmo.micro_utils.coroutines.withReadAcquire | |||||||
| import dev.inmo.micro_utils.coroutines.withWriteLock | import dev.inmo.micro_utils.coroutines.withWriteLock | ||||||
| import dev.inmo.micro_utils.repos.* | import dev.inmo.micro_utils.repos.* | ||||||
| import dev.inmo.micro_utils.repos.cache.cache.KVCache | import dev.inmo.micro_utils.repos.cache.cache.KVCache | ||||||
|  | import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||||
| import kotlinx.coroutines.CoroutineScope | import kotlinx.coroutines.CoroutineScope | ||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| @@ -29,7 +30,7 @@ open class ReadCRUDCacheRepo<ObjectType, IdType>( | |||||||
|             kvCache.getAll() |             kvCache.getAll() | ||||||
|         }.takeIf { it.size.toLong() == count() } ?: parentRepo.getAll().also { |         }.takeIf { it.size.toLong() == count() } ?: parentRepo.getAll().also { | ||||||
|             locker.withWriteLock { |             locker.withWriteLock { | ||||||
|                 kvCache.actualizeAll(true) { it } |                 kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -148,7 +149,9 @@ open class CRUDCacheRepo<ObjectType, IdType, InputValueType>( | |||||||
|     locker, |     locker, | ||||||
|     idGetter |     idGetter | ||||||
| ), | ), | ||||||
|     CRUDRepo<ObjectType, IdType, InputValueType> |     CRUDRepo<ObjectType, IdType, InputValueType> { | ||||||
|  |     override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) | ||||||
|  | } | ||||||
|  |  | ||||||
| fun <ObjectType, IdType, InputType> CRUDRepo<ObjectType, IdType, InputType>.cached( | fun <ObjectType, IdType, InputType> CRUDRepo<ObjectType, IdType, InputType>.cached( | ||||||
|     kvCache: KVCache<IdType, ObjectType>, |     kvCache: KVCache<IdType, ObjectType>, | ||||||
|   | |||||||
| @@ -1,5 +1,11 @@ | |||||||
| package dev.inmo.micro_utils.repos.cache | package dev.inmo.micro_utils.repos.cache | ||||||
|  |  | ||||||
| interface CacheRepo { | interface InvalidatableRepo { | ||||||
|  |     /** | ||||||
|  |      * Invalidates its internal data. It __may__ lead to autoreload of data. In case when repo makes autoreload, | ||||||
|  |      * it must do loading of data __before__ clear | ||||||
|  |      */ | ||||||
|     suspend fun invalidate() |     suspend fun invalidate() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | typealias CacheRepo = InvalidatableRepo | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock | |||||||
| import dev.inmo.micro_utils.pagination.* | import dev.inmo.micro_utils.pagination.* | ||||||
| import dev.inmo.micro_utils.repos.* | import dev.inmo.micro_utils.repos.* | ||||||
| import dev.inmo.micro_utils.repos.cache.cache.KVCache | import dev.inmo.micro_utils.repos.cache.cache.KVCache | ||||||
|  | import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||||
| import kotlinx.coroutines.CoroutineScope | import kotlinx.coroutines.CoroutineScope | ||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| import kotlinx.coroutines.flow.* | import kotlinx.coroutines.flow.* | ||||||
| @@ -48,9 +49,7 @@ open class ReadKeyValueCacheRepo<Key,Value>( | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override suspend fun invalidate() = locker.withWriteLock { |     override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) | ||||||
|         kvCache.clear() |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached( | fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached( | ||||||
| @@ -75,10 +74,6 @@ open class KeyValueCacheRepo<Key,Value>( | |||||||
|         } |         } | ||||||
|     }.launchIn(scope) |     }.launchIn(scope) | ||||||
|  |  | ||||||
|     override suspend fun invalidate() = locker.withWriteLock { |  | ||||||
|         kvCache.clear() |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     override suspend fun clear() { |     override suspend fun clear() { | ||||||
|         parentRepo.clear() |         parentRepo.clear() | ||||||
|         locker.withWriteLock { |         locker.withWriteLock { | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import dev.inmo.micro_utils.pagination.* | |||||||
| import dev.inmo.micro_utils.pagination.utils.* | import dev.inmo.micro_utils.pagination.utils.* | ||||||
| import dev.inmo.micro_utils.repos.* | import dev.inmo.micro_utils.repos.* | ||||||
| import dev.inmo.micro_utils.repos.cache.cache.KVCache | import dev.inmo.micro_utils.repos.cache.cache.KVCache | ||||||
|  | import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||||
| import kotlinx.coroutines.CoroutineScope | import kotlinx.coroutines.CoroutineScope | ||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| import kotlinx.coroutines.flow.* | import kotlinx.coroutines.flow.* | ||||||
| @@ -47,9 +48,7 @@ open class ReadKeyValuesCacheRepo<Key,Value>( | |||||||
|         kvCache.contains(k) |         kvCache.contains(k) | ||||||
|     } || parentRepo.contains(k) |     } || parentRepo.contains(k) | ||||||
|  |  | ||||||
|     override suspend fun invalidate() = locker.withWriteLock { |     override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) | ||||||
|         kvCache.clear() |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached( | fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached( | ||||||
| @@ -84,10 +83,6 @@ open class KeyValuesCacheRepo<Key,Value>( | |||||||
|             kvCache.unset(it) |             kvCache.unset(it) | ||||||
|         } |         } | ||||||
|     }.launchIn(scope) |     }.launchIn(scope) | ||||||
|  |  | ||||||
|     override suspend fun invalidate() = locker.withWriteLock { |  | ||||||
|         kvCache.clear() |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| fun <Key, Value> KeyValuesRepo<Key, Value>.cached( | fun <Key, Value> KeyValuesRepo<Key, Value>.cached( | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.repos.ReadCRUDRepo | |||||||
| import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper | import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper | ||||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||||
| import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo | import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo | ||||||
|  | import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||||
| import dev.inmo.micro_utils.repos.set | import dev.inmo.micro_utils.repos.set | ||||||
| import kotlinx.coroutines.CoroutineScope | import kotlinx.coroutines.CoroutineScope | ||||||
| import kotlinx.coroutines.delay | import kotlinx.coroutines.delay | ||||||
| @@ -56,7 +57,7 @@ open class AutoRecacheReadCRUDRepo<RegisteredObject, Id>( | |||||||
|     override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap { |     override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap { | ||||||
|         originalRepo.getAll() |         originalRepo.getAll() | ||||||
|     }.onSuccess { |     }.onSuccess { | ||||||
|         kvCache.actualizeAll(clear = true) { it } |         kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } | ||||||
|     }.getOrElse { |     }.getOrElse { | ||||||
|         kvCache.getAll() |         kvCache.getAll() | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.repos.ReadKeyValueRepo | |||||||
| import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper | import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper | ||||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||||
| import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo | import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo | ||||||
|  | import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||||
| import dev.inmo.micro_utils.repos.set | import dev.inmo.micro_utils.repos.set | ||||||
| import kotlinx.coroutines.CoroutineScope | import kotlinx.coroutines.CoroutineScope | ||||||
| import kotlinx.coroutines.delay | import kotlinx.coroutines.delay | ||||||
| @@ -56,7 +57,7 @@ open class AutoRecacheReadKeyValueRepo<Id, RegisteredObject>( | |||||||
|     override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap { |     override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap { | ||||||
|         originalRepo.getAll() |         originalRepo.getAll() | ||||||
|     }.onSuccess { |     }.onSuccess { | ||||||
|         kvCache.actualizeAll(clear = true) { it } |         kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } | ||||||
|     }.getOrElse { |     }.getOrElse { | ||||||
|         kvCache.getAll() |         kvCache.getAll() | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.pagination.Pagination | |||||||
| import dev.inmo.micro_utils.pagination.PaginationResult | import dev.inmo.micro_utils.pagination.PaginationResult | ||||||
| import dev.inmo.micro_utils.repos.* | import dev.inmo.micro_utils.repos.* | ||||||
| import dev.inmo.micro_utils.repos.cache.* | import dev.inmo.micro_utils.repos.cache.* | ||||||
|  | import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||||
| import kotlinx.coroutines.CoroutineScope | import kotlinx.coroutines.CoroutineScope | ||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| @@ -42,7 +43,7 @@ open class FullReadCRUDCacheRepo<ObjectType, IdType>( | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     protected open suspend fun actualizeAll() { |     protected open suspend fun actualizeAll() { | ||||||
|         locker.withWriteLock { kvCache.actualizeAll(parentRepo) } |         kvCache.actualizeAll(parentRepo, locker = locker) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> = doOrTakeAndActualize( |     override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> = doOrTakeAndActualize( | ||||||
| @@ -72,7 +73,7 @@ open class FullReadCRUDCacheRepo<ObjectType, IdType>( | |||||||
|     override suspend fun getAll(): Map<IdType, ObjectType> = doOrTakeAndActualizeWithWriteLock( |     override suspend fun getAll(): Map<IdType, ObjectType> = doOrTakeAndActualizeWithWriteLock( | ||||||
|         { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, |         { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, | ||||||
|         { getAll() }, |         { getAll() }, | ||||||
|         { kvCache.actualizeAll(clear = true) { it } } |         { kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } } | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualizeWithWriteLock( |     override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualizeWithWriteLock( | ||||||
|   | |||||||
| @@ -8,8 +8,8 @@ import dev.inmo.micro_utils.coroutines.withWriteLock | |||||||
| import dev.inmo.micro_utils.pagination.Pagination | import dev.inmo.micro_utils.pagination.Pagination | ||||||
| import dev.inmo.micro_utils.pagination.PaginationResult | import dev.inmo.micro_utils.pagination.PaginationResult | ||||||
| import dev.inmo.micro_utils.repos.* | import dev.inmo.micro_utils.repos.* | ||||||
|  | import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||||
| import dev.inmo.micro_utils.repos.pagination.getAll |  | ||||||
| import kotlinx.coroutines.CoroutineScope | import kotlinx.coroutines.CoroutineScope | ||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| import kotlinx.coroutines.flow.* | import kotlinx.coroutines.flow.* | ||||||
| @@ -41,10 +41,7 @@ open class FullReadKeyValueCacheRepo<Key,Value>( | |||||||
|         actualize = { locker.withWriteLock { actualize(it) } } |         actualize = { locker.withWriteLock { actualize(it) } } | ||||||
|     ) |     ) | ||||||
|     protected open suspend fun actualizeAll() { |     protected open suspend fun actualizeAll() { | ||||||
|         locker.withWriteLock { |         kvCache.actualizeAll(parentRepo, locker) | ||||||
|             kvCache.clear() |  | ||||||
|             kvCache.set(parentRepo.getAll()) |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override suspend fun get(k: Key): Value? = doOrTakeAndActualizeWithWriteLock( |     override suspend fun get(k: Key): Value? = doOrTakeAndActualizeWithWriteLock( | ||||||
| @@ -74,7 +71,7 @@ open class FullReadKeyValueCacheRepo<Key,Value>( | |||||||
|     override suspend fun getAll(): Map<Key, Value> = doOrTakeAndActualizeWithWriteLock( |     override suspend fun getAll(): Map<Key, Value> = doOrTakeAndActualizeWithWriteLock( | ||||||
|         { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, |         { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, | ||||||
|         { getAll() }, |         { getAll() }, | ||||||
|         { kvCache.actualizeAll(clear = true) { it } } |         { kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } } | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = doOrTakeAndActualize( |     override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = doOrTakeAndActualize( | ||||||
| @@ -150,9 +147,7 @@ open class FullKeyValueCacheRepo<Key,Value>( | |||||||
|     override suspend fun unsetWithValues(toUnset: List<Value>) = parentRepo.unsetWithValues(toUnset) |     override suspend fun unsetWithValues(toUnset: List<Value>) = parentRepo.unsetWithValues(toUnset) | ||||||
|  |  | ||||||
|     override suspend fun invalidate() { |     override suspend fun invalidate() { | ||||||
|         locker.withWriteLock { |         kvCache.actualizeAll(parentRepo, locker) | ||||||
|             kvCache.actualizeAll(parentRepo) |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override suspend fun clear() { |     override suspend fun clear() { | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock | |||||||
| import dev.inmo.micro_utils.pagination.* | import dev.inmo.micro_utils.pagination.* | ||||||
| import dev.inmo.micro_utils.pagination.utils.* | import dev.inmo.micro_utils.pagination.utils.* | ||||||
| import dev.inmo.micro_utils.repos.* | import dev.inmo.micro_utils.repos.* | ||||||
|  | import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||||
| import kotlinx.coroutines.CoroutineScope | import kotlinx.coroutines.CoroutineScope | ||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| @@ -41,15 +42,13 @@ open class FullReadKeyValuesCacheRepo<Key,Value>( | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     protected open suspend fun actualizeKey(k: Key) { |     protected open suspend fun actualizeKey(k: Key) { | ||||||
|         locker.withWriteLock { |         kvCache.actualizeAll(locker = locker, clearMode = ActualizeAllClearMode.Never) { | ||||||
|             kvCache.set(k, parentRepo.getAll(k)) |             mapOf(k to parentRepo.getAll(k)) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     protected open suspend fun actualizeAll() { |     protected open suspend fun actualizeAll() { | ||||||
|         locker.withWriteLock { |         kvCache.actualizeAll(parentRepo, locker = locker) | ||||||
|             kvCache.actualizeAll(parentRepo) |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> { |     override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> { | ||||||
| @@ -187,9 +186,11 @@ open class FullKeyValuesCacheRepo<Key,Value>( | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     override suspend fun invalidate() { |     override suspend fun invalidate() { | ||||||
|         locker.withWriteLock { |         kvCache.actualizeAll(parentRepo, locker = locker) | ||||||
|             kvCache.actualizeAll(parentRepo) |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     override suspend fun set(toSet: Map<Key, List<Value>>) { | ||||||
|  |         super<KeyValuesRepo>.set(toSet) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override suspend fun removeWithValue(v: Value) { |     override suspend fun removeWithValue(v: Value) { | ||||||
|   | |||||||
| @@ -1,43 +1,169 @@ | |||||||
| package dev.inmo.micro_utils.repos.cache.util | package dev.inmo.micro_utils.repos.cache.util | ||||||
|  |  | ||||||
|  | import dev.inmo.micro_utils.coroutines.SmartRWLocker | ||||||
|  | import dev.inmo.micro_utils.coroutines.withWriteLock | ||||||
| import dev.inmo.micro_utils.repos.* | import dev.inmo.micro_utils.repos.* | ||||||
|  | import kotlinx.serialization.Serializable | ||||||
|  | import kotlin.js.JsName | ||||||
|  | import kotlin.jvm.JvmName | ||||||
|  |  | ||||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | /** | ||||||
|     clear: Boolean = true, |  * `invalidate`/`actualizeAll` clearing mode. Declare when data in original repo will be cleared | ||||||
|  |  */ | ||||||
|  | @Serializable | ||||||
|  | sealed interface ActualizeAllClearMode { | ||||||
|  |     /** | ||||||
|  |      * Instruct user of this mode to clear internal data __before load__ of external data | ||||||
|  |      */ | ||||||
|  |     @Serializable | ||||||
|  |     data object BeforeLoad : ActualizeAllClearMode | ||||||
|  |     /** | ||||||
|  |      * Instruct user of this mode to clear internal data __after load__ of external data and __before set__ of internal data | ||||||
|  |      */ | ||||||
|  |     @Serializable | ||||||
|  |     data object BeforeSet : ActualizeAllClearMode | ||||||
|  |     /** | ||||||
|  |      * Instruct user of this mode to never clear internal data | ||||||
|  |      */ | ||||||
|  |     @Serializable | ||||||
|  |     data object Never : ActualizeAllClearMode | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeLoad( | ||||||
|     getAll: () -> Map<K, V> |     getAll: () -> Map<K, V> | ||||||
| ) { | ) { | ||||||
|     set( |     clear() | ||||||
|         getAll().also { |     val newData = getAll() | ||||||
|             if (clear) { |     set(newData) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeSet( | ||||||
|  |     getAll: () -> Map<K, V> | ||||||
|  | ) { | ||||||
|  |     val newData = getAll() | ||||||
|  |     clear() | ||||||
|  |     set(newData) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithoutClear( | ||||||
|  |     getAll: () -> Map<K, V> | ||||||
|  | ) { | ||||||
|  |     val newData = getAll() | ||||||
|  |     set(newData) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @JvmName("actualizeAllWithClearBeforeLoadWithLocker") | ||||||
|  | @JsName("actualizeAllWithClearBeforeLoadWithLocker") | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeLoad( | ||||||
|  |     locker: SmartRWLocker, | ||||||
|  |     getAll: () -> Map<K, V> | ||||||
|  | ) { | ||||||
|  |     locker.withWriteLock { | ||||||
|         clear() |         clear() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     val newData = getAll() | ||||||
|  |     locker.withWriteLock { | ||||||
|  |         set(newData) | ||||||
|     } |     } | ||||||
|     ) | } | ||||||
|  |  | ||||||
|  | @JvmName("actualizeAllWithClearBeforeSetWithLocker") | ||||||
|  | @JsName("actualizeAllWithClearBeforeSetWithLocker") | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeSet( | ||||||
|  |     locker: SmartRWLocker, | ||||||
|  |     getAll: () -> Map<K, V> | ||||||
|  | ) { | ||||||
|  |     val newData = getAll() | ||||||
|  |     locker.withWriteLock { | ||||||
|  |         clear() | ||||||
|  |         set(newData) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @JvmName("actualizeAllWithoutClearWithLocker") | ||||||
|  | @JsName("actualizeAllWithoutClearWithLocker") | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithoutClear( | ||||||
|  |     locker: SmartRWLocker, | ||||||
|  |     getAll: () -> Map<K, V> | ||||||
|  | ) { | ||||||
|  |     val newData = getAll() | ||||||
|  |     locker.withWriteLock { | ||||||
|  |         set(newData) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeLoad( | ||||||
|  |     locker: SmartRWLocker? = null, | ||||||
|  |     getAll: () -> Map<K, V> | ||||||
|  | ) { | ||||||
|  |     locker ?.let { | ||||||
|  |         actualizeAllWithClearBeforeLoad(locker = locker, getAll) | ||||||
|  |     } ?: actualizeAllWithClearBeforeLoad(getAll) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeSet( | ||||||
|  |     locker: SmartRWLocker? = null, | ||||||
|  |     getAll: () -> Map<K, V> | ||||||
|  | ) { | ||||||
|  |     locker ?.let { | ||||||
|  |         actualizeAllWithClearBeforeSet(locker = locker, getAll) | ||||||
|  |     } ?: actualizeAllWithClearBeforeSet(getAll) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithoutClear( | ||||||
|  |     locker: SmartRWLocker? = null, | ||||||
|  |     getAll: () -> Map<K, V> | ||||||
|  | ) { | ||||||
|  |     locker ?.let { | ||||||
|  |         actualizeAllWithoutClear(locker = locker, getAll) | ||||||
|  |     } ?: actualizeAllWithoutClear(getAll) | ||||||
| } | } | ||||||
|  |  | ||||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | ||||||
|     repo: ReadKeyValueRepo<K, V>, |     locker: SmartRWLocker? = null, | ||||||
|     clear: Boolean = true, |     clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, | ||||||
|  |     getAll: () -> Map<K, V> | ||||||
| ) { | ) { | ||||||
|     actualizeAll(clear) { |     when (clearMode) { | ||||||
|         repo.getAll() |         ActualizeAllClearMode.BeforeLoad -> locker ?.let { | ||||||
|  |             actualizeAllWithClearBeforeLoad(locker = locker, getAll) | ||||||
|  |         } ?: actualizeAllWithClearBeforeLoad(getAll) | ||||||
|  |         ActualizeAllClearMode.BeforeSet -> locker ?.let { | ||||||
|  |             actualizeAllWithClearBeforeSet(locker = locker, getAll) | ||||||
|  |         } ?: actualizeAllWithClearBeforeSet(getAll) | ||||||
|  |         ActualizeAllClearMode.Never -> locker ?.let { | ||||||
|  |             actualizeAllWithoutClear(locker = locker, getAll) | ||||||
|  |         } ?: actualizeAllWithoutClear(getAll) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | ||||||
|  |     parentRepo: ReadKeyValueRepo<K, V>, | ||||||
|  |     locker: SmartRWLocker? = null, | ||||||
|  |     clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, | ||||||
|  | ) { | ||||||
|  |     actualizeAll(locker, clearMode) { | ||||||
|  |         parentRepo.getAll() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| suspend inline fun <K, V> KeyValueRepo<K, List<V>>.actualizeAll( | suspend inline fun <K, V> KeyValueRepo<K, List<V>>.actualizeAll( | ||||||
|     repo: ReadKeyValuesRepo<K, V>, |     parentRepo: ReadKeyValuesRepo<K, V>, | ||||||
|     clear: Boolean = true, |     locker: SmartRWLocker? = null, | ||||||
|  |     clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, | ||||||
| ) { | ) { | ||||||
|     actualizeAll(clear) { |     actualizeAll(locker, clearMode) { | ||||||
|         repo.getAll() |         parentRepo.getAll() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | ||||||
|     repo: ReadCRUDRepo<V, K>, |     parentRepo: ReadCRUDRepo<V, K>, | ||||||
|     clear: Boolean = true, |     locker: SmartRWLocker? = null, | ||||||
|  |     clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, | ||||||
| ) { | ) { | ||||||
|     actualizeAll(clear) { |     actualizeAll(locker, clearMode) { | ||||||
|         repo.getAll() |         parentRepo.getAll() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| package dev.inmo.micro_utils.repos | package dev.inmo.micro_utils.repos | ||||||
|  |  | ||||||
|  | import dev.inmo.micro_utils.common.diff | ||||||
| import dev.inmo.micro_utils.pagination.* | import dev.inmo.micro_utils.pagination.* | ||||||
| import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging | import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging | ||||||
| import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging | import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging | ||||||
| @@ -130,6 +131,14 @@ interface KeyValuesRepo<Key, Value> : ReadKeyValuesRepo<Key, Value>, WriteKeyVal | |||||||
|  |  | ||||||
|         remove(toRemove) |         remove(toRemove) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     override suspend fun set(toSet: Map<Key, List<Value>>) { | ||||||
|  |         toSet.forEach { (k, v) -> | ||||||
|  |             val diff = getAll(k).diff(v) | ||||||
|  |             remove(k, diff.removed.map { it.value }) | ||||||
|  |             add(k, diff.added.map { it.value }) | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| typealias OneToManyKeyValueRepo<Key,Value> = KeyValuesRepo<Key, Value> | typealias OneToManyKeyValueRepo<Key,Value> = KeyValuesRepo<Key, Value> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,6 +42,22 @@ interface WriteCRUDRepo<ObjectType, IdType, InputValueType> : Repo { | |||||||
| } | } | ||||||
| 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 | ||||||
|  |  */ | ||||||
|  | val <ObjectType> WriteCRUDRepo<ObjectType, *, *>.onNewObjects: Flow<ObjectType> | ||||||
|  |     get() = newObjectsFlow | ||||||
|  | /** | ||||||
|  |  * Just mirroring [WriteCRUDRepo.updatedObjectsFlow] to be same as in KV repos | ||||||
|  |  */ | ||||||
|  | val <ObjectType> WriteCRUDRepo<ObjectType, *, *>.onUpdatedObjects: Flow<ObjectType> | ||||||
|  |     get() = updatedObjectsFlow | ||||||
|  | /** | ||||||
|  |  * Just mirroring [WriteCRUDRepo.deletedObjectsIdsFlow] to be same as in KV repos | ||||||
|  |  */ | ||||||
|  | val <IdType> WriteCRUDRepo<*, IdType, *>.onDeletedObjectsIds: Flow<IdType> | ||||||
|  |     get() = deletedObjectsIdsFlow | ||||||
|  |  | ||||||
| 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()) | ||||||
|   | |||||||
| @@ -0,0 +1,20 @@ | |||||||
|  | package dev.inmo.micro_utils.repos.diff | ||||||
|  |  | ||||||
|  | import dev.inmo.micro_utils.common.MapDiff | ||||||
|  | import dev.inmo.micro_utils.common.applyDiff | ||||||
|  | import dev.inmo.micro_utils.common.diff | ||||||
|  | import dev.inmo.micro_utils.repos.CRUDRepo | ||||||
|  | import dev.inmo.micro_utils.repos.ReadCRUDRepo | ||||||
|  | import dev.inmo.micro_utils.repos.unset | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> ReadCRUDRepo<Registered, Id>.diff(other: Map<Id, Registered>): MapDiff<Id, Registered> { | ||||||
|  |     return getAll().diff(other) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> Map<Id, Registered>.diff(other: ReadCRUDRepo<Registered, Id>): MapDiff<Id, Registered> { | ||||||
|  |     return diff(other.getAll()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> MutableMap<Id, Registered>.applyDiff(other: ReadCRUDRepo<Registered, Id>) { | ||||||
|  |     applyDiff(diff(other)) | ||||||
|  | } | ||||||
| @@ -0,0 +1,33 @@ | |||||||
|  | package dev.inmo.micro_utils.repos.diff | ||||||
|  |  | ||||||
|  | import dev.inmo.micro_utils.common.MapDiff | ||||||
|  | import dev.inmo.micro_utils.common.applyDiff | ||||||
|  | import dev.inmo.micro_utils.common.diff | ||||||
|  | import dev.inmo.micro_utils.repos.KeyValueRepo | ||||||
|  | import dev.inmo.micro_utils.repos.ReadKeyValueRepo | ||||||
|  | import dev.inmo.micro_utils.repos.unset | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> ReadKeyValueRepo<Id, Registered>.diff(other: Map<Id, Registered>): MapDiff<Id, Registered> { | ||||||
|  |     return getAll().diff(other) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> Map<Id, Registered>.diff(other: ReadKeyValueRepo<Id, Registered>): MapDiff<Id, Registered> { | ||||||
|  |     return diff(other.getAll()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> KeyValueRepo<Id, Registered>.applyDiff(diff: MapDiff<Id, Registered>) { | ||||||
|  |     unset(diff.removed.map { it.key }) | ||||||
|  |     set( | ||||||
|  |         diff.changed.map { (k, oldNew) -> | ||||||
|  |             k to oldNew.second | ||||||
|  |         }.toMap() + diff.added | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> KeyValueRepo<Id, Registered>.applyDiff(other: Map<Id, Registered>) { | ||||||
|  |     applyDiff(diff(other)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> MutableMap<Id, Registered>.applyDiff(other: ReadKeyValueRepo<Id, Registered>) { | ||||||
|  |     applyDiff(diff(other)) | ||||||
|  | } | ||||||
| @@ -0,0 +1,33 @@ | |||||||
|  | package dev.inmo.micro_utils.repos.diff | ||||||
|  |  | ||||||
|  | import dev.inmo.micro_utils.common.MapDiff | ||||||
|  | import dev.inmo.micro_utils.common.applyDiff | ||||||
|  | import dev.inmo.micro_utils.common.diff | ||||||
|  | import dev.inmo.micro_utils.repos.* | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> ReadKeyValuesRepo<Id, Registered>.diff(other: Map<Id, List<Registered>>): MapDiff<Id, List<Registered>> { | ||||||
|  |     return getAll().diff(other) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> Map<Id, List<Registered>>.diff(other: ReadKeyValuesRepo<Id, Registered>): MapDiff<Id, List<Registered>> { | ||||||
|  |     return diff(other.getAll()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> KeyValuesRepo<Id, Registered>.applyDiff(diff: MapDiff<Id, List<Registered>>) { | ||||||
|  |     diff.removed.forEach { | ||||||
|  |         clear(it.key) | ||||||
|  |     } | ||||||
|  |     set( | ||||||
|  |         diff.changed.map { (k, oldNew) -> | ||||||
|  |             k to oldNew.second | ||||||
|  |         }.toMap() + diff.added | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> KeyValuesRepo<Id, Registered>.applyDiff(other: Map<Id, List<Registered>>) { | ||||||
|  |     applyDiff(diff(other)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | suspend fun <Id, Registered> MutableMap<Id, List<Registered>>.applyDiff(other: ReadKeyValuesRepo<Id, Registered>) { | ||||||
|  |     applyDiff(diff(other)) | ||||||
|  | } | ||||||
| @@ -1,6 +1,7 @@ | |||||||
| package dev.inmo.micro_utils.repos.exposed.keyvalue | package dev.inmo.micro_utils.repos.exposed.keyvalue | ||||||
|  |  | ||||||
| import dev.inmo.micro_utils.repos.KeyValueRepo | import dev.inmo.micro_utils.repos.KeyValueRepo | ||||||
|  | import kotlinx.coroutines.channels.BufferOverflow | ||||||
| import kotlinx.coroutines.flow.* | import kotlinx.coroutines.flow.* | ||||||
| import org.jetbrains.exposed.sql.* | import org.jetbrains.exposed.sql.* | ||||||
| import org.jetbrains.exposed.sql.statements.* | import org.jetbrains.exposed.sql.statements.* | ||||||
| @@ -8,13 +9,15 @@ import org.jetbrains.exposed.sql.transactions.transaction | |||||||
|  |  | ||||||
| abstract class AbstractExposedKeyValueRepo<Key, Value>( | abstract class AbstractExposedKeyValueRepo<Key, Value>( | ||||||
|     override val database: Database, |     override val database: Database, | ||||||
|     tableName: String? = null |     tableName: String? = null, | ||||||
|  |     flowsExtraBufferCapacity: Int = Int.MAX_VALUE, | ||||||
|  |     flowsBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND | ||||||
| ) : KeyValueRepo<Key, Value>, AbstractExposedReadKeyValueRepo<Key, Value>( | ) : KeyValueRepo<Key, Value>, AbstractExposedReadKeyValueRepo<Key, Value>( | ||||||
|     database, |     database, | ||||||
|     tableName |     tableName | ||||||
| ) { | ) { | ||||||
|     protected val _onNewValue = MutableSharedFlow<Pair<Key, Value>>() |     protected val _onNewValue = MutableSharedFlow<Pair<Key, Value>>(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|     protected val _onValueRemoved = MutableSharedFlow<Key>() |     protected val _onValueRemoved = MutableSharedFlow<Key>(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|  |  | ||||||
|     override val onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow() |     override val onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow() | ||||||
|     override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow() |     override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow() | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ package dev.inmo.micro_utils.repos.exposed.keyvalue | |||||||
|  |  | ||||||
| import dev.inmo.micro_utils.repos.KeyValueRepo | import dev.inmo.micro_utils.repos.KeyValueRepo | ||||||
| import dev.inmo.micro_utils.repos.exposed.ColumnAllocator | import dev.inmo.micro_utils.repos.exposed.ColumnAllocator | ||||||
|  | import kotlinx.coroutines.channels.BufferOverflow | ||||||
| import kotlinx.coroutines.flow.* | import kotlinx.coroutines.flow.* | ||||||
| import org.jetbrains.exposed.sql.* | import org.jetbrains.exposed.sql.* | ||||||
| import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq | import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq | ||||||
| @@ -13,15 +14,17 @@ open class ExposedKeyValueRepo<Key, Value>( | |||||||
|     database: Database, |     database: Database, | ||||||
|     keyColumnAllocator: ColumnAllocator<Key>, |     keyColumnAllocator: ColumnAllocator<Key>, | ||||||
|     valueColumnAllocator: ColumnAllocator<Value>, |     valueColumnAllocator: ColumnAllocator<Value>, | ||||||
|     tableName: String? = null |     tableName: String? = null, | ||||||
|  |     flowsExtraBufferCapacity: Int = Int.MAX_VALUE, | ||||||
|  |     flowsBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND | ||||||
| ) : KeyValueRepo<Key, Value>, ExposedReadKeyValueRepo<Key, Value>( | ) : KeyValueRepo<Key, Value>, ExposedReadKeyValueRepo<Key, Value>( | ||||||
|     database, |     database, | ||||||
|     keyColumnAllocator, |     keyColumnAllocator, | ||||||
|     valueColumnAllocator, |     valueColumnAllocator, | ||||||
|     tableName |     tableName | ||||||
| ) { | ) { | ||||||
|     protected val _onNewValue = MutableSharedFlow<Pair<Key, Value>>() |     protected val _onNewValue = MutableSharedFlow<Pair<Key, Value>>(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|     protected val _onValueRemoved = MutableSharedFlow<Key>() |     protected val _onValueRemoved = MutableSharedFlow<Key>(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|  |  | ||||||
|     override val onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow() |     override val onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow() | ||||||
|     override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow() |     override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow() | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package dev.inmo.micro_utils.repos.exposed.onetomany | package dev.inmo.micro_utils.repos.exposed.onetomany | ||||||
|  |  | ||||||
| import dev.inmo.micro_utils.repos.KeyValuesRepo | import dev.inmo.micro_utils.repos.KeyValuesRepo | ||||||
|  | import kotlinx.coroutines.channels.BufferOverflow | ||||||
| import kotlinx.coroutines.flow.* | import kotlinx.coroutines.flow.* | ||||||
| import org.jetbrains.exposed.sql.* | import org.jetbrains.exposed.sql.* | ||||||
| import org.jetbrains.exposed.sql.statements.InsertStatement | import org.jetbrains.exposed.sql.statements.InsertStatement | ||||||
| @@ -8,18 +9,20 @@ import org.jetbrains.exposed.sql.transactions.transaction | |||||||
|  |  | ||||||
| abstract class AbstractExposedKeyValuesRepo<Key, Value>( | abstract class AbstractExposedKeyValuesRepo<Key, Value>( | ||||||
|     override val database: Database, |     override val database: Database, | ||||||
|     tableName: String? = null |     tableName: String? = null, | ||||||
|  |     flowsExtraBufferCapacity: Int = Int.MAX_VALUE, | ||||||
|  |     flowsBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND | ||||||
| ) : KeyValuesRepo<Key, Value>, AbstractExposedReadKeyValuesRepo<Key, Value>( | ) : KeyValuesRepo<Key, Value>, AbstractExposedReadKeyValuesRepo<Key, Value>( | ||||||
|     database, |     database, | ||||||
|     tableName |     tableName | ||||||
| ) { | ) { | ||||||
|     protected val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow() |     protected val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|     override val onNewValue: Flow<Pair<Key, Value>> |     override val onNewValue: Flow<Pair<Key, Value>> | ||||||
|         get() = _onNewValue.asSharedFlow() |         get() = _onNewValue.asSharedFlow() | ||||||
|     protected val _onValueRemoved: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow() |     protected val _onValueRemoved: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|     override val onValueRemoved: Flow<Pair<Key, Value>> |     override val onValueRemoved: Flow<Pair<Key, Value>> | ||||||
|         get() = _onValueRemoved.asSharedFlow() |         get() = _onValueRemoved.asSharedFlow() | ||||||
|     protected val _onDataCleared: MutableSharedFlow<Key> = MutableSharedFlow() |     protected val _onDataCleared: MutableSharedFlow<Key> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|     override val onDataCleared: Flow<Key> |     override val onDataCleared: Flow<Key> | ||||||
|         get() = _onDataCleared.asSharedFlow() |         get() = _onDataCleared.asSharedFlow() | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ package dev.inmo.micro_utils.repos.exposed.onetomany | |||||||
|  |  | ||||||
| import dev.inmo.micro_utils.repos.KeyValuesRepo | import dev.inmo.micro_utils.repos.KeyValuesRepo | ||||||
| import dev.inmo.micro_utils.repos.exposed.ColumnAllocator | import dev.inmo.micro_utils.repos.exposed.ColumnAllocator | ||||||
|  | import kotlinx.coroutines.channels.BufferOverflow | ||||||
| import kotlinx.coroutines.flow.* | import kotlinx.coroutines.flow.* | ||||||
| import org.jetbrains.exposed.sql.* | import org.jetbrains.exposed.sql.* | ||||||
| import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq | import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq | ||||||
| @@ -13,20 +14,22 @@ open class ExposedKeyValuesRepo<Key, Value>( | |||||||
|     database: Database, |     database: Database, | ||||||
|     keyColumnAllocator: ColumnAllocator<Key>, |     keyColumnAllocator: ColumnAllocator<Key>, | ||||||
|     valueColumnAllocator: ColumnAllocator<Value>, |     valueColumnAllocator: ColumnAllocator<Value>, | ||||||
|     tableName: String? = null |     tableName: String? = null, | ||||||
|  |     flowsExtraBufferCapacity: Int = Int.MAX_VALUE, | ||||||
|  |     flowsBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND | ||||||
| ) : KeyValuesRepo<Key, Value>, ExposedReadKeyValuesRepo<Key, Value>( | ) : KeyValuesRepo<Key, Value>, ExposedReadKeyValuesRepo<Key, Value>( | ||||||
|     database, |     database, | ||||||
|     keyColumnAllocator, |     keyColumnAllocator, | ||||||
|     valueColumnAllocator, |     valueColumnAllocator, | ||||||
|     tableName |     tableName | ||||||
| ) { | ) { | ||||||
|     protected val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow() |     protected val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|     override val onNewValue: Flow<Pair<Key, Value>> |     override val onNewValue: Flow<Pair<Key, Value>> | ||||||
|         get() = _onNewValue |         get() = _onNewValue | ||||||
|     protected val _onValueRemoved: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow() |     protected val _onValueRemoved: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|     override val onValueRemoved: Flow<Pair<Key, Value>> |     override val onValueRemoved: Flow<Pair<Key, Value>> | ||||||
|         get() = _onValueRemoved |         get() = _onValueRemoved | ||||||
|     protected val _onDataCleared: MutableSharedFlow<Key> = MutableSharedFlow() |     protected val _onDataCleared: MutableSharedFlow<Key> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||||
|     override val onDataCleared: Flow<Key> |     override val onDataCleared: Flow<Key> | ||||||
|         get() = _onDataCleared |         get() = _onDataCleared | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,8 +1,6 @@ | |||||||
| package dev.inmo.micro_utils.repos.generator | package dev.inmo.micro_utils.repos.generator | ||||||
|  |  | ||||||
| import com.google.devtools.ksp.KspExperimental | import com.google.devtools.ksp.* | ||||||
| import com.google.devtools.ksp.getAnnotationsByType |  | ||||||
| import com.google.devtools.ksp.isAnnotationPresent |  | ||||||
| import com.google.devtools.ksp.processing.CodeGenerator | import com.google.devtools.ksp.processing.CodeGenerator | ||||||
| import com.google.devtools.ksp.processing.Resolver | import com.google.devtools.ksp.processing.Resolver | ||||||
| import com.google.devtools.ksp.processing.SymbolProcessor | import com.google.devtools.ksp.processing.SymbolProcessor | ||||||
| @@ -36,6 +34,7 @@ import kotlinx.serialization.Serializable | |||||||
| import java.io.File | import java.io.File | ||||||
| import kotlin.reflect.KProperty1 | import kotlin.reflect.KProperty1 | ||||||
| import kotlin.reflect.full.memberProperties | import kotlin.reflect.full.memberProperties | ||||||
|  | import kotlin.reflect.jvm.jvmName | ||||||
|  |  | ||||||
| private fun KSClassifierReference.quilifiedName(): String = "${qualifier ?.let { "${it.quilifiedName()}." } ?: ""}${referencedName()}" | private fun KSClassifierReference.quilifiedName(): String = "${qualifier ?.let { "${it.quilifiedName()}." } ?: ""}${referencedName()}" | ||||||
|  |  | ||||||
| @@ -75,16 +74,29 @@ class Processor( | |||||||
|                         ORIGINAL FILE: ${ksFile.fileName} |                         ORIGINAL FILE: ${ksFile.fileName} | ||||||
|                     """.trimIndent() |                     """.trimIndent() | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|                     val newName = "New${ksClassDeclaration.simpleName.getShortName()}" |                     val newName = "New${ksClassDeclaration.simpleName.getShortName()}" | ||||||
|                     val registeredName = "Registered${ksClassDeclaration.simpleName.getShortName()}" |                     val registeredName = "Registered${ksClassDeclaration.simpleName.getShortName()}" | ||||||
|  |  | ||||||
|                     val allKSClassProperties = ksClassDeclaration.getAllProperties() |                     val allKSClassProperties = ksClassDeclaration.getAllProperties() | ||||||
|                     val excludedKSClassProperties = allKSClassProperties.filter { |                     val excludedKSClassProperties = allKSClassProperties.filter { property -> | ||||||
|                         it.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) |                         property.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) || (property.findOverridee() ?.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) == true) | ||||||
|                     } |                     } | ||||||
|                     val excludedKSClassPropertiesNames = excludedKSClassProperties.map { it.simpleName.asString() } |                     val excludedKSClassPropertiesNames = excludedKSClassProperties.map { it.simpleName.asString() } | ||||||
|                     val ksClassProperties = allKSClassProperties.filter { |                     val ksClassProperties = allKSClassProperties.filter { | ||||||
|                         it !in excludedKSClassProperties |                         it !in excludedKSClassProperties | ||||||
|  |                     }.groupBy { it.simpleName.asString() }.map { | ||||||
|  |                         var current = it.value.first() | ||||||
|  |                         var currentType = current.type.resolve() | ||||||
|  |                         it.value.forEach { | ||||||
|  |                             val type = it.type.resolve() | ||||||
|  |  | ||||||
|  |                             if (currentType.isAssignableFrom(type) && !type.isAssignableFrom(currentType)) { | ||||||
|  |                                 current = it | ||||||
|  |                                 currentType = type | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         current | ||||||
|                     } |                     } | ||||||
|                     val ksClassPropertiesNames = ksClassProperties.map { it.simpleName.asString() } |                     val ksClassPropertiesNames = ksClassProperties.map { it.simpleName.asString() } | ||||||
|                     val newNewType = TypeSpec.classBuilder(newName).apply { |                     val newNewType = TypeSpec.classBuilder(newName).apply { | ||||||
| @@ -99,17 +111,20 @@ class Processor( | |||||||
|                         } |                         } | ||||||
|                         primaryConstructor( |                         primaryConstructor( | ||||||
|                             FunSpec.constructorBuilder().apply { |                             FunSpec.constructorBuilder().apply { | ||||||
|  |                                 val withoutDefaults = mutableListOf<Pair<ParameterSpec.Builder, PropertySpec.Builder>>() | ||||||
|                                 ksClassProperties.forEach { |                                 ksClassProperties.forEach { | ||||||
|                                     addParameter( |                                     val property = PropertySpec.builder(it.simpleName.getShortName(), it.type.toTypeName(), KModifier.OVERRIDE).apply { | ||||||
|                                         ParameterSpec.builder(it.simpleName.getShortName(), it.typeName).apply { |  | ||||||
|                                             annotations += it.annotations.map { it.toAnnotationSpec() } |  | ||||||
|                                         }.build() |  | ||||||
|                                     ) |  | ||||||
|                                     typeBuilder.addProperty( |  | ||||||
|                                         PropertySpec.builder(it.simpleName.getShortName(), it.typeName, KModifier.OVERRIDE).apply { |  | ||||||
|                                         initializer(it.simpleName.getShortName()) |                                         initializer(it.simpleName.getShortName()) | ||||||
|                                         }.build() |                                     } | ||||||
|                                     ) |                                     ParameterSpec.builder(it.simpleName.getShortName(), it.type.toTypeName()).apply { | ||||||
|  |                                         withoutDefaults.add(this to property) | ||||||
|  |                                         annotations += it.annotations.map { it.toAnnotationSpec() } | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |  | ||||||
|  |                                 withoutDefaults.forEach { | ||||||
|  |                                     addParameter(it.first.build()) | ||||||
|  |                                     addProperty(it.second.build()) | ||||||
|                                 } |                                 } | ||||||
|                             }.build() |                             }.build() | ||||||
|                         ) |                         ) | ||||||
| @@ -125,14 +140,25 @@ class Processor( | |||||||
|                         (it.arguments.first().value as List<KSType>).map { it.declaration as KSClassDeclaration } |                         (it.arguments.first().value as List<KSType>).map { it.declaration as KSClassDeclaration } | ||||||
|                     }.toList() |                     }.toList() | ||||||
|  |  | ||||||
|  |  | ||||||
|                     val registeredTypesProperties: List<KSPropertyDeclaration> = registeredSupertypes.flatMap { registeredType -> |                     val registeredTypesProperties: List<KSPropertyDeclaration> = registeredSupertypes.flatMap { registeredType -> | ||||||
|                         registeredType.getAllProperties() |                         registeredType.getAllProperties() | ||||||
|                     }.filter { |                     }.filter { | ||||||
|                         it.simpleName.asString() !in excludedKSClassPropertiesNames && it.getAnnotationsByType(GenerateCRUDModelExcludeOverride::class).none() |                         it.simpleName.asString() !in excludedKSClassPropertiesNames && !it.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) | ||||||
|                     } |                     } | ||||||
|                     val allProperties: List<KSPropertyDeclaration> = ksClassProperties.toList() + registeredTypesProperties |                     val allProperties: List<KSPropertyDeclaration> = registeredTypesProperties + ksClassProperties.toList() | ||||||
|                     val propertiesToOverrideInRegistered = allProperties.distinctBy { it.simpleName.asString() }.sortedBy { property -> |                     val propertiesToOverrideInRegistered = allProperties.groupBy { it.simpleName.asString() }.map { | ||||||
|  |                         var current = it.value.first() | ||||||
|  |                         var currentType = current.type.resolve() | ||||||
|  |                         it.value.forEach { | ||||||
|  |                             val type = it.type.resolve() | ||||||
|  |  | ||||||
|  |                             if (currentType.isAssignableFrom(type) && !type.isAssignableFrom(currentType)) { | ||||||
|  |                                 current = it | ||||||
|  |                                 currentType = type | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         current | ||||||
|  |                     }.sortedBy { property -> | ||||||
|                         val name = property.simpleName.asString() |                         val name = property.simpleName.asString() | ||||||
|  |  | ||||||
|                         ksClassPropertiesNames.indexOf(name).takeIf { it > -1 } ?.let { |                         ksClassPropertiesNames.indexOf(name).takeIf { it > -1 } ?.let { | ||||||
| @@ -156,17 +182,20 @@ class Processor( | |||||||
|                         addModifiers(KModifier.DATA) |                         addModifiers(KModifier.DATA) | ||||||
|                         primaryConstructor( |                         primaryConstructor( | ||||||
|                             FunSpec.constructorBuilder().apply { |                             FunSpec.constructorBuilder().apply { | ||||||
|  |                                 val withoutDefaults = mutableListOf<Pair<ParameterSpec.Builder, PropertySpec.Builder>>() | ||||||
|                                 propertiesToOverrideInRegistered.forEach { |                                 propertiesToOverrideInRegistered.forEach { | ||||||
|                                     addParameter( |                                     val property = PropertySpec.builder(it.simpleName.getShortName(), it.type.toTypeName(), KModifier.OVERRIDE).apply { | ||||||
|                                         ParameterSpec.builder(it.simpleName.getShortName(), it.typeName).apply { |  | ||||||
|                                             annotations += it.annotations.map { it.toAnnotationSpec() } |  | ||||||
|                                         }.build() |  | ||||||
|                                     ) |  | ||||||
|                                     typeBuilder.addProperty( |  | ||||||
|                                         PropertySpec.builder(it.simpleName.getShortName(), it.typeName, KModifier.OVERRIDE).apply { |  | ||||||
|                                         initializer(it.simpleName.getShortName()) |                                         initializer(it.simpleName.getShortName()) | ||||||
|                                         }.build() |                                     } | ||||||
|                                     ) |                                     ParameterSpec.builder(it.simpleName.getShortName(), it.type.toTypeName()).apply { | ||||||
|  |                                         withoutDefaults.add(this to property) | ||||||
|  |                                         annotations += it.annotations.map { it.toAnnotationSpec() } | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |  | ||||||
|  |                                 withoutDefaults.forEach { | ||||||
|  |                                     addParameter(it.first.build()) | ||||||
|  |                                     addProperty(it.second.build()) | ||||||
|                                 } |                                 } | ||||||
|                             }.build() |                             }.build() | ||||||
|                         ) |                         ) | ||||||
| @@ -191,7 +220,7 @@ class Processor( | |||||||
|                         FunSpec.builder("asRegistered").apply { |                         FunSpec.builder("asRegistered").apply { | ||||||
|                             receiver(ksClassDeclaration.toClassName()) |                             receiver(ksClassDeclaration.toClassName()) | ||||||
|                             (registeredTypesProperties.filter { it.simpleName.asString() !in ksClassPropertiesNames }).forEach { |                             (registeredTypesProperties.filter { it.simpleName.asString() !in ksClassPropertiesNames }).forEach { | ||||||
|                                 addParameter(it.simpleName.asString(), it.typeName) |                                 addParameter(it.simpleName.asString(), it.type.toTypeName()) | ||||||
|                             } |                             } | ||||||
|                             addCode( |                             addCode( | ||||||
|                                 CodeBlock.of( |                                 CodeBlock.of( | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ public data class NewTest( | |||||||
|   override val property1: String, |   override val property1: String, | ||||||
|   override val property2: Int, |   override val property2: Int, | ||||||
|   @Serializable |   @Serializable | ||||||
|  |   @SerialName(`value` = "custom_parent_name") | ||||||
|   override val parent: ParentTypeId?, |   override val parent: ParentTypeId?, | ||||||
| ) : Test | ) : Test | ||||||
|  |  | ||||||
| @@ -24,6 +25,7 @@ public data class RegisteredTest( | |||||||
|   override val property1: String, |   override val property1: String, | ||||||
|   override val property2: Int, |   override val property2: Int, | ||||||
|   @Serializable |   @Serializable | ||||||
|  |   @SerialName(`value` = "custom_parent_name") | ||||||
|   override val parent: ParentTypeId?, |   override val parent: ParentTypeId?, | ||||||
| ) : Test, IRegisteredTest | ) : Test, IRegisteredTest | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ package dev.inmo.micro_utils.repos.generator.test | |||||||
|  |  | ||||||
| import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModel | import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModel | ||||||
| import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModelExcludeOverride | import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModelExcludeOverride | ||||||
|  | import kotlinx.serialization.SerialName | ||||||
| import kotlinx.serialization.Serializable | import kotlinx.serialization.Serializable | ||||||
| import kotlin.jvm.JvmInline | import kotlin.jvm.JvmInline | ||||||
|  |  | ||||||
| @@ -18,6 +19,7 @@ sealed interface Test { | |||||||
|     val property1: String |     val property1: String | ||||||
|     val property2: Int |     val property2: Int | ||||||
|     @Serializable |     @Serializable | ||||||
|  |     @SerialName("custom_parent_name") | ||||||
|     val parent: ParentTypeId? |     val parent: ParentTypeId? | ||||||
|  |  | ||||||
|     @GenerateCRUDModelExcludeOverride |     @GenerateCRUDModelExcludeOverride | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user