Scala.jsをNode環境で動作させるときに環境変数を取得したかったけどうまく動かずにハマったのでメモ。
tl;dr
val env = js.Dynamic.global.process.env.asInstanceOf[js.Dictionary[String]].toMap
Scala.jsと環境変数
通常Scalaで環境変数にアクセスするにはsys.env
を利用するが、もともとJavascript(ECMAScript)はブラウザ上で動作するためのスクリプトであるため、環境変数の概念がない。
Node.jsを利用すると普通に環境変数を利用できるが、これはあくまでNode.jsという言語処理系が特別にモジュールを用意してくれているというだけの話で、Node限定の話だ*1。
このためか、忠実にJavascriptにコードを変換するScala.jsでは、sys.env
を利用しても環境変数を得られない。Node.jsを前提にしてしまうことは避けたいのだろう。
実行環境としてNode.jsを前提にしてよいのであれば、グローバルオブジェクトを経由して以下のように環境変数をMap
の形で取り出すことができる:
val env = js.Dynamic.global.process.env.asInstanceOf[js.Dictionary[String]].toMap
要するにNode.jsの機能を直接呼び出しているだけだ。
Cats Effect 3の場合
ちなみにCats Effect 3はEnv
という環境変数を扱うための組込みのモジュールを提供している。
こちらは実行環境ごとに正しく環境変数を取得するためのコードが仕込まれていて、Scala.jsでも正しく動作する:
//> using scala 3.3.3 //> using dep "org.typelevel::cats-effect::3.5.4" import cats.effect.IO import cats.effect.std.Env object App extends cats.effect.IOApp.Simple { def run: IO[Unit] = for { e <- Env[IO].get("HOME") _ <- IO.println(e) } yield () }
最初からCats Effectを使うのであればこれを使うのがよいだろう。
*1:といってもBunなどでは同じAPIで環境変数を取得できるようになっている