Packages

Embed a safe and reproductible node environment into your Elixir application

Current section

Files

Jump to
nox lib nox.env.ex
Raw

lib/nox.env.ex

defmodule Nox.Env do
@moduledoc """
Environment of node installation
If new/1 is called with `shared: true`, directory is built from a hash
of (parsed) versions and thus, will be shared between all envs using
these versions.
"""
alias Nox.Semver
defstruct dir: nil, versions: []
@default_nvm "v1.1.2"
@default_node "8.9.4"
@default_npm "5.6"
@type options :: [option]
@type option :: {:dir, Path.t}
| {:shared, boolean}
| {:node, String.t}
| {:nvm, String.t}
| {:npm, String.t}
@type t :: %__MODULE__{}
@doc """
Creates new env
"""
@spec new(options) :: t
def new(options \\ []) do
# Check version syntax
{_, _, _, _} = Semver.parse(Keyword.get(options, :nvm, @default_nvm))
{_, _, _, _} = Semver.parse(Keyword.get(options, :node, @default_node))
{_, _, _, _} = Semver.parse(Keyword.get(options, :npm, @default_npm))
versions = [
nvm: Keyword.get(options, :nvm, @default_nvm),
node: Keyword.get(options, :node, @default_node),
npm: Keyword.get(options, :npm, @default_npm)
]
dir = if Keyword.get(options, :shared, false) do
find_shared(versions)
else
Keyword.get_lazy(options, :dir, fn -> :code.priv_dir(:nox) end)
end
%__MODULE__{ dir: dir, versions: versions }
end
@doc """
Creates default env
"""
@spec default() :: t
def default, do: new(shared: false)
###
### Priv
###
def find_shared(versions) do
hash = Enum.reduce(versions, :crypto.hash_init(:sha256), fn
{util, vsn}, ctx ->
vhash = :erlang.phash2({util, Semver.parse(vsn)})
:crypto.hash_update(ctx, "#{vhash}")
end) |> :crypto.hash_final() |> Base.url_encode64()
Path.join Application.get_env(:nox, :shared_dir), "nox-#{hash}"
end
end