With either coroutine
or ktor
dependency, when KotlinJS
npm library is published, in the resulting generated typescript d.ts
file there are atomicfu
references
export namespace kotlinx.atomicfu {
function atomic$ref$<T>(initial: T, trace: kotlinx.atomicfu.TraceBase): kotlinx.atomicfu.AtomicRef<T>;
function atomic$boolean$(initial: boolean, trace: kotlinx.atomicfu.TraceBase): kotlinx.atomicfu.AtomicBoolean;
function atomic$int$(initial: number, trace: kotlinx.atomicfu.TraceBase): kotlinx.atomicfu.AtomicInt;
function atomic$long$(initial: kotlin.Long, trace: kotlinx.atomicfu.TraceBase): kotlinx.atomicfu.AtomicLong;
}
but reference for TraceBase
is missing from the file and when compiling a Typescript
app that depends on above kotlinJS
library, it complains about missing TraceBase
.
The only way to move forward is to add skipLibCheck = true
in the tsconfig
file. That's not an ideal solution for user of the library.
Is there a way to solve this issue?
It's a known compiler bug. There is an issue created to fix it: https://youtrack.jetbrains.com/issue/KT-50464
Temporarily you can solve it using Gradle by removing all atomicfu
references from the generated d.ts
file.
Solution below assumes that you use this Gradle plugin NPM package publishing. It provides a packJsNpmPublication
task that builds the js
library publication code with specific naming for generated files.
You should add below two gradle tasks
// This task copies content of "js" build folder into a "temp" folder
tasks.register<Copy>("copyJsBuildContentToTemp") {
this.from("$buildDir/publications/npm/js/")
this.into("$buildDir/publications/npm/js/temp/")
}
// This task goes through your `d.ts` file from `temp` folder,
// Removes all the lines containing `atomicfu` word and then last line with '}'
// Then copies the modified file back into `js` folder that replaces the original file
// At the end, it deletes the `temp` folder
tasks.register<Copy>("removeAtomicFu") {
var atomicfu = false
duplicatesStrategy = DuplicatesStrategy.INCLUDE
from(buildDir.resolve("$buildDir/publications/npm/js/temp/${rootProject.name}-${project.name}.d.ts")) {
filter {
when {
it.contains("atomicfu") -> {
atomicfu = true
""
}
atomicfu && it == "}" -> {
atomicfu = false
""
}
else -> it
}
}
}
this.into("$buildDir/publications/npm/js/")
dependsOn("copyJsBuildContentToTemp")
doLast {
delete("$buildDir/publications/npm/js/temp")
}
}
// This makes sure that `removeAtomicFu` tasks runs at the end of task
// `assembleJsNpmPublication` so when `pack` or `publish` runs and creates
// the `tarball` file, it would put update content in the `tgz` file
project.afterEvaluate {
tasks.findByName("assembleJsNpmPublication")?.finalizedBy("removeAtomicFu")
}
Now if you run ./gradlew packJsNpmPublication
you'll have build content without atomicfu
references.