Skip to content

Commit 41c7ffa

Browse files
committed
Fixes #45 Add mechanism to dump jira fields
1 parent 4932c7a commit 41c7ffa

File tree

17 files changed

+359
-77
lines changed

17 files changed

+359
-77
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.tix.builder
2+
3+
import org.tix.feature.info.fields.FieldInfoFetcher
4+
5+
fun fieldInfoForCLI() = FieldInfoFetcher(configUseCaseForCLI())

src/commonMain/kotlin/org/tix/builder/TixForCLI.kt

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package org.tix.builder
22

33
import org.tix.config.ConfigurationPaths
4-
import org.tix.config.domain.AuthConfigurationUseCase
5-
import org.tix.config.domain.ConfigurationBakerUseCase
6-
import org.tix.config.domain.ConfigurationMergeUseCase
7-
import org.tix.config.domain.ConfigurationReadUseCase
4+
import org.tix.config.domain.*
85
import org.tix.config.reader.ConfigurationFileReader
96
import org.tix.config.reader.RawTixConfigurationReader
107
import org.tix.config.reader.auth.AuthConfigurationPaths
@@ -29,17 +26,21 @@ fun tixPlanForCLI() = planWithFileSystem(CLIPlanViewStateReducer())
2926

3027
private fun <VS : PlanViewState> planWithFileSystem(viewStateReducer: PlanViewStateReducer<VS>) =
3128
TixPlan(
32-
authConfigUseCase = AuthConfigurationUseCase(authReader()),
33-
configBakerUseCase = ConfigurationBakerUseCase(),
34-
configReadUseCase = configReadSource(),
35-
configMergeUseCase = ConfigurationMergeUseCase(),
29+
configUseCase = configUseCaseForCLI(),
3630
markdownFileUseCase = TextFileUseCase(TextFileIO()),
3731
parserUseCase = TicketParserUseCase(TicketParser()),
3832
ticketPlannerUseCase = TicketPlannerUseCase(ticketPlannerFactory(cliEnv())),
3933
viewStateReducer = viewStateReducer
4034

4135
)
4236

37+
internal fun configUseCaseForCLI() = configurationUseCase(
38+
AuthConfigurationUseCase(authReader()),
39+
ConfigurationBakerUseCase(),
40+
configReadSource(),
41+
ConfigurationMergeUseCase(),
42+
)
43+
4344
private fun authReader() = AuthReader(
4445
fileReader = FileAuthSourceReader(AuthConfigurationPaths(), configFileReader()),
4546
envReader = EnvAuthSourceReader(authEnv())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.tix.config.domain
2+
3+
import kotlinx.coroutines.flow.Flow
4+
import kotlinx.coroutines.flow.flatMapLatest
5+
import kotlinx.coroutines.flow.flowOf
6+
import kotlinx.coroutines.flow.map
7+
import org.tix.config.data.TixConfiguration
8+
import org.tix.config.data.raw.RawTixConfiguration
9+
import org.tix.domain.FlowResult
10+
import org.tix.domain.FlowTransformer
11+
import org.tix.domain.transform
12+
13+
class ConfigurationUseCase(
14+
private val authConfigUseCase: FlowTransformer<AuthConfigAction, TicketSystemAuth>,
15+
private val configBakerUseCase: FlowTransformer<ConfigBakerAction, FlowResult<TixConfiguration>>,
16+
private val configReadUseCase: FlowTransformer<ConfigurationSourceOptions, List<RawTixConfiguration>>,
17+
private val configMergeUseCase: FlowTransformer<List<RawTixConfiguration>, FlowResult<RawTixConfiguration>>,
18+
) : FlowTransformer<ConfigurationSourceOptions, FlowResult<TixConfiguration>> {
19+
override fun transformFlow(upstream: Flow<ConfigurationSourceOptions>) =
20+
upstream.flatMapLatest { config(it) }
21+
22+
private fun config(configSourceOptions: ConfigurationSourceOptions) =
23+
flowOf(configSourceOptions)
24+
.transform(configReadUseCase)
25+
.transform(configMergeUseCase)
26+
.flatMapLatest { mergeResult ->
27+
bakeConfig(mergeResult, configSourceOptions.workspaceDirectory)
28+
}
29+
30+
private fun bakeConfig(mergeResult: FlowResult<RawTixConfiguration>, path: String?) =
31+
if (mergeResult.isSuccess) {
32+
val rawConfig = mergeResult.getOrThrow()
33+
flowOf(AuthConfigAction(path, rawConfig))
34+
.transform(authConfigUseCase)
35+
.map { ConfigBakerAction(rawConfig, it) }
36+
.transform(configBakerUseCase)
37+
} else {
38+
flowOf(FlowResult.failure(mergeResult.throwable))
39+
}
40+
}
41+
42+
fun configurationUseCase(
43+
authConfigUseCase: FlowTransformer<AuthConfigAction, TicketSystemAuth>,
44+
configBakerUseCase: FlowTransformer<ConfigBakerAction, FlowResult<TixConfiguration>>,
45+
configReadUseCase: FlowTransformer<ConfigurationSourceOptions, List<RawTixConfiguration>>,
46+
configMergeUseCase: FlowTransformer<List<RawTixConfiguration>, FlowResult<RawTixConfiguration>>
47+
) = ConfigurationUseCase(authConfigUseCase, configBakerUseCase, configReadUseCase, configMergeUseCase)

src/commonMain/kotlin/org/tix/domain/FlowResult.kt

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ sealed class FlowResult<T>(open val value: T?, open val throwable: Throwable?) {
2222
val isFailure get() = this is Failure
2323

2424
val isSuccess get() = this is Success
25+
26+
inline fun <R> map(transform: (value: T) -> R): FlowResult<R> =
27+
when(this) {
28+
is Failure -> failure(throwable)
29+
is Success -> try {
30+
success(transform(getOrThrow()))
31+
} catch (ex: Throwable) {
32+
failure(ex)
33+
}
34+
}
2535
}
2636

2737
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.tix.feature.info.fields
2+
3+
import kotlinx.coroutines.flow.first
4+
import kotlinx.coroutines.flow.flowOf
5+
import kotlinx.coroutines.flow.map
6+
import org.tix.config.data.JiraConfiguration
7+
import org.tix.config.data.TixConfiguration
8+
import org.tix.config.domain.ConfigurationSourceOptions
9+
import org.tix.domain.FlowResult
10+
import org.tix.domain.FlowTransformer
11+
import org.tix.domain.transform
12+
import org.tix.integrations.jira.JiraApiFactory
13+
14+
class FieldInfoFetcher(
15+
private val configUseCase: FlowTransformer<ConfigurationSourceOptions, FlowResult<TixConfiguration>>,
16+
private val jiraApiFactory: JiraApiFactory = JiraApiFactory()
17+
) {
18+
suspend fun fetchFields(configOptions: ConfigurationSourceOptions) =
19+
flowOf(configOptions)
20+
.transform(configUseCase)
21+
.map { configToFields(it) }
22+
.first()
23+
24+
private suspend fun configToFields(configResult: FlowResult<TixConfiguration>) =
25+
configResult.map { tixConfig ->
26+
tixConfig.jira?.let { fields(it) } ?: emptyList()
27+
}
28+
29+
private suspend fun fields(jiraConfig: JiraConfiguration) =
30+
jiraApiFactory.api(jiraConfig)
31+
.field
32+
.fields()
33+
}

src/commonMain/kotlin/org/tix/feature/plan/TixPlan.kt

+3-13
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@ package org.tix.feature.plan
22

33
import kotlinx.coroutines.CoroutineScope
44
import org.tix.config.data.TixConfiguration
5-
import org.tix.config.data.raw.RawTixConfiguration
6-
import org.tix.config.domain.AuthConfigAction
7-
import org.tix.config.domain.ConfigBakerAction
85
import org.tix.config.domain.ConfigurationSourceOptions
9-
import org.tix.config.domain.TicketSystemAuth
106
import org.tix.domain.FlowResult
117
import org.tix.domain.FlowTransformer
128
import org.tix.feature.plan.domain.combiner.MarkdownPlanDomainCombiner
@@ -20,22 +16,16 @@ import org.tix.feature.plan.presentation.reducer.PlanViewStateReducer
2016
import org.tix.feature.plan.presentation.state.PlanViewState
2117
import org.tix.ticket.Ticket
2218

23-
class TixPlan<VS: PlanViewState> internal constructor(
24-
authConfigUseCase: FlowTransformer<AuthConfigAction, TicketSystemAuth>,
25-
configBakerUseCase: FlowTransformer<ConfigBakerAction, FlowResult<TixConfiguration>>,
26-
configReadUseCase: FlowTransformer<ConfigurationSourceOptions, List<RawTixConfiguration>>,
27-
configMergeUseCase: FlowTransformer<List<RawTixConfiguration>, FlowResult<RawTixConfiguration>>,
19+
class TixPlan<VS : PlanViewState> internal constructor(
20+
configUseCase: FlowTransformer<ConfigurationSourceOptions, FlowResult<TixConfiguration>>,
2821
markdownFileUseCase: FlowTransformer<String, FlowResult<String>>,
2922
parserUseCase: FlowTransformer<TicketParserArguments, FlowResult<List<Ticket>>>,
3023
ticketPlannerUseCase: FlowTransformer<TicketPlannerAction, TicketPlanStatus>,
3124
private val viewStateReducer: PlanViewStateReducer<VS>,
3225
) {
3326
private val markdownPlanCombiner = MarkdownPlanDomainCombiner(
3427
planSourceCombiner = planSourceCombiner(
35-
authConfigUseCase,
36-
configBakerUseCase,
37-
configReadUseCase,
38-
configMergeUseCase,
28+
configUseCase = configUseCase,
3929
markdownFileUseCase,
4030
MarkdownSourceValidator()
4131
),

src/commonMain/kotlin/org/tix/feature/plan/domain/ticket/github/GithubPlannerFactory.kt

+7-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ import org.tix.feature.plan.domain.stats.githubTicketStats
77
import org.tix.feature.plan.domain.ticket.TicketPlanner
88
import org.tix.feature.plan.domain.ticket.TicketPlannerFactory
99
import org.tix.feature.plan.domain.ticket.dry.DryRunPlanningSystem
10-
import org.tix.integrations.github.GithubApi
10+
import org.tix.integrations.github.GithubApiFactory
1111
import org.tix.platform.Env
1212

13-
class GithubPlannerFactory(private val env: Env) : TicketPlannerFactory {
13+
class GithubPlannerFactory(
14+
private val env: Env,
15+
private val apiFactory: GithubApiFactory = GithubApiFactory()
16+
) :
17+
TicketPlannerFactory {
1418
override fun planners(
1519
shouldDryRun: Boolean,
1620
tixConfig: TixConfiguration
@@ -40,6 +44,6 @@ class GithubPlannerFactory(private val env: Env) : TicketPlannerFactory {
4044
if (shouldDryRun) {
4145
DryRunPlanningSystem(githubTicketStats(this.startingLevel))
4246
} else {
43-
GithubPlanningSystem(GithubApi(this), githubTicketStats(this.startingLevel))
47+
GithubPlanningSystem(apiFactory.api(this), githubTicketStats(this.startingLevel))
4448
}
4549
}

src/commonMain/kotlin/org/tix/feature/plan/domain/ticket/jira/JiraPlannerFactory.kt

+6-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import org.tix.feature.plan.domain.stats.jiraTicketStats
77
import org.tix.feature.plan.domain.ticket.TicketPlanner
88
import org.tix.feature.plan.domain.ticket.TicketPlannerFactory
99
import org.tix.feature.plan.domain.ticket.dry.DryRunPlanningSystem
10-
import org.tix.integrations.jira.JiraApi
10+
import org.tix.integrations.jira.JiraApiFactory
1111
import org.tix.platform.Env
1212

13-
class JiraPlannerFactory(private val env: Env) : TicketPlannerFactory {
13+
class JiraPlannerFactory(
14+
private val env: Env,
15+
private val apiFactory: JiraApiFactory = JiraApiFactory()
16+
) : TicketPlannerFactory {
1417
override fun planners(
1518
shouldDryRun: Boolean,
1619
tixConfig: TixConfiguration
@@ -40,6 +43,6 @@ class JiraPlannerFactory(private val env: Env) : TicketPlannerFactory {
4043
if (shouldDryRun) {
4144
DryRunPlanningSystem(jiraTicketStats(this.startingLevel))
4245
} else {
43-
JiraPlanningSystem(JiraApi(this))
46+
JiraPlanningSystem(apiFactory.api(this))
4447
}
4548
}

src/commonMain/kotlin/org/tix/feature/plan/presentation/PlanSourceCombiner.kt

+5-40
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@ package org.tix.feature.plan.presentation
22

33
import kotlinx.coroutines.flow.*
44
import org.tix.config.data.TixConfiguration
5-
import org.tix.config.data.raw.RawTixConfiguration
6-
import org.tix.config.domain.AuthConfigAction
7-
import org.tix.config.domain.ConfigBakerAction
85
import org.tix.config.domain.ConfigurationSourceOptions
9-
import org.tix.config.domain.TicketSystemAuth
106
import org.tix.domain.FlowResult
117
import org.tix.domain.FlowTransformer
128
import org.tix.domain.transform
@@ -20,16 +16,14 @@ import org.tix.feature.plan.domain.parse.MarkdownSourceValidator
2016
import org.tix.feature.plan.domain.parse.MarkdownTextSource
2117

2218
class PlanSourceCombiner(
23-
private val authConfigUseCase: FlowTransformer<AuthConfigAction, TicketSystemAuth>,
24-
private val configBakerUseCase: FlowTransformer<ConfigBakerAction, FlowResult<TixConfiguration>>,
25-
private val configReadUseCase: FlowTransformer<ConfigurationSourceOptions, List<RawTixConfiguration>>,
26-
private val configMergeUseCase: FlowTransformer<List<RawTixConfiguration>, FlowResult<RawTixConfiguration>>,
19+
private val configurationUseCase: FlowTransformer<ConfigurationSourceOptions, FlowResult<TixConfiguration>>,
2720
private val markdownFileUseCase: FlowTransformer<String, FlowResult<String>>,
2821
private val markdownValidator: MarkdownSourceValidator
2922
) : FlowTransformer<MarkdownPlanAction, PlanSourceResult> {
3023
override fun transformFlow(upstream: Flow<MarkdownPlanAction>): Flow<PlanSourceResult> =
3124
upstream.flatMapLatest { action ->
32-
config(action.configSourceOptions)
25+
flowOf(action.configSourceOptions)
26+
.transform(configurationUseCase)
3327
.combine(markdown(action.markdownSource)) { configResult, markdownResult ->
3428
toResult(configResult, markdownResult)
3529
}.catch {
@@ -38,25 +32,6 @@ class PlanSourceCombiner(
3832
}
3933
}
4034

41-
private fun config(configSourceOptions: ConfigurationSourceOptions) =
42-
flowOf(configSourceOptions)
43-
.transform(configReadUseCase)
44-
.transform(configMergeUseCase)
45-
.flatMapLatest { mergeResult ->
46-
bakeConfig(mergeResult, configSourceOptions.workspaceDirectory)
47-
}
48-
49-
private fun bakeConfig(mergeResult: FlowResult<RawTixConfiguration>, path: String?) =
50-
if (mergeResult.isSuccess) {
51-
val rawConfig = mergeResult.getOrThrow()
52-
flowOf(AuthConfigAction(path, rawConfig))
53-
.transform(authConfigUseCase)
54-
.map { ConfigBakerAction(rawConfig, it) }
55-
.transform(configBakerUseCase)
56-
} else {
57-
flowOf(FlowResult.failure(mergeResult.throwable))
58-
}
59-
6035
private fun markdown(markdownInput: MarkdownSource): Flow<FlowResult<String>> {
6136
val result = runCatching {
6237
markdownValidator.validate(markdownInput)
@@ -90,17 +65,7 @@ sealed class PlanSourceResult {
9065
}
9166

9267
fun planSourceCombiner(
93-
authConfigUseCase: FlowTransformer<AuthConfigAction, TicketSystemAuth>,
94-
configBakerUseCase: FlowTransformer<ConfigBakerAction, FlowResult<TixConfiguration>>,
95-
configReadUseCase: FlowTransformer<ConfigurationSourceOptions, List<RawTixConfiguration>>,
96-
configMergeUseCase: FlowTransformer<List<RawTixConfiguration>, FlowResult<RawTixConfiguration>>,
68+
configUseCase: FlowTransformer<ConfigurationSourceOptions, FlowResult<TixConfiguration>>,
9769
markdownFileUseCase: FlowTransformer<String, FlowResult<String>>,
9870
markdownValidator: MarkdownSourceValidator
99-
) = PlanSourceCombiner(
100-
authConfigUseCase,
101-
configBakerUseCase,
102-
configReadUseCase,
103-
configMergeUseCase,
104-
markdownFileUseCase,
105-
markdownValidator
106-
)
71+
) = PlanSourceCombiner(configUseCase, markdownFileUseCase, markdownValidator)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.tix.integrations.github
2+
3+
import io.ktor.client.engine.*
4+
import org.tix.config.data.GithubConfiguration
5+
6+
class GithubApiFactory(private val engine: HttpClientEngine? = null) {
7+
fun api(config: GithubConfiguration) = GithubApi(config, engine)
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.tix.integrations.jira
2+
3+
import org.tix.config.data.JiraConfiguration
4+
5+
class JiraApiFactory {
6+
fun api(configuration: JiraConfiguration) = JiraApi(configuration)
7+
}

0 commit comments

Comments
 (0)