CLOVIS
09/03/2025, 7:47 PMuseCommonJs()
. To detect that, I'm using:
val moduleKind = project.objects.property<JsModuleKind>()
project.tasks.withType<org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink> {
moduleKind.set(compilerOptions.moduleKind)
}
but by the time moduleKind
is set, it's not allowed to add a implementation(npm("foo", "1.0.0"))
anymore.
I've also tried having a : RequiresNpmDependencies
task with a dependency set that changes once moduleKind
is known, and that works without the configuration cache, but with it I get a serialization crash within the configuration cache itself.Edoardo Luppi
09/03/2025, 8:05 PMEdoardo Luppi
09/03/2025, 8:06 PMVampire
09/03/2025, 8:13 PMimplementation(moduleKind.map { npm("foo", "1.0.0") })
?CLOVIS
09/04/2025, 7:56 AMCLOVIS
09/04/2025, 7:57 AMimplementation
is resolved before moduleKind.set()
is called…
If I could somehow do implementation(project.tasks.withType<…>().flatMap { it.compilerOptions.moduleKind })
then that may work maybe, but I don't see such a functionEdoardo Luppi
09/04/2025, 8:01 AMArtem Kobzar
09/04/2025, 8:48 AMVampire
09/04/2025, 9:16 AM@Vampire I tried, butMaybe you should find out why. Whenever order matters, usually something somewhere is doing something wrong. In this case probably doing dependency resolution at configuration time.is resolved beforeimplementation
is called…moduleKind.set()
If I could somehow doThat would probably not help either, because you have the same problem. You already evilly break task-configuration avoidance by usingthen that may work maybe, but I don't see such a functionimplementation(project.tasks.withType<…>().flatMap { it.compilerOptions.moduleKind })
tasks.withType(...) { ... }
which is the same as doing tasks.withType(...).all { ... }
, and thus causes each and every task of that type to be configured, whether it will be executed or not and it does this immediately for all tasks that are already registered and for future ones as soon as they are registered.
So if with that above snippet and using the property like I suggested the property is "set too late", then there is not much you can do besides becoming even dirtier like using afterEvaluate { ... }
, which is not good of course.
Maybe you should just not try to do that reaction?
If you want to proved the user convenience, maybe you should instead provide some function in your plugin that the user invokes and that then does both tasks for him, the one you want to react to and the reaction?
Or something like that.CLOVIS
09/04/2025, 9:21 AMkotlin.js().moduleKind
should be a Provider
in the Kotlin extension instead of only being a provider available on a task
• : RequiresNpmDependencies
should be a ListProperty
instead of a Set
CLOVIS
09/04/2025, 9:27 AMmaybe you should instead provide some function in your plugin that the user invokes and that then does both tasks for himMaybe, but I don't think that approach scales. What if there was a third plugin that had to work with both KGP and my plugin? Should it provide its own config, if my plugin is there configure it, and otherwise configure KGP directly? Conceptually, this is the configuration of KGP. My plugin just needs an additional dependency to be able to deal with it, but it doesn't otherwise care. I could also not provide anything automatically at all and document users that they need to add the dependencies x and y for this to work, but IMO the point of Gradle is that you can trust the defaults.
Vampire
09/04/2025, 9:37 AMVampire
09/04/2025, 9:47 AMimplementation(
js()
.compilations
.named("main")
.flatMap { it.compileTaskProvider }
.flatMap { it.compilerOptions.moduleKind }
.filter { it == "MODULE_COMMONJS" }
.map { npm("foo", "1.0.0") }
)
maybe?Vampire
09/04/2025, 9:48 AMVampire
09/04/2025, 9:50 AMuseCommonJs()
call is made, this should hopefully work properly.CLOVIS
09/04/2025, 5:57 PMval kotlinExt = project.kotlinExtension as KotlinMultiplatformExtension
val moduleKind = kotlinExt.js().compilations.named("main")
.flatMap { it.compileTaskProvider }
.flatMap { it.compilerOptions.moduleKind }
val plugins = moduleKind.map {
when (it) {
JsModuleKind.MODULE_COMMONJS, JsModuleKind.MODULE_UMD -> listOf(
ExternalVitePlugin("viteCommonjs", "vite-plugin-commonjs", "0.10.4"),
ExternalVitePlugin("commonjs", "@rollup/plugin-commonjs", "20.0.6"),
)
else -> emptyList()
}
}
project.tasks.withType(WriteConfig::class.java).configureEach {
config.plugins.addAll(plugins)
doFirst {
println("Plugins: ${plugins.get()}")
}
}
(this doesn't have the implementation
part yet) but I get:
A problem was found with the configuration of task ':viteConfigureProd' (type 'WriteConfig').
- Type 'opensavvy.gradle.vite.base.tasks.WriteConfig' property 'plugins' doesn't have a configured value.
so I'm not sure it's going to workVampire
09/05/2025, 6:47 AMconfig.plugins.addAll
, does the doFirst
print the expected plugins?CLOVIS
09/05/2025, 7:43 AM* What went wrong:
Execution failed for task ':app:viteConfigureProd'.
> Cannot query the value of this provider because it has no value available.
Vampire
09/05/2025, 9:01 AMmap
it.
You probably need an orElse(emptyList())
.Vampire
09/05/2025, 9:01 AMaddLater
where an absent provider is just ignored.Vampire
09/05/2025, 9:02 AMplugins
to config.plugins
. I guess that is a ListProperty
which becomes unset if you add an unset provider.CLOVIS
09/05/2025, 9:31 AMconfig.plugins
is a ListProperty
, but that one I own and there is already a .convention(emptyList())