init projects

This commit is contained in:
2026-06-17 18:58:41 +03:00
parent 8543c4e241
commit 21a768edd5
505 changed files with 19998 additions and 93 deletions
+1
View File
@@ -0,0 +1 @@
build
+2
View File
@@ -0,0 +1,2 @@
build
bin
+78
View File
@@ -0,0 +1,78 @@
plugins {
`kotlin-dsl`
}
dependencies {
compileOnly(libs.plugins.android.library.toDep())
compileOnly(libs.plugins.android.application.toDep())
compileOnly(libs.plugins.compose.compiler.toDep())
compileOnly(libs.plugins.jetbrains.compose.toDep())
compileOnly(libs.plugins.serialization.toDep())
compileOnly(libs.plugins.kotlin.multiplatform.toDep())
compileOnly(libs.plugins.devtools.ksp.toDep())
compileOnly(libs.plugins.koin.compiler.toDep())
}
fun Provider<PluginDependency>.toDep() = map {
"${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version}"
}
val prefix = "ru.shadowsparky.plugin."
gradlePlugin {
plugins {
create("conventionKmp") {
id = "convention.kmp"
implementationClass = "${prefix}Kmp"
}
create("conventionKtorClient") {
id = "convention.ktor-client"
implementationClass = "${prefix}KtorClient"
}
create("conventionCompose") {
id = "convention.compose"
implementationClass = "${prefix}Compose"
}
create("conventionSerialization") {
id = "convention.serialization"
implementationClass = "${prefix}Serialization"
}
create("conventionAndroidLib") {
id = "convention.android-lib"
implementationClass = "${prefix}AndroidLibrary"
}
create("conventionSqlDelight") {
id = "convention.sqldelight"
implementationClass = "${prefix}SqlDelight"
}
create("conventionJvm") {
id = "convention.jvm"
implementationClass = "${prefix}Jvm"
}
create("conventionKoin") {
id = "convention.koin"
implementationClass = "${prefix}Koin"
}
create("conventionKrpcClient") {
id = "convention.krpc-client"
implementationClass = "${prefix}KrpcClient"
}
create("conventionKrpcServer") {
id = "convention.krpc-server"
implementationClass = "${prefix}KrpcServer"
}
create("conventionWebApp") {
id = "convention.web-app"
implementationClass = "${prefix}WebApplication"
}
create("conventionBackendApp") {
id = "convention.backend-app"
implementationClass = "${prefix}BackendApplication"
}
create("conventionAndroidApp") {
id = "convention.android-app"
implementationClass = "${prefix}AndroidApplication"
}
}
}
@@ -0,0 +1,39 @@
package ru.shadowsparky
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.LibraryExtension
import org.gradle.api.JavaVersion
import org.gradle.api.Project
fun LibraryExtension.setupAndroid(project: Project) {
val libs = project.findLibs()
compileSdk {
version = release(libs.findVersion("proj.compile").get().toString().toInt())
}
defaultConfig {
minSdk = libs.findVersion("proj.min").get().toString().toInt()
}
compileOptions {
val javaVersion = JavaVersion.toVersion(libs.findVersion("proj.java").get())
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
}
}
fun ApplicationExtension.setupAndroid(project: Project) {
val libs = project.findLibs()
compileSdk {
version = release(libs.findVersion("proj.compile").get().toString().toInt())
}
defaultConfig {
minSdk = libs.findVersion("proj.min").get().toString().toInt()
targetSdk {
version = release(libs.findVersion("proj.target").get().toString().toInt())
}
}
compileOptions {
val javaVersion = JavaVersion.toVersion(libs.findVersion("proj.java").get())
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
}
}
@@ -0,0 +1,5 @@
package ru.shadowsparky
object BuildFlags {
const val DESKTOP = true
}
@@ -0,0 +1,79 @@
package ru.shadowsparky
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.LibraryExtension
import org.gradle.api.Project
import org.gradle.api.artifacts.UnknownConfigurationException
import org.gradle.api.artifacts.VersionCatalog
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.DependencyHandlerScope
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.findByType
internal fun Project.findLibs(): VersionCatalog {
return extensions.findByType(VersionCatalogsExtension::class.java)!!.named("libs")
}
val Project.isAndroidApp: Boolean
get() {
return extensions.findByType<ApplicationExtension>() != null
}
val Project.isAndroidLib: Boolean
get() {
return extensions.findByType<LibraryExtension>() != null
}
val Project.isWebApp: Boolean
get() {
return hasPlugin("convention-web-app")
}
val Project.isBackendApp: Boolean
get() {
return hasPlugin("convention-backend-app")
}
internal fun Project.hasAndroidSupport(): Boolean {
return isAndroidApp || isAndroidLib
}
internal fun Project.hasMultiplatformSupport(): Boolean = hasPlugin("kotlin-multiplatform")
private fun Project.hasPlugin(alias: String): Boolean {
val plugin = findLibs().findPlugin(alias).get().get().pluginId
return pluginManager.hasPlugin(plugin)
}
internal fun DependencyHandlerScope.implementation(deps: Any) {
try {
add("commonMainImplementation", deps)
} catch (_: UnknownConfigurationException) {
add("implementation", deps)
}
}
internal fun DependencyHandlerScope.androidImplementation(deps: Any) {
add("androidMainImplementation", deps)
}
internal fun DependencyHandlerScope.desktopImplementation(deps: Any) {
if (BuildFlags.DESKTOP) add("desktopMainImplementation", deps)
}
internal fun Project.applyCoroutines(
libs: VersionCatalog,
hasAndroid: Boolean = hasAndroidSupport()
) {
dependencies {
implementation(libs.findLibrary("kotlinx-coroutines-core").get())
if (hasAndroid) {
val lib = libs.findLibrary("kotlinx.coroutines.android").get()
if (hasMultiplatformSupport()) {
androidImplementation(lib)
} else {
implementation(lib)
}
}
}
}
@@ -0,0 +1,48 @@
package ru.shadowsparky
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
private const val COMMON_MAIN = "kspCommonMainMetadata"
private const val KSP = "ksp"
private const val KSP_ANDROID = "kspAndroid"
private const val KSP_ANDROID_JVM = "kspAndroidJvm"
private const val KSP_WASM_JS = "kspWasmJs"
private const val KSP_JS = "kspJs"
private const val KSP_DESKTOP = "kspDesktop"
private const val KSP_JVM = "kspJvm"
private fun Project.hasConfig(name: String) = configurations.findByName(name) != null
internal fun Project.kspAllPlatforms(deps: Any) {
dependencies {
// common
if (hasConfig(COMMON_MAIN)) {
add(COMMON_MAIN, deps)
} else {
add(KSP, deps)
return@dependencies
}
// android
when {
hasConfig(KSP_ANDROID) -> add(KSP_ANDROID, deps)
hasConfig(KSP_ANDROID_JVM) -> add(KSP_ANDROID_JVM, deps)
}
// web
when {
hasConfig(KSP_WASM_JS) -> add(KSP_WASM_JS, deps)
hasConfig(KSP_JS) -> add(KSP_JS, deps)
}
// desktop
when {
hasConfig(KSP_DESKTOP) -> add(KSP_DESKTOP, deps)
hasConfig(KSP_JVM) -> add(KSP_JVM, deps)
}
}
}
@@ -0,0 +1,53 @@
package ru.shadowsparky.plugin
import com.android.build.api.dsl.ApplicationExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import ru.shadowsparky.applyCoroutines
import ru.shadowsparky.findLibs
import ru.shadowsparky.setupAndroid
import java.io.File
import java.io.FileInputStream
import java.util.Properties
class AndroidApplication : Plugin<Project> {
override fun apply(target: Project) = with(target) {
val libs = findLibs()
pluginManager.apply(libs.findPlugin("android.application").get().get().pluginId)
extensions.configure<ApplicationExtension> {
val keystorePropertiesFile = File(rootDir, "keystore.properties")
signingConfigs {
if (keystorePropertiesFile.exists()) {
val keystoreProperties = Properties()
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
create("release") {
storeFile = File(rootDir, "release.keystore")
check(storeFile?.exists() == true) { "Unable to load keystore file!" }
storePassword = keystoreProperties["RELEASE_STORE_PASSWORD"].toString()
keyAlias = keystoreProperties["RELEASE_KEY_ALIAS"].toString()
keyPassword = keystoreProperties["RELEASE_KEY_PASSWORD"].toString()
}
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = true
if (keystorePropertiesFile.exists()) {
signingConfig = signingConfigs.getByName("release")
}
proguardFiles(file("proguard-rules.pro"))
}
getByName("debug") {
isMinifyEnabled = false
applicationIdSuffix = ".debug"
if (keystorePropertiesFile.exists()) {
signingConfig = signingConfigs.getByName("release")
}
}
}
setupAndroid(target)
}
applyCoroutines(libs)
}
}
@@ -0,0 +1,42 @@
package ru.shadowsparky.plugin
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import com.android.build.api.dsl.LibraryExtension
import org.gradle.api.Action
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import ru.shadowsparky.applyCoroutines
import ru.shadowsparky.findLibs
import ru.shadowsparky.hasMultiplatformSupport
import ru.shadowsparky.setupAndroid
class AndroidLibrary : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
val libs = findLibs()
val isMultiplatform = hasMultiplatformSupport()
val pluginName = if (isMultiplatform) {
"multiplatform.android.library"
} else {
"android.library"
}
pluginManager.apply(libs.findPlugin(pluginName).get().get().pluginId)
if (isMultiplatform) {
extensions.configure<KotlinMultiplatformExtension> {
android {
compileSdk = libs.findVersion("proj.compile").get().toString().toInt()
minSdk = libs.findVersion("proj.min").get().toString().toInt()
androidResources.enable = true
}
}
} else {
extensions.configure<LibraryExtension> { setupAndroid(target) }
}
applyCoroutines(libs)
}
}
private fun org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension.android(configure: Action<KotlinMultiplatformAndroidLibraryTarget>): Unit =
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("android", configure)
@@ -0,0 +1,12 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import ru.shadowsparky.findLibs
class BackendApplication : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
val libs = findLibs()
plugins.apply(libs.findPlugin("convention-jvm").get().get().pluginId)
}
}
@@ -0,0 +1,28 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import org.jetbrains.compose.ComposePlugin
import ru.shadowsparky.findLibs
import ru.shadowsparky.implementation
class Compose : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
val libs = findLibs()
plugins.apply(libs.findPlugin("jetbrains.compose").get().get().pluginId)
plugins.apply(libs.findPlugin("compose.compiler").get().get().pluginId)
dependencies {
val compose = ComposePlugin.Dependencies(target)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.components.resources)
implementation(libs.findLibrary("compose-material3").get())
implementation(libs.findLibrary("decompose").get())
implementation(libs.findLibrary("decompose-extensions").get())
implementation(libs.findLibrary("decompose-lifecycle-coroutines").get())
implementation(libs.findLibrary("image.loader").get())
}
}
}
@@ -0,0 +1,22 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.kotlin.dsl.withType
import ru.shadowsparky.applyCoroutines
import ru.shadowsparky.findLibs
class Jvm : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
val libs = findLibs()
plugins.apply(libs.findPlugin("java-library").get().get().pluginId)
plugins.apply(libs.findPlugin("jetbrains-kotlin-jvm").get().get().pluginId)
tasks.withType<JavaCompile> {
sourceCompatibility = libs.findVersion("proj-server-java").get().toString()
targetCompatibility = libs.findVersion("proj-server-java").get().toString()
}
applyCoroutines(libs)
}
}
@@ -0,0 +1,32 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import ru.shadowsparky.BuildFlags
import ru.shadowsparky.applyCoroutines
import ru.shadowsparky.findLibs
class Kmp : Plugin<Project> {
override fun apply(target: Project) = with(target) {
val libs = findLibs()
pluginManager.apply(libs.findPlugin("kotlin-multiplatform").get().get().pluginId)
extensions.configure<KotlinMultiplatformExtension> { applyConfig() }
applyCoroutines(libs, false)
kotlinExtension.sourceSets.named("commonMain").configure {
kotlin.srcDirs(
"build/generated/ksp/metadata/commonMain/kotlin"
)
}
}
}
@OptIn(ExperimentalWasmDsl::class)
fun KotlinMultiplatformExtension.applyConfig() {
if (BuildFlags.DESKTOP) jvm("desktop")
wasmJs { browser() }
}
@@ -0,0 +1,44 @@
package ru.shadowsparky.plugin
import org.gradle.api.Action
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionAware
import org.gradle.kotlin.dsl.dependencies
import org.koin.compiler.plugin.KoinGradleExtension
import ru.shadowsparky.androidImplementation
import ru.shadowsparky.findLibs
import ru.shadowsparky.hasAndroidSupport
import ru.shadowsparky.hasMultiplatformSupport
import ru.shadowsparky.implementation
import ru.shadowsparky.isAndroidApp
import ru.shadowsparky.isWebApp
class Koin : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
val libs = findLibs()
plugins.apply(libs.findPlugin("koin-compiler").get().get().pluginId)
koinCompiler {
val checkSafety = isAndroidApp || isWebApp // || isBackendApp
if (checkSafety) {
println("koin check safety enabled for module ${target.name}")
}
compileSafety.set(checkSafety)
}
dependencies {
implementation(libs.findLibrary("koin-core").get())
implementation(libs.findLibrary("koin-annotations").get())
if (hasAndroidSupport()) {
val androidKoin = libs.findLibrary("koin-android").get()
if (hasMultiplatformSupport()) {
androidImplementation(androidKoin)
} else {
implementation(androidKoin)
}
}
}
}
}
private fun Project.koinCompiler(configure: Action<KoinGradleExtension>): Unit =
(this as ExtensionAware).extensions.configure("koinCompiler", configure)
@@ -0,0 +1,20 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import ru.shadowsparky.findLibs
import ru.shadowsparky.implementation
class KrpcClient : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
val libs = findLibs()
plugins.apply(libs.findPlugin("krpc").get().get().pluginId)
dependencies {
implementation(libs.findLibrary("kotlinx-rpc-krpc-ktor-client").get())
implementation(libs.findLibrary("kotlinx-rpc-krpc-serialization-json").get())
implementation(libs.findLibrary("kotlinx-rpc-krpc-client").get())
}
}
}
@@ -0,0 +1,20 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import ru.shadowsparky.findLibs
import ru.shadowsparky.implementation
class KrpcServer : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
val libs = findLibs()
plugins.apply(libs.findPlugin("krpc").get().get().pluginId)
dependencies {
implementation(libs.findLibrary("kotlinx-rpc-krpc-ktor-server").get())
implementation(libs.findLibrary("kotlinx-rpc-krpc-serialization-json").get())
implementation(libs.findLibrary("kotlinx-rpc-krpc-server").get())
}
}
}
@@ -0,0 +1,30 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import ru.shadowsparky.androidImplementation
import ru.shadowsparky.desktopImplementation
import ru.shadowsparky.findLibs
import ru.shadowsparky.implementation
class KtorClient : Plugin<Project> {
override fun apply(target: Project) {
val libs = target.findLibs()
target.dependencies {
implementation(libs.findLibrary("ktor.client.websockets").get())
implementation(libs.findLibrary("ktor-serialization-kotlinx-json").get())
implementation(libs.findLibrary("ktor-client-content-negotiation").get())
implementation(libs.findLibrary("ktor-client-logging").get())
implementation(libs.findLibrary("ktor-client-auth").get())
implementation(libs.findLibrary("ktor-client-core").get())
val okHttp = libs.findLibrary("ktor.client.okhttp").get()
try {
androidImplementation(okHttp)
desktopImplementation(okHttp)
} catch (_: Exception) {
implementation(okHttp)
}
}
}
}
@@ -0,0 +1,18 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import ru.shadowsparky.findLibs
import ru.shadowsparky.implementation
class Serialization : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
val libs = findLibs()
plugins.apply(libs.findPlugin("serialization").get().get().pluginId)
dependencies {
implementation(libs.findLibrary("kotlinx.serialization.json").get())
implementation(libs.findLibrary("kotlinx.serialization.core").get())
}
}
}
@@ -0,0 +1,28 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import ru.shadowsparky.androidImplementation
import ru.shadowsparky.desktopImplementation
import ru.shadowsparky.findLibs
import ru.shadowsparky.hasAndroidSupport
import ru.shadowsparky.implementation
class SqlDelight : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
val libs = findLibs()
plugins.apply(libs.findPlugin("sqldelight").get().get().pluginId)
dependencies {
implementation(libs.findLibrary("coroutines.extensions").get())
implementation(libs.findLibrary("sql.delight.runtime").get())
if (hasAndroidSupport()) {
androidImplementation(libs.findLibrary("androidx.sqlite").get())
androidImplementation(libs.findLibrary("androidx.sqlite.framework").get())
}
desktopImplementation(libs.findLibrary("sqlite.driver").get())
}
}
}
@@ -0,0 +1,9 @@
package ru.shadowsparky.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
class WebApplication : Plugin<Project> {
override fun apply(target: Project) {
}
}
+15
View File
@@ -0,0 +1,15 @@
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
rootProject.name = "build-logic"
include(":convention")