Executing a kotlin -script.kts with a dependency from github - kotlin

I am aware that *.kts scripts can include a dependency like this:
#!/usr/bin/env kscript
#file:DependsOn("com.domain.project:name:1.0-SNAPSHOT")
I created a small library to process different text snippets and uploaded it on github.
Is it possible to use this library as a dependency within a kotlin script without going through mvnRepository or something similar?
something like this for example:
#!/usr/bin/env kscript
#file:DependsOn("com.github.username.project")

I was not able to find a method of requesting the dependency from the repository or the direct url of a jar file.
I was however able to use jitpack on top of my regular github repository. Unfortunately, pointing to the master branch did not work for me, but creating a release seem to work just fine.
The resulting boilerplate looks like this:
#!/usr/bin/env kscript
#file:MavenRepository("com.github.username:repo:1.0.0", "https://jitpack.io")
#file:DependsOn("com.github.username:repo:1.0.0")
import repo.MyLibrary
fun useLibrary(){
val library = MyLibrary()
library.use()
}
Where com.github.username is the personal github account, repo is the repository and 1.0.0 is the release version tag.

Related

How do I apply a plugin in a .kts (Kotlin script) file?

Kotlin script (.main.kts) files have the idea of providing executable Kotlin code in ONE single standalone file, which is immensely convenient for scripting or when sharing code snippets on StackOverflow for example. In contrast to that, currently almost all Java/Kotlin uses a build system (e.g. gradle) with cryptic build files and a deep folder structure.
While I like the Kotlin script idea a lot, it seems to be barely used, with only 22 questions on StackOverflow and extremely sparse documentation and precious few Google results. I am able to pull in dependencies using #file:DependsOn inside of the actual script rather than the traditional build file:
build.gradle:
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0'
}
foo.main.kts:
#file:DependsOn("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0")
However, I can't find a way to use "apply plugin" in my .main.kts file. It's not used in any of the code snippets I found online.
build.gradle:
apply plugin: 'kotlinx-serialization'
foo.main.kts:
???
For reference, I attached an MWE below. The error message says the class Node is not serializable, but as pointed out in this question that message is misleading and the actual issue that apply plugin is missing, which I do not know how to use outside of a build.gradle file:
#file:DependsOn("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0")
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
#Serializable
data class Node (val numbers: List<Int>)
val h = Json.decodeFromString<Node>(""" {"numbers": [1, 2, 3]} """)
Run it on Ubuntu:
snap install kotlin
kotlin foo.main.kts
kotlinx-serialization is a Gradle plugin, which adds to pipeline same-named compiler plugin - it generates the serializer() method for classes annotated with #Serializable.
When you compile Kotlin code with kotlinc compiler, you can attach the plugin by providing the path to its JAR file (it's bundled with the compiler) using the -Xplugin=/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar compiler option.
For .kts files, there is a #file:CompilerOptions annotation, but currently (in Kotlin 1.5.10) this particular key is not supported (warning: the following compiler arguments are ignored on script compilation: -Xplugin)
Command line
On the command line you may use
kotlinc -script -Xplugin="/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar" foo.main.kts
Script header
As a workaround you may use this shebang:
#!/usr/bin/env -S kotlinc -script -Xplugin="/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar"
To run your script you need to turn it into an executable:
chmod u+x foo.main.kts
Now it could be run with:
./foo.main.kts

How to run aurelia-plugins/aurelia-plugins-google-places-autocomplete locally

I have installed this aurelia plugin in my project: https://github.com/aurelia-plugins/aurelia-plugins-google-places-autocomplete which is basically an Aurelia wrapper for google places autocomplete.
Unfortunately I'm experience a "regeneratorRuntime is not defined" issue when using it (It has been reported in the repo). And the reason seems to be the way that async/await are transpiled. I have found a possible solution to fix the issue as seen here: Babel 6 regeneratorRuntime is not defined with async/await
I have cloned the repo and installed now I just need to be able to run it locally to test it out. Does someone know how I can run that repo locally. Thank you very much.
Usually what I do when I want to test a plugin is I will create test project where I run the plugin as a feature. Features work just like plugins except they are local to your project's structure. Instead of doing
aurelia.use
.plugin('aurelia-plugins-google-places-autocomplete', config => { \\...
You will do
aurelia.use
.feature('aurelia-plugins-google-places-autocomplete', config => { \\...
This is assuming you place the plugin in src\aurelia-plugins-google-places-autocomplete.
This is a story that I would like to see us come up with a pattern for. Maybe we'll add something to the skeleton-plugin project that will help with this.

How to work with gradle wrapper, init script, multi project and best with idea

to sum up the components and environment:
multi-project, typically each gradle project is soley in a seperate git
you don't want to use submodules
gradle init scripts in a seperate config / super repository
using gradle wrapper
for the GUI guy: IntelliJ IDEa with Gradle integratiom -> help
allowed to use gradle idea -> guide
so,
Q: How to elegant marriage these components. How can I define an init script to be used in the wrapper of a single repository without affecting other repositories.
I know:
init scripts are typical in a "GRADLE_HOME" directory
init scripts can be defined per console via -I
(yes, I read the documentation 😅 )
Problems found:
intelliJ doesn't allow to define the -I option in UI
anyone needs to checkout and update a seperate repository if you want to share between projects
the settings.gradle || gradle.properties file seems not to support any option either
Constraints:
(while these are possible answers, they are neither elegant nor fault proof)
the desired solution should be applicable for SINGLE projects, and should not be globally applied to all projects on the same computer
Hidden Questions:
can I include global gradle settings from an URL so noone needs a clone of the meta-repo??
does an URL include do the same as an init script? Or what you can do with initScript what you can't in include?
You can do the following:
Create a custom gradle distribution with the common settings defined in the init script
Configure your projects to use that distribution through the distributionUrl key in the gradle/wrapper/gradle-wrapper.properties
Use regular gradle build from command line/usual import into intellij - it just works
By the way, there is a gradle plugin for simplifying custom gradle distribution construction
You can use the buildSrc customization - depending on what you need -
where buildSrc/build.gradle takes effect prior configuration phase of your project.
What you should know, that there is a different scope, i.e. buildSrc/build.gradle's allprojects is scoped to any project beneath buildSrc and not your normal projects.
More generally speaking: buildSrc/build.gradle is like what you do normally in buildscript or task declarations in script plugins and you can write clean plugin code without publish it as plugins.
⚠️ Limitations:
you can't take care about plugin resolution - therefor you have to get into your projects settings.gradle
you can't change dependency management for your projects - you still have to do this in your project's buildSrc
for both you can see How can the gradle plugin repository be changed?
you still have to apply (even self buildSrc homed) plugins in your project (what is a good thing if you ask me, because it's more visible / clear what happens)
you can't share this with a second repository - without using git submodules, etc.

Play 2 dependency on a local module in Intellij Idea

I am kind of new to PlayFramework 2 and can not figure out how to resolve play 2 application dependencies. I need to add dependency on a local module loaded in IntellijIdea, not a jar file or repository.
While adding module dependencies in Idea project setting works just fine and ide itself is able to resolve them (autocompletion, imports etc are working), when trying to run in play2, its compiler cannot resolve any dependencies.
I manually configured Build.scala (adding val appDependencies = Seq("" % "" % "")) but am puzzled as to what resolvers I should use. I cannot point to a jar file, as it is a work in progress and such a file should be updated too often. Doing so would defeat the whole purpose of managed dependencies.
Play's main build mechanism uses SBT, which needs to know how to find all sources required for the build. There are several options for this:
make your module an SBT project itself and publish it to your local ivy repository. However that might be somewhat complex at this stage, and would involve adding your local ivy repository to the resolvers and re-publishing every time you change something in the module
declare your module as a sub-project. Play's documentation describes the process of working with sub-projects, I think this is the way you'd like to try out since then the idea command on Play's console will generate the IntelliJ configuration for the main application and the module.

How do I reference play framework third party modules without referencing an absolute path?

Here is my situation. I have a play app which uses the guice module. In order to work with the guice module:
I installed it using play install guice. This installs it in the $PLAY_HOME/modules which is fine by me. I don't want to edit the module files in any way whatsoever.
Then I declared the module in my dependencies.yml like so: - play -> guice 1.2
Within my app, I ran play dependencies, and this resoles the module just fine and creates a modules/guice-1.2 file that references the guice module.
The issue is that the content of that file is something like the following: /some-absolute-path/play-1.2.x/modules/guice-1.2.
That works fine when working locally for development. But when I want to move to a production server, with a different install of Play! (i.e. with a different absolute path to it) it will obviously fail.
So what's the best way to deal with this?
For now I've resorted to declaring the module in the application.conf file like this: module.guice=${play.path}/modules/guice-1.2.
Unfortunately the ${play.path} magic doesn't seem to work on those generated files.
By the way I use version 1.2.3 of Play!
you should try with ${application.path} in your dependencies.yml file, like in this example
require:
- play -> crud
- provided -> DateHelper 1.0
repositories:
- provided:
type: local
artifact: "${application.path}/jar/[module]-[revision].jar"
contains:
- provided -> *
see this question: How can I specify a local jar file as a dependency in Play! Framework 1.x
When you run in production you will either resync the dependencies (via play deps command) with the local installation of Play or in some scenarios you can precompile everything and then there will be no issues with the paths.
That second scenario is the one with Heroku, for example.
It's not answer to your question, but I have faced with same issue.
I don't want to call resync the dependencies on production.
I don't want to ask my team members, install special module.
I don't want to commit file containing absolute path with module location.
The only workaround that I find: do not install module in Play! application, just include jars which use this module manually. play-guice.jar should be included as #opensas suggested, aopalliance and com.google.inject as regular dependencies in dependencies.yml.
The funny thing, that resync dependencies is also deleting .svn files, so back-up its before calling this command.