Is it possible to import a JavaScript file in a Kotlin/JS project?
Asked Answered
M

2

11

If I have a JavaScript file called myfile.js as follows:

function myJsFunc() { return "Hello from JavaScript"; }

How can I import this file into a Kotlin/JS project and invoke myJsFunc() from Kotlin code?

Muzz answered 23/5, 2021 at 14:57 Comment(2)
Maybe you should edit your question to be specific that it's for the Node.js target. For the browser target, this can be solved by adding further adjustments in the webpack.config.d folder as Joffrey pointed out.Grounds
Dukat has been removed from kotlin gradle plugin in recent versions as it was not reliable enough to be useful. The team is rethinking the approach before reintegrating it back.Grory
G
4

Copied-over from slack discussion


First you need to declare an npm dependency in gradle

kotlin.sourceSets.named("jsMain") {
  dependencies {
    implementation(npm("package-name", "version"))
  }
}

Then you can either use ./gradlew generateExternals and pray that dukat works or write external declarations yourself.

package-name and version appears the same as it would in package.json, so all the protocols like file:xxx are supported as well.

You can also hack it with local TS sources, however I do not recommend it. If you still must stick with it, create a small npm module somewhere on your repo and use that via file:path/to/that/module version instead. I recommend generating absolute path to that module in gradle instead of trying to work out relative path from package.json that kotlin plugin generates

kotlin.sourceSets.named("jsMain") {
  dependencies {
    val pathToLocalNpmModule = rootProject.projectDir.resolve("js/my-module").canonicalPath
    implementation(npm("my-module", "file:$pathToLocalNpmModule"))
  }
}

Finally, for that particullar function, kotlin external declaration would look like this (assuming that you point your package.json#main field directly to that js file)

// Explicit export
export function myJsFunc() { return "Hello from JavaScript"; }

// Default export
export default myJsFunc
// Explicit export
@JsModule("my-module")
public external fun myJsFunc(): String

// Default export
@JsModule("my-module")
@JsName("default")
public external fun myJsFunc(): String

Now on the inverse, if you want to integrate your kotlin/js gradle module into local js/ts project, I recommend just using ./gradlew pack task provided by npm-publish gradle plugin (configures itself, just apply it) and use the bundle via file:xxx version protocol in your js/ts package.json.

Grory answered 8/7, 2021 at 16:18 Comment(1)
Is there any documentation describing how to use Dukat with Gradle? I can't find anything. Searching ./gradlew generateExternals doesn't give anything. It would be really nice to be able to generate Kotlin bindings with a gradle task.Lapoint
L
-2

You will probably find some interesting information in the doc: Use JavaScript from Kotlin.

Essentially, you'll need to write external declarations manually to tell Kotlin about the functions and types that should be available in JS.

Making the file itself available depends on your build and how you deploy your code.

Latialatices answered 23/5, 2021 at 15:2 Comment(6)
Hi, yes I have read this page many times already. Of external declarations, it says, tantalisingly, "When the compiler sees such a declaration, it assumes that the implementation for the corresponding class, function or property is provided externally (by the developer or via an npm dependency )" -- without explaining how to provide the implementation.Muzz
@Muzz It will really depend on how you build your code and where the file comes from. For instance, how do you include the JavaScript file compiled from Kotlin into your application? Is it included in an HTML page? If so, and if your JS file is part of your sources, you can reference your JS file from the HTML. If your JS comes from an NPM dependency, you can use gradle's dependencies block with npm() helper to get it.Latialatices
feels like the questions you're asking me are the questions I want the answer to :) If it helps, my project is ultimately going to run on Node.js rather than in the browser. No it does not come from an NPM dependency. Like I say in my question, it's a simple Javascript file which I want to include. You ask "How do you include the JavaScript file"? That's my question! Can it be loaded from the resources folder, for example? If not, how can I include it?Muzz
@Muzz "you ask how do you include the JS file, that's my question" - Actually I asked how you include the JS file that is the build product of your Kotlin sources, not the JS file that you want to use as a dependency. I'm assuming you already have the Kotlin/JS project setup, with only Kotlin sources, and now you're trying to add a JS file as a dependency. That's why I ask questions about your setup of the Kotlin/JS project.Latialatices
If it's going to run on nodejs, I'm assuming you intend to run the compiled Kotlin/JS file directly. I'm not well versed into runtime dependencies management in Node, but I think you may have to turn your JS file into a module and tweak the generated webpack config. Unfortunately I don't have much experience there, but you can most likely find help on the Kotlin/JS public slackLatialatices
At the moment I'm simply using ./gradlew nodeRun to run my project, and unsurprisingly it can't find my external function. I guess I need to put the JS file somewhere it can be found (where?) and include @JSModule or similar annotation to point to the name of the file and the function within the file (what exactly?)Muzz

© 2022 - 2024 — McMap. All rights reserved.