scalacenter / scalajs-bundler

https://scalacenter.github.io/scalajs-bundler
Other
234 stars 101 forks source link

Task to check latest npm versions (like sbt-updates for npmDependencies) #191

Open nafg opened 6 years ago

nafg commented 6 years ago

I have this code unversioned in some of my projects. I think scalajs-bundler would be a better home for it. I don't remember how much of it was copied from somewhere online.


val npmLatest = taskKey[Unit]("Get latest npm package versions")
npmLatest := {
  val logger = streams.value.log
  val projsDeps =
    Def.task {
      (projectID.value.name, (npmDependencies in Compile).??(Nil).value)
    }.all(ScopeFilter(inAnyProject)).value

  def pad(s: String, len: Int): String = s.padTo(len, ' ')

  val maxProjLen = projsDeps.map(_._1.length).max
  val maxPkgLen = projsDeps.flatMap(_._2.map(_._1.length)).max
  val maxVerLen = projsDeps.flatMap(_._2.map(_._2.length)).max
  for ((proj, deps) <- projsDeps) {
    val latestVersions =
      for ((pkg, ver) <- deps)
        yield (pkg, ver, s"npm view $pkg dist-tags.latest".!!.trim)
    val updates = latestVersions.filter(x => x._2 != x._3)
    if (updates.nonEmpty) {
      logger.info(s"$BOLD${pad(proj, maxProjLen)} $RESET${updates.length} new npm package versions")
      for ((pkg, cur, latest) <- updates)
        logger.info(s"  $BOLD${pad(pkg, maxPkgLen)}$RESET ${pad(cur, maxVerLen)} -> $latest")
    }
  }
}
nafg commented 6 years ago

In scalajs-bundler it might be structured differently. The main thing is to iterate over npmDependencies, run npm view $PACKAGE_NAME dist-tags.latest on each one, and compare the returned version with the configured version.

nafg commented 5 years ago

My biggest issue was reusing this across the right projects

I just realized I can make a shell script like this, using a multiline-string parameter (fish; for bash you may need a heredoc):

sbt 'set TaskKey[Unit]("npmLatest") := {
  import scala.Console._
  import scala.sys.process._

  val logger = streams.value.log
  val projsDeps =
    Def.task {
      (projectID.value.name, (npmDependencies in Compile).??(Nil).value)
    }.all(ScopeFilter(inAnyProject)).value

  def pad(s: String, len: Int): String = s.padTo(len, 32.toChar)

  val maxProjLen = projsDeps.map(_._1.length).max
  val maxPkgLen = projsDeps.flatMap(_._2.map(_._1.length)).max
  val maxVerLen = projsDeps.flatMap(_._2.map(_._2.length)).max
  for ((proj, deps) <- projsDeps) {
    val latestVersions =
      for ((pkg, ver) <- deps)
        yield (pkg, ver, s"npm view $pkg dist-tags.latest".!!.trim)
    val updates = latestVersions.filter(x => x._2 != x._3)
    if (updates.nonEmpty) {
      logger.info(s"$BOLD${pad(proj, maxProjLen)} $RESET${updates.length} new npm package versions")
      for ((pkg, cur, latest) <- updates)
        logger.info(s"  $BOLD${pad(pkg, maxPkgLen)}$RESET ${pad(cur, maxVerLen)} -> $latest")
    }
  }
}' npmLatest

Now I can just keep it in ~/bin and use it whenever I need it!