writing nodejs applications in kotlin with intellij idea ce - node.js

I am trying to develop a Nodejs application using Kotlin 1.3.11 using the IntelliJ IDEA CE development environment. Unfortunately I haven't made any progress towards a running application. To ensure everything is setup correctly I want to print out a simple "hello world".
I searched for articles or tutorials about the topic but I didn't find much about bringing those three together (Kotlin, IntelliJ, Nodejs). The most specific ones which I found are:
a medium post and another post.
As far as I (believe to) know, there are three major steps:
calling initializing the node app via npm and using npm to install the node dependencies like kotlin and expressjs
creating a build.gradle to define other dependencies and tasks
creating an IntelliJ IDEA project
I tried to perform the steps in different orders but I never came to a running application. Also I searched in IntelliJ's documentation but the Nodejs integration isn't a feature of the free community edition. There isn't a description how to make Kotlin and Nodejs work together too.
Has anyone here successfully tried to do that (or failed and knows why it is not going to work)? Do I have to use another IDE or to write my own build tools/toolchain?
Sincerely J.

I haven't done this in IDEA CE, but theoretically, this should work.
Prerequisites: You have node installed, you can execute gradle tasks
This is a Minimum Configuration, There is a comprehensive one. Add a comment if intrested for that
Step 1:Create a new Kotlin/JS project (with gradle) and make sure that your gradle build file looks like this
group 'node-example'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.3.11'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin2js'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
}
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "node/index.js"
}
task npmInit(type: Exec) {
commandLine "npm", "init", "-y"
}
task npmInstall(type: Exec) {
commandLine "npm", "install", "kotlin", "express", "--save"
}
task npmRun(type: Exec) {
commandLine "node", "node/index.js"
}
npmRun.dependsOn(build)
Step 2: After syncing your build.gradle in step 1 run the gradle tasks npmInit and npmInstall
./gradlew :npmInit
./graldew :npmInstall
Step 3:
Create your kotlin file (index.kt/main.kt/whatever.kt) in src/main/kotlin and test the code below
external fun require(module:String):dynamic
fun main(args: Array<String>) {
println("Hello JavaScript!")
val express = require("express")
val app = express()
app.get("/", { req, res ->
res.type("text/plain")
res.send("Kotlin/JS is kool")
})
app.listen(3000, {
println("Listening on port 3000")
})
}
Step 4: RTFA - Run The App
Run the gradle task npmRun
./gradlew :npmRun
Hope that helps
Note:
1. This template was pulled from the medium post you asked above and modified a little
2. Remember to run your gradle tasks using sudo (if you are using linux)

Edit: Alternatively, you could clone https://github.com/miquelbeltran/kotlin-node.js and follow the instructions in the read me.
I managed to get the Medium post to work by replacing gradle build with the following (since the post was published in 2017(!) and requires a much older version of Gradle):
Comment out the entire contents of build.gradle like so:
/*group 'node-example'
...
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "node/index.js"
}*/
Run this command in the command prompt: (3.4.1 was the latest version of Gradle just before the Medium post was published.)
gradle wrapper --gradle-version=3.4.1
Uncomment out build.gradle:
group 'node-example'
...
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "node/index.js"
}
Run this command in place of gradle build:
gradlew build
And finally run this command as in the post: (As of writing this answer on StackOverflow, Node.js does not be downgraded and the current LTS version 10.16.0 works perfectly.)
node node/index.js

Related

Could not find org.nodejs:x64

When I try to build my Frontend app I get
Could not resolve all dependencies for configuration ':frontend:nodeDist'.
> Could not find org.nodejs:x64/node:6.17.1.
Searched in the following locations:
http://nodejs.org/dist/v6.17.1/ivy.xml
http://nodejs.org/dist/v6.17.1/x64/node.exe
On another machine it downloads the node without issue from http://nodejs.org/dist/v6.17.1/win-x64/node.exe
Why does my machine not create the same download url with win-x64 instead of x64?
my build.gradle contains:
buildscript {
dependencies {
classpath 'com.moowork.gradle:gradle-node-plugin:0.10'
}
}
apply plugin: 'com.moowork.node'
node {
version = '6.17.1'
npmVersion = '2.10.1'
download = true
}
upgrading the versions is not an option in my case

Building NodeJS using Gradle

I'm very new to Gradle. I started reading about it yesterday. I found an example build.gradle that builds a node application. I'm a little bit confused in the contents of the file. I'm not sure which ones are reserved or predefined words. One of the strings is node. It wasn't used somewhere but I figured out it was needed by the node plugin.
buildscript {
repositories {
mavenCentral()
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'com.moowork.gradle:gradle-node-plugin:1.2.0'
}
}
apply plugin: 'base'
apply plugin: 'com.moowork.node' // gradle-node-plugin
node {
/* gradle-node-plugin configuration
https://github.com/srs/gradle-node-plugin/blob/master/docs/node.md
Task name pattern:
./gradlew npm_<command> Executes an NPM command.
*/
// Version of node to use.
version = '10.14.1'
// Version of npm to use.
npmVersion = '6.4.1'
// If true, it will download node using above parameters.
// If false, it will try to use globally installed node.
download = true
}
npm_run_build {
// make sure the build task is executed only when appropriate files change
inputs.files fileTree('public')
inputs.files fileTree('src')
// 'node_modules' appeared not reliable for dependency change detection (the task was rerun without changes)
// though 'package.json' and 'package-lock.json' should be enough anyway
inputs.file 'package.json'
inputs.file 'package-lock.json'
outputs.dir 'build'
}
// pack output of the build into JAR file
task packageNpmApp(type: Zip) {
dependsOn npm_run_build
baseName 'npm-app'
extension 'jar'
destinationDir file("${projectDir}/build_packageNpmApp")
from('build') {
// optional path under which output will be visible in Java classpath, e.g. static resources path
into 'static'
}
}
// declare a dedicated scope for publishing the packaged JAR
configurations {
npmResources
}
configurations.default.extendsFrom(configurations.npmResources)
// expose the artifact created by the packaging task
artifacts {
npmResources(packageNpmApp.archivePath) {
builtBy packageNpmApp
type 'jar'
}
}
assemble.dependsOn packageNpmApp
String testsExecutedMarkerName = "${projectDir}/.tests.executed"
task test(type: NpmTask) {
dependsOn assemble
// force Jest test runner to execute tests once and finish the process instead of starting watch mode
environment CI: 'true'
args = ['run', 'test']
inputs.files fileTree('src')
inputs.file 'package.json'
inputs.file 'package-lock.json'
// allows easy triggering re-tests
doLast {
new File(testsExecutedMarkerName).text = 'delete this file to force re-execution JavaScript tests'
}
outputs.file testsExecutedMarkerName
}
check.dependsOn test
clean {
delete packageNpmApp.archivePath
delete testsExecutedMarkerName
}
Also, how is the build.gradle parsed? I'm also wondering how it is able to magically download node and npm tools.
This is a very general synopsis:
Gradle aims to hide away the logic from developers.
Most *.gradle files contain configuration blocks (closures) to specify HOW logic should run.
Plugins augment gradle with more configurable logic.
Also, 'convention over configuration' is a practice emphasize in gradle and its plugins, providing sensible defaults to minimize developers' configuration efforts.
The com.moowork.node plugin is configured through the node extension block.
Extension blocks are gradle's way to allow plugins to add more 'reserved' words to the standard gradle model.
The download = true configuration tells the plugin to download node (version = '10.14.1') and nmp (npmVersion = '6.4.1') in your project's root (unless you override its defaults as well).
The download of these tools will occur when any of the plugin's task is invoked.
Hope this helps.
In your snippet only true is keyword, the other things are methods or getters coming from Gradle or Node JS plugin:
apply plugin: ... is a method from org.gradle.api.Project.apply(java.util.Map<String, ?>)
node is a method autogenerated by Gradle with signature void node(Closure<com.moowork.gradle.node.NodeExtension>) (method accepting a code block), see https://github.com/srs/gradle-node-plugin/blob/master/src/main/groovy/com/moowork/gradle/node/NodeExtension.groovy
node { version = ... } - version, npmVersion are fields from NodeExtension class
other things similarly, everything is a method or a field. If you're using IntelliJ, use Ctrl+mouse click to navigate to the originating method/field declaration.

How to change Node.js version on Jenkins?

I have several jobs on Jenkins for launch protractor tests. I'm starting to use async/await at some points and seems that the default version of Node.js that has Jenkins doesn't handle async/await.
I prepared a workaround on another pipeline that uses async/await, but I don't want to use it as a default solution:
nodejs(nodeJSInstallationName: "Node 8.11") {
"npm config ls"
"node -v"
"npm"
}
How can I setup the desired version Node.js, which will be used by Jenkins by default?
Go to: Dashboard → Manage Jenkins → Global Tool Configuration → NodeJS and pick the desired Node.js version from the combobox.
Just use the following two lines in your pipeline
env.NODEJS_HOME = "${tool 'NodeJsv12.16.2'}"
env.PATH="${env.NODEJS_HOME}/bin:${env.PATH}"
See the example bellow
node {
env.NODEJS_HOME = "${tool 'NodeJsv12.16.2'}"
env.PATH="${env.NODEJS_HOME}/bin:${env.PATH}"
sh 'npm --version'
stage('Preparation') {
}
}

Importing react-native project in android studio

Am having a small problem with opening/importing a react-native into Android studio.
If I open the project using the open a project dialog, it tells me that the project is not gradle enabled and it is such a pain to make and test code changes. Couldn't find out how to enable the project as a gradle project after the fact even after going through the material on the help site.
On the other hand, if I import using the import a gradle project dialog and select the build.gradle file, the project is imported, but I only see the files inside the android directory instead of the main project directory. But this method allows me to push changes easily to the emulator.
How can I fix my problem?
Thanks,
Just import android directory from Android Studio,
make changes to your app/build.gradle
add these codes before apply from: "../../node_modules/react-native/react.gradle"
project.ext.react = [
bundleAssetName: "index.android.bundle",
entryFile: "index.android.js",
bundleInDebug: false,
bundleInRelease: true,
root: "../../",
jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
jsBundleDirRelease: "$buildDir/intermediates/assets/release",
resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
inputExcludes: ["android/", "ios/"],
nodeExecutableAndArgs: ["node"],
extraPackagerArgs: []
]
Now create task for "react-native start" to your gradle
task startReactNative(type: Exec) {
workingDir "../../"
commandLine 'cmd', '/c', 'react-native', 'start'
println "Working Directory for React is: $workingDir"
standardOutput = new ByteArrayOutputStream()
ext.output = {
println "React-Native Output: " + standardOutput.toString()
return standardOutput.toString()
}
}
You can run your app as usual, after app installed to your device, run startReactNative task in order to activate Hot Reload

Module missing in Android Studio and Gradle sync fails

I have set up a brand new project in Android Studio 1.1 RC 1:
Created an Android project [app] (because there is no way to create an App Engine backend project right away).
Added an existing backend module by first creating a new App Engine module and then manually importing the files [backend].
Removed the Android app module [app].
Added a Java library module, same procedure, first creating a new module, then importing files [common].
Everything compiles fine, but Android Studio has two problems:
When I look at Project Structure, the [common] module is missing in the left pane, but it still appears as referenced module in the right pane!?
My Project tree looks fine and all modules are recognized, but gradle is telling me the sync failed.
Gradle says "Task '' not found in root project" ('' is empty string as it seems). I get a Warning and an exception in the log when running from Terminal, but it doesn't seem to be related (related to Indexing), so I haven't included it here.
settings.gradle has both modules specified:
include ':backend', ':common'
I tried to exchange the .iml file of the main project with a fake one which contains both modules, with the result that (besides multiple side effects) both modules were there. (I restored the original state because of the side-effects.)
Here are my gradle files:
Root module:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.1'
}
}
allprojects {
repositories {
jcenter()
}
}
[backend]
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.google.appengine:gradle-appengine-plugin:1.9.17'
}
}
repositories {
jcenter();
}
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'appengine'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
dependencies {
appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.17'
compile 'com.google.appengine:appengine-endpoints:1.9.17'
compile 'com.google.appengine:appengine-endpoints-deps:1.9.17'
compile 'javax.servlet:servlet-api:2.5'
compile 'com.googlecode.objectify:objectify:5.1.3'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'io.jsonwebtoken:jjwt:0.4'
compile project(':common')
}
appengine {
downloadSdk = true
appcfg {
oauth2 = true
}
endpoints {
getClientLibsOnBuild = true
getDiscoveryDocsOnBuild = true
}
}
[common]
apply plugin: 'java'
task sourcesJar(type: Jar, dependsOn:classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts {
archives sourcesJar
}
dependencies {
compile 'com.google.http-client:google-http-client-android:1.18.0-rc'
compile 'com.google.code.gson:gson:2.3.1'
}
apply plugin: 'maven'
group = 'cc.closeup'
version = 'v2-2.0-SNAPSHOT'
install {
repositories.mavenInstaller {
pom.artifactId = 'common'
pom.packaging = 'jar'
}
}
Any ideas? Anything else that you'd like to see here?
If you want to build an AE project only. You could try this tutorial for intellij idea jetbrains.com/idea/help/creating-google-app-engine-project.html
My mistake was I removed [app]. It seems that if you create an App Engine backend module, you must keep a "fake" frontend module in the same project to keep Android Studio/gradle happy.
In earlier Android Studio versions it was possible to remove the frontend module without problems, but it seems Google has locked this somehow. It still works when I keep the fake frontend module.
--
Why I configured it this way? In my configuration, I have backend and frontend modules in different projects, and I have the backend project install libraries into local Maven, which I then pick up within my frontend project (with a team you would choose a local Maven server). This configuration has multiple advantages, for example that I can test backend/frontend on two screens simultaneously without switching back and forth all the time. Some companies may also want this configuration to keep their backend code separate and secure.

Resources