diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bda2ccc..fa22a05 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -90,4 +90,7 @@ jobs: uses: gradle/actions/setup-gradle@v5 - name: Build library - run: ./gradlew assemble --no-configuration-cache + run: ./gradlew :deci:assemble --no-configuration-cache + + - name: Compile sample (smoke check) + run: ./gradlew :sample:composeApp:compileKotlinJvm --no-configuration-cache diff --git a/CHANGELOG.md b/CHANGELOG.md index 36e5a77..61d27c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,39 @@ # Changelog +## [Unreleased] + +### Removed + +- **Intel Apple targets dropped** — `iosX64` and `macosX64` klibs are no longer + published. Consumers targeting Intel macOS or the Intel iOS simulator must stay + on `0.2.2` or earlier. The Apple Silicon targets (`iosArm64`, + `iosSimulatorArm64`, `macosArm64`) are unaffected. + +### Changed + +- **Android `compileSdk` raised to 37** — projects depending on `deci` must now + compile against Android API level 37 or later. + +- **Build scripts modernized — no public API or runtime changes.** Migrated + deprecated Gradle/AGP/Kotlin/Compose DSL across all modules: the AGP KMP + `androidLibrary { }` block → `android { }`, `js(IR)` → `js`, the deprecated + `compose.*` dependency shortcuts → version-catalog coordinates, and the webpack + `devServer.static` property → the `static()` function. Removed unused build + dependencies and version-catalog entries (coroutines core/android/swing, plus + the `android-library`, `ktlint`, and `binary-compatibility-validator` plugin + aliases), and enabled Android host tests so the common test suite also runs on + the Android variant. + +## [0.2.2] - 2026-06-05 + +### Changed + +- **Dependency and toolchain updates** — no public API changes. Kotlin + `2.3.20` → `2.4.0`, Android Gradle Plugin `9.0.1` → `9.2.1`, Compose + `1.10.3` → `1.11.1`, kotlinx-coroutines `1.10.2` → `1.11.0`, + kotlinx-serialization `1.10.0` → `1.11.0`, Kotest `6.1.9` → `6.1.11`, + and the Gradle wrapper `9.1.0` → `9.5.1`. + ## [0.2.1] - 2026-03-24 ### Fixed diff --git a/README.MD b/README.MD index f46cf1d..2294c9c 100644 --- a/README.MD +++ b/README.MD @@ -1,26 +1,28 @@ Deci [![Maven Central](https://img.shields.io/maven-central/v/org.kimplify/deci)](https://central.sonatype.com/artifact/org.kimplify/deci) -[![Kotlin](https://img.shields.io/badge/Kotlin-2.3.20-7F52FF)](https://kotlinlang.org) +[![Kotlin](https://img.shields.io/badge/Kotlin-2.4.0-7F52FF)](https://kotlinlang.org) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) Deci is a Kotlin Multiplatform library for high-precision decimal arithmetic. Built for money, taxes, invoicing, and any workload where `Float`/`Double` cannot be trusted. ## Features -- **Multiplatform** -- Android, JVM, iOS, macOS, JS, WASM, Linux, Windows +- **Multiplatform** -- Android, JVM, iOS, macOS, JS, WASM - **Exact decimal math** -- backed by `BigDecimal`, `NSDecimalNumber`, and `decimal.js` - **Predictable rounding** -- explicit rounding modes, no silent precision loss - **Serialization ready** -- `kotlinx.serialization` support out of the box ## Installation +> Use the latest version shown in the Maven Central badge above. + Kotlin Multiplatform: ```kotlin kotlin { sourceSets { commonMain.dependencies { - implementation("org.kimplify:deci:0.2.0") + implementation("org.kimplify:deci:0.2.2") } } } @@ -29,7 +31,7 @@ kotlin { Single-platform: ```kotlin dependencies { - implementation("org.kimplify:deci:0.2.0") + implementation("org.kimplify:deci:0.2.2") } ``` @@ -164,7 +166,6 @@ Values serialize as JSON **strings** to preserve trailing zeros and avoid lossy | Android / JVM | `java.math.BigDecimal` | | iOS / macOS | `NSDecimalNumber` | | JS / WASM | `decimal.js` v10.6.0 | -| Linux / Windows | Pure Kotlin | ## Configuration diff --git a/build-logic/src/main/kotlin/deci.kmp.library.gradle.kts b/build-logic/src/main/kotlin/deci.kmp.library.gradle.kts index bc2b4e3..1d6a742 100644 --- a/build-logic/src/main/kotlin/deci.kmp.library.gradle.kts +++ b/build-logic/src/main/kotlin/deci.kmp.library.gradle.kts @@ -15,10 +15,8 @@ kotlin { wasmJs { browser() } // Apple targets - iosX64() iosArm64() iosSimulatorArm64() - macosX64() macosArm64() applyDefaultHierarchyTemplate() diff --git a/build.gradle.kts b/build.gradle.kts index 52af6ae..dc6eaae 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,6 +6,4 @@ plugins { alias(libs.plugins.compose.compiler).apply(false) alias(libs.plugins.kotlinx.serialization).apply(false) alias(libs.plugins.android.application).apply(false) - alias(libs.plugins.ktlint).apply(false) - alias(libs.plugins.binary.compatibility.validator).apply(false) } diff --git a/deci/build.gradle.kts b/deci/build.gradle.kts index b3f5495..22e2bab 100644 --- a/deci/build.gradle.kts +++ b/deci/build.gradle.kts @@ -8,30 +8,22 @@ val libsCatalog = extensions.getByType().named("libs") val deciVersion: String = libsCatalog.findVersion("version").get().requiredVersion kotlin { - androidLibrary { + android { namespace = "org.kimplify.deci" - compileSdk = 36 + compileSdk = 37 minSdk = 21 + withHostTest {} } sourceSets { commonMain.dependencies { - implementation(libs.kotlinx.coroutines.core) - implementation(libs.kotlinx.coroutines.test) implementation(libs.kotlinx.serialization.json) } commonTest.dependencies { implementation(kotlin("test")) implementation(libs.kotest.property) - } - - androidMain.dependencies { - implementation(libs.kotlinx.coroutines.android) - } - - jvmMain.dependencies { - implementation(libs.kotlinx.coroutines.swing) + implementation(libs.kotlinx.coroutines.test) } jsMain.dependencies { diff --git a/gradle.properties b/gradle.properties index 2970463..6c37d98 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,6 +10,7 @@ kotlin.code.style=official kotlin.daemon.jvmargs=-Xmx4G kotlin.native.binary.gc=cms kotlin.incremental.wasm=true +kotlin.native.ignoreDisabledTargets=true #Android android.useAndroidX=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4f8e91d..0218c4a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,22 +1,27 @@ [versions] -version = "0.2.1" +version = "0.2.2" -kotlin = "2.3.20" -agp = "9.0.1" +kotlin = "2.4.0" +agp = "9.2.1" maven-publish = "0.36.0" -compose = "1.10.3" -kotlinx-coroutines = "1.10.2" -kotlinx-serialization = "1.10.0" +compose = "1.11.1" +compose-material3 = "1.9.0" +compose-material-icons = "1.7.3" +kotlinx-coroutines = "1.11.0" +kotlinx-serialization = "1.11.0" androidx-activityCompose = "1.13.0" ktlint-plugin = "14.2.0" binary-compatibility-validator = "0.18.1" -kotest = "6.1.9" +kotest = "6.1.11" [libraries] -kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } -kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" } -kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" } +compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "compose" } +compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "compose" } +compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "compose" } +compose-material = { module = "org.jetbrains.compose.material:material", version.ref = "compose" } +compose-material3 = { module = "org.jetbrains.compose.material3:material3", version.ref = "compose-material3" } +compose-materialIconsExtended = { module = "org.jetbrains.compose.material:material-icons-extended", version.ref = "compose-material-icons" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" } kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" } androidx-activityCompose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } @@ -29,12 +34,9 @@ bcv-gradle-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-valid [plugins] multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } -android-library = { id = "com.android.library", version.ref = "agp" } maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "maven-publish" } compose = { id = "org.jetbrains.compose", version.ref = "compose" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } android-application = { id = "com.android.application", version.ref = "agp" } -ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-plugin" } -binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" } android-kmp-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e11132..5dd3c01 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index b3dae38..bc478d5 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -2870,7 +2870,16 @@ streamroller@^3.1.5: debug "^4.3.4" fs-extra "^8.1.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -2902,7 +2911,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -3245,7 +3261,16 @@ workerpool@^9.2.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-9.3.4.tgz#f6c92395b2141afd78e2a889e80cb338fe9fca41" integrity sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== diff --git a/sample/androidApp/build.gradle.kts b/sample/androidApp/build.gradle.kts index cbe2530..42ef4ed 100644 --- a/sample/androidApp/build.gradle.kts +++ b/sample/androidApp/build.gradle.kts @@ -6,7 +6,7 @@ plugins { android { namespace = "org.kimplify.deci.sample" - compileSdk = 36 + compileSdk = 37 defaultConfig { minSdk = 24 diff --git a/sample/composeApp/build.gradle.kts b/sample/composeApp/build.gradle.kts index 88c9a68..eca6496 100644 --- a/sample/composeApp/build.gradle.kts +++ b/sample/composeApp/build.gradle.kts @@ -15,13 +15,13 @@ plugins { kotlin { jvmToolchain(21) - androidLibrary { + android { namespace = "org.kimplify.deci.sample.shared" - compileSdk = 36 + compileSdk = 37 minSdk = 24 } jvm() - js(IR) { + js { outputModuleName.set("composeApp-js") browser { val rootDirPath = project.rootDir.path @@ -29,10 +29,8 @@ kotlin { commonWebpackConfig { outputFileName = "composeApp-js.js" devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply { - static = (static ?: mutableListOf()).apply { - add(rootDirPath) - add(projectDirPath) - } + static(rootDirPath) + static(projectDirPath) } } runTask { @@ -49,17 +47,14 @@ kotlin { commonWebpackConfig { outputFileName = "composeApp.js" devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply { - static = (static ?: mutableListOf()).apply { - add(rootDirPath) - add(projectDirPath) - } + static(rootDirPath) + static(projectDirPath) } } } binaries.executable() } listOf( - iosX64(), iosArm64(), iosSimulatorArm64() ).forEach { @@ -71,12 +66,12 @@ kotlin { sourceSets { commonMain.dependencies { - implementation(compose.runtime) - implementation(compose.ui) - implementation(compose.foundation) - implementation(compose.material) - implementation(compose.material3) - implementation(compose.materialIconsExtended) + implementation(libs.compose.runtime) + implementation(libs.compose.ui) + implementation(libs.compose.foundation) + implementation(libs.compose.material) + implementation(libs.compose.material3) + implementation(libs.compose.materialIconsExtended) implementation(project(":deci")) implementation(libs.kotlinx.serialization.json) } @@ -101,4 +96,4 @@ compose.desktop { vendor = "Kimplify" } } -} \ No newline at end of file +}