Skip to content

Commit c3b5e08

Browse files
authored
3.2.0 (#166)
2 parents 8cfc97a + ff36e7f commit c3b5e08

22 files changed

Lines changed: 170 additions & 128 deletions

File tree

.claude/agents/feature-planner.md

Lines changed: 0 additions & 91 deletions
This file was deleted.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,4 @@ docs/javadocs/**
178178
/.intellijPlatform/
179179
**/*.jks
180180
/.idea/ChatHistory_schema_v2.xml
181+
**/tmp/**

CLAUDE.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,21 @@ FlowMVI is a Kotlin Multiplatform MVI (Model-View-Intent) framework built on cor
1111
## Main Directories:
1212

1313
- `core/src/commonMain/kotlin/pro/respawn/flowmvi` - core logic, main module
14-
- ./plugins - default plugins and implementation samples.
1514
- ./StoreImpl.kt - core store implementation
16-
- ./modules/ - various store components, like code on how plugins work,
17-
- ./api/ - public API interfaces and contract.
15+
- ./api/ - public API interfaces and contracts (Store, State, Intent, Action, etc.)
16+
- ./dsl/ - DSL builders for stores, plugins, and configurations
17+
- ./modules/ - internal store modules (intent, state, action, recovery, lifecycle)
18+
- ./plugins/ - built-in plugins (logging, undo/redo, caching, job management, etc.)
19+
- ./delegate/ - delegate plugins for composition
20+
- ./decorators/ - public api intent decorators (retry, batch, conflate, timeout)
21+
- ./decorator/ - decorator framework and builders
22+
- ./impl/ - internal implementations
23+
- ./plugin/ - plugin execution machinery
24+
- ./store/ - store internals
25+
- ./util/ - utility classes (locks, dispatchers, collections)
26+
- ./exceptions/ - custom exceptions
27+
- ./annotation/ - API annotations (@ExperimentalFlowMVIAPI, etc.)
28+
- ./logging/ - logging framework and implementations
1829
- `android/` - Android ViewModel integration
1930
- `compose/` - Compose Multiplatform integration with lifecycle-aware subscriptions
2031
- `savedstate/` - Cross-platform state persistence
@@ -43,3 +54,12 @@ FlowMVI is a Kotlin Multiplatform MVI (Model-View-Intent) framework built on cor
4354
- Document public code ONLY via kdocs.
4455
- Do not run `assemble` on the entire project, that task can take hours, use more granular tasks
4556
- Avoid source breaking changes. Deprecate public api instead of removing it.
57+
58+
## Commit Guidelines
59+
60+
Format: `<type>[!]: [description]` where scope is optional, `!` = breaking change
61+
62+
**Types:** `feat` (→🚀 Features), `fix` (→🐞 Fixes), `feat!`/`breaking`/`api` (→🧨 Breaking), `docs` (→📚 Docs),
63+
`perf`, `refactor`, `test`, `chore`, `build`, `ci`, `style`, `revert`
64+
65+
Examples: `feat: add state recovery`, `fix: resolve lifecycle conflict`, `feat!: change Saver API`

build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,11 @@ rootProject.plugins.withType<YarnPlugin>().configureEach {
170170
yarnLockAutoReplace = true
171171
}
172172
}
173+
174+
gradle.taskGraph.whenReady {
175+
val lastTask = allTasks.lastOrNull()
176+
lastTask?.doLast {
177+
if (this.state.failure != null) return@doLast
178+
println("✅ TASK SUCCESSFUL. Some messages suppressed by logging.level=warn")
179+
}
180+
}

buildSrc/src/main/kotlin/Config.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ object Config {
2020
const val majorRelease = 3
2121
const val minorRelease = 2
2222
const val patch = 0
23-
const val postfix = "-alpha06" // include dash (-)
24-
const val versionCode = 11
23+
const val postfix = "" // include dash (-)
24+
const val versionCode = 12
2525

2626
const val majorVersionName = "$majorRelease.$minorRelease.$patch"
2727
const val versionName = "$majorVersionName$postfix"
@@ -53,6 +53,11 @@ object Config {
5353
"-Xconsistent-data-class-copy-visibility",
5454
"-Xwarning-level=NOTHING_TO_INLINE:disabled",
5555
"-Xwarning-level=UNUSED_ANONYMOUS_PARAMETER:disabled",
56+
"-Xcontext-sensitive-resolution",
57+
"-Xcontext-parameters",
58+
// "-Xwhen-guards",
59+
"-Xallow-reified-type-in-catch",
60+
"-Xdata-flow-based-exhaustiveness",
5661
)
5762
val jvmCompilerArgs = buildList {
5863
add("-Xjvm-default=all") // enable all jvm optimizations

core/src/commonMain/kotlin/pro/respawn/flowmvi/logging/LoggingDsl.kt

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public val StoreLogLevel.asSymbol: String
3333
}
3434

3535
/**
36-
* Write a message to [StoreLogger]. Tag is the [Store.name] by default.
36+
* Write a message to [StoreLogger]. Tag is the [pro.respawn.flowmvi.api.Store.name] by default.
3737
*/
3838
public fun PipelineContext<*, *, *>.log(
3939
level: StoreLogLevel = StoreLogLevel.Debug,
@@ -42,7 +42,7 @@ public fun PipelineContext<*, *, *>.log(
4242
): Unit = config.logger(level, tag, message)
4343

4444
/**
45-
* Write a message to [StoreLogger]. Tag is the [Store.name] by default.
45+
* Write a message to [StoreLogger]. Tag is the [pro.respawn.flowmvi.api.Store.name] by default.
4646
*/
4747
public fun PipelineContext<*, *, *>.log(
4848
e: Exception,
@@ -87,3 +87,59 @@ public fun StoreLogger.warn(tag: String? = null, message: () -> String): Unit =
8787
*/
8888
public fun StoreLogger.error(tag: String? = null, message: () -> String): Unit =
8989
log(StoreLogLevel.Error, tag, message)
90+
91+
/**
92+
* Shorthand for [log] with [StoreLogLevel.Trace] as the log level.
93+
*/
94+
public fun PipelineContext<*, *, *>.logt(
95+
tag: String? = config.name,
96+
message: () -> String
97+
): Unit = log(StoreLogLevel.Trace, tag, message)
98+
99+
/**
100+
* Shorthand for [log] with [StoreLogLevel.Debug] as the log level.
101+
*/
102+
public fun PipelineContext<*, *, *>.logd(
103+
tag: String? = config.name,
104+
message: () -> String
105+
): Unit = log(StoreLogLevel.Debug, tag, message)
106+
107+
/**
108+
* Shorthand for [log] with [StoreLogLevel.Info] as the log level.
109+
*/
110+
public fun PipelineContext<*, *, *>.logi(
111+
tag: String? = config.name,
112+
message: () -> String
113+
): Unit = log(StoreLogLevel.Info, tag, message)
114+
115+
/**
116+
* Shorthand for [log] with [StoreLogLevel.Warn] as the log level.
117+
*/
118+
public fun PipelineContext<*, *, *>.logw(
119+
tag: String? = config.name,
120+
message: () -> String
121+
): Unit = log(StoreLogLevel.Warn, tag, message)
122+
123+
/**
124+
* Shorthand for [log] with [StoreLogLevel.Error] as the log level.
125+
*/
126+
public fun PipelineContext<*, *, *>.loge(
127+
tag: String? = config.name,
128+
message: () -> String
129+
): Unit = log(StoreLogLevel.Error, tag, message)
130+
131+
/**
132+
* Shorthand for logging an exception with [StoreLogLevel.Error] as the log level.
133+
*/
134+
public fun PipelineContext<*, *, *>.loge(
135+
e: Exception,
136+
tag: String? = config.name
137+
): Unit = log(e, StoreLogLevel.Error, tag)
138+
139+
/**
140+
* Shorthand for logging an exception with [StoreLogLevel.Warn] as the log level.
141+
*/
142+
public fun PipelineContext<*, *, *>.logw(
143+
e: Exception,
144+
tag: String? = config.name
145+
): Unit = log(e, StoreLogLevel.Warn, tag)

core/src/wasmJsMain/kotlin/pro/respawn/flowmvi/logging/PlatformStoreLogger.FlowMVI.core.wasmJs.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@file:Suppress("UnusedParameter", "UNUSED_PARAMETER")
2+
@file:OptIn(ExperimentalWasmJsInterop::class)
3+
24
package pro.respawn.flowmvi.logging
35

46
private fun log(message: String): Unit = js("""console.log(message)""")

debugger/ideplugin/build.gradle.kts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@file:Suppress("UnstableApiUsage")
22

3-
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
43
import kotlin.text.replace
4+
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
55

66
plugins {
77
kotlin("jvm")
@@ -41,7 +41,9 @@ intellijPlatform {
4141
}
4242
pluginVerification {
4343
ides {
44-
props["plugin.local.ide.path"]?.toString()?.let(::local) ?: create(
44+
// TODO: https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/1965
45+
// props["plugin.local.ide.path"]?.toString()?.let(::local)
46+
create(
4547
IntelliJPlatformType.IntellijIdeaCommunity,
4648
libs.versions.intellij.idea.get()
4749
)
@@ -115,6 +117,7 @@ dependencies {
115117
implementation(applibs.bundles.koin)
116118

117119
intellijPlatform {
120+
@Suppress("DEPRECATION") // crashes without this usage :D
118121
intellijIdeaCommunity(libs.versions.intellij.idea)
119122
pluginVerifier()
120123
zipSigner()

debugger/server/src/commonMain/kotlin/pro/respawn/flowmvi/debugger/server/arch/configuration/DefaultStoreConfiguration.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,24 @@ import pro.respawn.flowmvi.api.MVIAction
99
import pro.respawn.flowmvi.api.MVIIntent
1010
import pro.respawn.flowmvi.api.MVIState
1111
import pro.respawn.flowmvi.debugger.server.BuildFlags
12+
import pro.respawn.flowmvi.debugger.server.platform.FileManager
1213
import pro.respawn.flowmvi.dsl.StoreBuilder
1314
import pro.respawn.flowmvi.plugins.enableLogging
1415
import pro.respawn.flowmvi.savedstate.api.Saver
1516
import pro.respawn.flowmvi.savedstate.dsl.CompressedFileSaver
1617
import pro.respawn.flowmvi.savedstate.dsl.JsonSaver
1718
import pro.respawn.flowmvi.savedstate.plugins.saveStatePlugin
18-
import java.io.File
1919

2020
internal class DefaultStoreConfiguration(
2121
private val json: Json,
22+
private val fileManager: FileManager,
2223
) : StoreConfiguration {
2324

2425
override fun <S : MVIState> saver(
2526
serializer: KSerializer<S>,
2627
fileName: String,
2728
) = CompressedFileSaver(
28-
// TODO: Abstract away
29-
path = { File(".cache").apply { mkdirs() }.resolve("$fileName.json.gz").absolutePath }
29+
path = { fileManager.cacheFile("states", "$fileName.json.gz") }
3030
).let { JsonSaver(json, serializer, it) }
3131

3232
override operator fun <S : MVIState, I : MVIIntent, A : MVIAction> StoreBuilder<S, I, A>.invoke(

debugger/server/src/commonMain/kotlin/pro/respawn/flowmvi/debugger/server/di/AppModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import pro.respawn.flowmvi.debugger.server.ui.screens.timeline.TimelineContainer
1111

1212
val appModule = module {
1313
single { DefaultJson }
14-
single<StoreConfiguration> { DefaultStoreConfiguration(get()) }
14+
single<StoreConfiguration> { DefaultStoreConfiguration(get(), get()) }
1515
container { new(::ConnectContainer) }
1616
container { new(::TimelineContainer) }
1717
container { new(::StoreDetailsContainer) }

0 commit comments

Comments
 (0)