Subiendo api v2
This commit is contained in:
0
deps/dotenv/.fetch
vendored
Normal file
0
deps/dotenv/.fetch
vendored
Normal file
3
deps/dotenv/.formatter.exs
vendored
Normal file
3
deps/dotenv/.formatter.exs
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[
|
||||
inputs: ["mix.exs", "{lib,test}/**/*.{ex,exs}"],
|
||||
]
|
||||
BIN
deps/dotenv/.hex
vendored
Normal file
BIN
deps/dotenv/.hex
vendored
Normal file
Binary file not shown.
21
deps/dotenv/LICENSE
vendored
Normal file
21
deps/dotenv/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Avdi Grimm
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
104
deps/dotenv/README.md
vendored
Normal file
104
deps/dotenv/README.md
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
# Dotenv for Elixir [](https://hex.pm/packages/dotenv) 
|
||||
|
||||
|
||||
This is a port of @bkeepers' [dotenv](https://github.com/bkeepers/dotenv) project to Elixir. You can read more about dotenv on that project's page. The short version is that it simplifies developing projects where configuration is stored in environment variables (e.g. projects intended to be deployed to Heroku).
|
||||
|
||||
## WARNING: Not compatible with Elixir releases
|
||||
|
||||
Elixir has an excellent configuration system and this dotenv implementation has
|
||||
a serious limitation in that it isn't available at compile time. It fits very
|
||||
poorly into a deployment setup using Elixir releases, distillery, or similar.
|
||||
|
||||
Configuration management should be built around Elixir's existing configuration system. A good example is [Phoenix](http://www.phoenixframework.org/) which generates a
|
||||
project where the production config imports the "secrets" from a file stored
|
||||
outside of version control. Even if you're using this for development, the same
|
||||
approach could be taken.
|
||||
|
||||
However, if you are using Heroku, Dokku, or another deployment process that does *not* use releases, read on!
|
||||
|
||||
### Quick Start
|
||||
|
||||
The simplest way to use Dotenv is with the included OTP application. This will automatically load variables from a `.env` file in the root of your project directory into the process environment when started.
|
||||
|
||||
First add `dotenv` to your dependencies.
|
||||
|
||||
For the latest release:
|
||||
|
||||
```elixir
|
||||
{:dotenv, "~> 3.0.0"}
|
||||
```
|
||||
|
||||
Most likely, if you are deploying in a Heroku-like environment, you'll want to only load the package in a non-production environment:
|
||||
|
||||
```elixir
|
||||
{:dotenv, "~> 3.0.0", only: [:dev, :test]}
|
||||
```
|
||||
|
||||
For master:
|
||||
|
||||
```elixir
|
||||
{:dotenv, github: "avdi/dotenv_elixir"}
|
||||
```
|
||||
|
||||
Fetch your dependencies with `mix deps.get`.
|
||||
|
||||
Now, when you load your app in a console with `iex -S mix`, your environment variables will be set automatically.
|
||||
|
||||
#### Using Environment Variables in Configuration
|
||||
|
||||
[Mix loads configuration before loading any application code.](https://github.com/elixir-lang/elixir/blob/52141f2a3fa69906397017883242948dd93d91b5/lib/mix/lib/mix/tasks/run.ex#L123) If you want to use `.env` variables in your application configuration, you'll need to load dotenv manually on application start and reload your application config:
|
||||
|
||||
```elixir
|
||||
defmodule App.Application do
|
||||
use Application
|
||||
|
||||
def start(_type, _args) do
|
||||
unless Mix.env == :prod do
|
||||
Dotenv.load
|
||||
Mix.Task.run("loadconfig")
|
||||
end
|
||||
|
||||
# ... the rest of your application startup
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
#### Elixir 1.9 and older
|
||||
|
||||
If you are running an old version of Elixir, you'll need to add the `:dotenv` application to your applications list when running in the `:dev` environment:
|
||||
|
||||
```elixir
|
||||
# Configuration for the OTP application
|
||||
def application do
|
||||
[
|
||||
mod: { YourApp, [] },
|
||||
applications: app_list(Mix.env)
|
||||
]
|
||||
end
|
||||
|
||||
defp app_list(:dev), do: [:dotenv | app_list]
|
||||
defp app_list(_), do: app_list
|
||||
defp app_list, do: [...]
|
||||
```
|
||||
|
||||
#### Reloading the `.env` file
|
||||
|
||||
The `Dotenv.reload!/0` function will reload the variables defined in the `.env` file.
|
||||
|
||||
More examples of the server API usage can be found in [dotenv_app_test.exs](https://github.com/avdi/dotenv_elixir/blob/master/test/dotenv_app_test.exs).
|
||||
|
||||
### Serverless API
|
||||
|
||||
If you would like finer-grained control over when variables are loaded, or would like to inspect them, Dotenv also provides a serverless API for interacting with `.env` files.
|
||||
|
||||
The `load!/1` function loads variables into the process environment, and can be passed a path or list of paths to read from.
|
||||
|
||||
Alternately, `load/1` will return a data structure of the variables read from the `.env` file:
|
||||
|
||||
```elixir
|
||||
iex(1)> Dotenv.load
|
||||
%Dotenv.Env{paths: ["/elixir/dotenv_elixir/.env"],
|
||||
values: %{"APP_TEST_VAR" => "HELLO"}}
|
||||
```
|
||||
|
||||
For further details, see the inline documentation. Usage examples can be found in [dotenv_test.exs](https://github.com/avdi/dotenv_elixir/blob/master/test/dotenv_test.exs).
|
||||
13
deps/dotenv/hex_metadata.config
vendored
Normal file
13
deps/dotenv/hex_metadata.config
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{<<"app">>,<<"dotenv">>}.
|
||||
{<<"build_tools">>,[<<"mix">>]}.
|
||||
{<<"description">>,<<"A port of dotenv to Elixir">>}.
|
||||
{<<"elixir">>,<<"~> 1.0">>}.
|
||||
{<<"files">>,
|
||||
[<<"lib">>,<<"lib/dotenv">>,<<"lib/dotenv/supervisor.ex">>,
|
||||
<<"lib/dotenv/server.ex">>,<<"lib/dotenv/env.ex">>,<<"lib/dotenv.ex">>,
|
||||
<<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>]}.
|
||||
{<<"licenses">>,[<<"MIT">>]}.
|
||||
{<<"links">>,[{<<"github">>,<<"https://github.com/avdi/dotenv_elixir">>}]}.
|
||||
{<<"name">>,<<"dotenv">>}.
|
||||
{<<"requirements">>,[]}.
|
||||
{<<"version">>,<<"3.1.0">>}.
|
||||
235
deps/dotenv/lib/dotenv.ex
vendored
Normal file
235
deps/dotenv/lib/dotenv.ex
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
defmodule Dotenv do
|
||||
@moduledoc """
|
||||
This module implements both an OTP application API and a "serverless" API.
|
||||
|
||||
Server API
|
||||
==========
|
||||
|
||||
Start the application with `start/2` On starting, it will automatically export
|
||||
the environment variables in the default path (`.env`).
|
||||
|
||||
The environment can then be reloaded with `reload!/0` or a specific path
|
||||
or list of paths can be provided to `reload!/1`.
|
||||
|
||||
Serverless API
|
||||
==============
|
||||
|
||||
To use the serverless API, you can either load the environment variables with
|
||||
`load!` (again, optionally passing in a path or list of paths), or you
|
||||
can retrieve the variables without exporting them using `load`.
|
||||
"""
|
||||
|
||||
use Application
|
||||
alias Dotenv.Env
|
||||
|
||||
def start(_type, env_path \\ :automatic) do
|
||||
Dotenv.Supervisor.start_link(env_path)
|
||||
end
|
||||
|
||||
@quotes_pattern ~r/^(['"])(.*)\1$/
|
||||
@pattern ~r/
|
||||
\A
|
||||
(?:export\s+)? # optional export
|
||||
([\w\.]+) # key
|
||||
(?:\s*=\s*|:\s+?) # separator
|
||||
( # optional value begin
|
||||
'(?:\'|[^'])*?' # single quoted value
|
||||
| # or
|
||||
"(?:\"|[^"])*?" # double quoted value
|
||||
| # or
|
||||
[^#\n]+? # unquoted value
|
||||
)? # value end
|
||||
(?:\s*\#.*)? # optional comment
|
||||
\z
|
||||
/x
|
||||
|
||||
# https://regex101.com/r/XrvCwE/1
|
||||
@env_expand_pattern ~r/
|
||||
(?:^|[^\\]) # prevent to expand \\$
|
||||
( # get variable key pattern
|
||||
\$ #
|
||||
(?: #
|
||||
([A-Z0-9_]*[A-Z_]+[A-Z0-9_]*) # get variable key
|
||||
| #
|
||||
(?: #
|
||||
{([A-Z0-9_]*[A-Z_]+[A-Z0-9_]*)} # get variable key between {}
|
||||
) #
|
||||
) #
|
||||
) #
|
||||
/x
|
||||
|
||||
##############################################################################
|
||||
# Server API
|
||||
##############################################################################
|
||||
|
||||
@doc """
|
||||
Calls the server to reload the values in the `.env` file into the
|
||||
system environment.
|
||||
|
||||
This call is asynchronous (`cast`).
|
||||
"""
|
||||
@spec reload!() :: :ok
|
||||
def reload! do
|
||||
:gen_server.cast(:dotenv, :reload!)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Calls the server to reload the values in the file located at `env_path` into
|
||||
the system environment.
|
||||
|
||||
This call is asynchronous (`cast`).
|
||||
"""
|
||||
@spec reload!(any) :: :ok
|
||||
def reload!(env_path) do
|
||||
:gen_server.cast(:dotenv, {:reload!, env_path})
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the current state of the server as a `Dotenv.Env` struct.
|
||||
"""
|
||||
@spec env() :: Env.t()
|
||||
def env do
|
||||
:gen_server.call(:dotenv, :env)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieves the value of the given `key` from the server, or `fallback` if the
|
||||
value is not found.
|
||||
"""
|
||||
@spec get(String.t(), String.t() | nil) :: String.t()
|
||||
def get(key, fallback \\ nil) do
|
||||
:gen_server.call(:dotenv, {:get, key, fallback})
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Serverless API
|
||||
##############################################################################
|
||||
|
||||
@doc """
|
||||
Reads the env files at the provided `env_path` path(s), exports the values into
|
||||
the system environment, and returns them in a `Dotenv.Env` struct.
|
||||
"""
|
||||
def load!(env_path \\ :automatic) do
|
||||
env = load(env_path)
|
||||
System.put_env(env.values)
|
||||
env
|
||||
end
|
||||
|
||||
@doc """
|
||||
Reads the env files at the provided `env_path` path(s) and returns the values in a `Dotenv.Env` struct.
|
||||
"""
|
||||
@spec load(String.t() | :automatic | [String.t()]) :: Env.t()
|
||||
def load(env_path \\ :automatic)
|
||||
|
||||
def load([env_path | env_paths]) do
|
||||
first_env = load(env_path)
|
||||
rest_env = load(env_paths)
|
||||
|
||||
%Env{paths: [env_path | rest_env.paths], values: Map.merge(first_env.values, rest_env.values)}
|
||||
end
|
||||
|
||||
def load([]) do
|
||||
%Env{paths: [], values: Map.new()}
|
||||
end
|
||||
|
||||
def load(env_path) do
|
||||
{env_path, contents} = read_env_file(env_path)
|
||||
values = contents |> parse_contents()
|
||||
%Env{paths: [env_path], values: values}
|
||||
end
|
||||
|
||||
def parse_contents(contents) do
|
||||
values = String.split(contents, "\n")
|
||||
|
||||
values
|
||||
|> Enum.flat_map(&Regex.scan(@pattern, &1))
|
||||
|> trim_quotes_from_values
|
||||
|> Enum.reduce([], &expand_env/2)
|
||||
|> Enum.reduce(Map.new(), &collect_into_map/2)
|
||||
end
|
||||
|
||||
defp collect_into_map([_whole, k, v], env), do: Map.put(env, k, v)
|
||||
defp collect_into_map([_whole, _k], env), do: env
|
||||
|
||||
defp trim_quotes_from_values(values) do
|
||||
values
|
||||
|> Enum.map(fn values ->
|
||||
Enum.map(values, &trim_quotes/1)
|
||||
end)
|
||||
end
|
||||
|
||||
defp trim_quotes(value) do
|
||||
String.replace(value, @quotes_pattern, "\\2")
|
||||
end
|
||||
|
||||
# without value
|
||||
defp expand_env([_whole, _k], acc), do: acc
|
||||
|
||||
defp expand_env([whole, k, v], acc) do
|
||||
matchs = Regex.scan(@env_expand_pattern, v)
|
||||
|
||||
new_value =
|
||||
case Enum.empty?(matchs) do
|
||||
true ->
|
||||
v
|
||||
|
||||
false ->
|
||||
matchs
|
||||
|> Enum.reduce(v, fn [_whole, pattern | keys], v ->
|
||||
v |> replace_env(pattern, keys, acc)
|
||||
end)
|
||||
end
|
||||
|
||||
acc ++ [[whole, k, new_value]]
|
||||
end
|
||||
|
||||
defp replace_env(value, pattern, ["" | keys], env), do: replace_env(value, pattern, keys, env)
|
||||
defp replace_env(value, pattern, [key | _], env), do: replace_env(value, pattern, key, env)
|
||||
|
||||
defp replace_env(value, pattern, key, %Env{} = env) do
|
||||
new_value = env |> Env.get(key) || ""
|
||||
|
||||
pattern
|
||||
|> Regex.escape()
|
||||
|> Regex.compile!()
|
||||
|> Regex.replace(value, new_value)
|
||||
end
|
||||
|
||||
defp replace_env(value, pattern, key, acc) when is_list(acc) do
|
||||
values = acc |> Enum.reduce(Map.new(), &collect_into_map/2)
|
||||
replace_env(value, pattern, key, %Env{values: values})
|
||||
end
|
||||
|
||||
defp replace_env(value, pattern, key, %{} = values) do
|
||||
replace_env(value, pattern, key, %Env{values: values})
|
||||
end
|
||||
|
||||
defp read_env_file(:automatic) do
|
||||
case find_env_path() do
|
||||
{:ok, env_path} -> {env_path, File.read!(env_path)}
|
||||
{:error, _} -> {:none, ""}
|
||||
end
|
||||
end
|
||||
|
||||
defp read_env_file(:none) do
|
||||
{:none, ""}
|
||||
end
|
||||
|
||||
defp read_env_file(env_path) do
|
||||
{env_path, File.read!(env_path)}
|
||||
end
|
||||
|
||||
defp find_env_path do
|
||||
find_env_path(File.cwd!())
|
||||
end
|
||||
|
||||
defp find_env_path(dir) do
|
||||
candidate = Path.join(dir, ".env")
|
||||
|
||||
cond do
|
||||
File.exists?(candidate) -> {:ok, candidate}
|
||||
dir == "/" -> {:error, "No .env found"}
|
||||
true -> find_env_path(Path.dirname(dir))
|
||||
end
|
||||
end
|
||||
end
|
||||
20
deps/dotenv/lib/dotenv/env.ex
vendored
Normal file
20
deps/dotenv/lib/dotenv/env.ex
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
defmodule Dotenv.Env do
|
||||
@type t :: %Dotenv.Env{paths: [String.t()], values: %{String.t() => String.t()}}
|
||||
defstruct paths: [], values: Map.new()
|
||||
|
||||
def path(%Dotenv.Env{paths: paths}) do
|
||||
Enum.join(paths, ":")
|
||||
end
|
||||
|
||||
def get(env, key) do
|
||||
Dotenv.Env.get(env, System.get_env(key), key)
|
||||
end
|
||||
|
||||
def get(%Dotenv.Env{values: values}, fallback, key) when is_function(fallback) do
|
||||
Map.get(values, key, fallback.(key))
|
||||
end
|
||||
|
||||
def get(%Dotenv.Env{values: values}, fallback, key) do
|
||||
Map.get(values, key, fallback)
|
||||
end
|
||||
end
|
||||
29
deps/dotenv/lib/dotenv/server.ex
vendored
Normal file
29
deps/dotenv/lib/dotenv/server.ex
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
defmodule Dotenv.Server do
|
||||
@moduledoc false
|
||||
use GenServer
|
||||
|
||||
def start_link(env_path) do
|
||||
GenServer.start_link(__MODULE__, env_path, name: :dotenv)
|
||||
end
|
||||
|
||||
def init(env_path) do
|
||||
env = Dotenv.load!(env_path)
|
||||
{:ok, env}
|
||||
end
|
||||
|
||||
def handle_cast(:reload!, env) do
|
||||
{:noreply, Dotenv.load!(env.paths)}
|
||||
end
|
||||
|
||||
def handle_cast({:reload!, env_path}, _env) do
|
||||
{:noreply, Dotenv.load!(env_path)}
|
||||
end
|
||||
|
||||
def handle_call(:env, _from, env) do
|
||||
{:reply, env, env}
|
||||
end
|
||||
|
||||
def handle_call({:get, key, fallback}, _from, env) do
|
||||
{:reply, Dotenv.Env.get(env, fallback, key), env}
|
||||
end
|
||||
end
|
||||
13
deps/dotenv/lib/dotenv/supervisor.ex
vendored
Normal file
13
deps/dotenv/lib/dotenv/supervisor.ex
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
defmodule Dotenv.Supervisor do
|
||||
@moduledoc false
|
||||
use Supervisor
|
||||
|
||||
def start_link(env_path \\ :automatic) do
|
||||
Supervisor.start_link(__MODULE__, env_path)
|
||||
end
|
||||
|
||||
def init(env_path) do
|
||||
children = [Supervisor.child_spec({Dotenv.Server, env_path}, [])]
|
||||
Supervisor.init(children, strategy: :one_for_one)
|
||||
end
|
||||
end
|
||||
39
deps/dotenv/mix.exs
vendored
Normal file
39
deps/dotenv/mix.exs
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
defmodule DotenvElixir.Mixfile do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :dotenv,
|
||||
version: "3.1.0",
|
||||
elixir: "~> 1.0",
|
||||
deps: deps(),
|
||||
package: [
|
||||
maintainers: ["Jared Norman"],
|
||||
contributors: [
|
||||
"Avdi Grimm",
|
||||
"David Rouchy",
|
||||
"Jared Norman",
|
||||
"Louis Simoneau",
|
||||
"Michael Bianco"
|
||||
],
|
||||
links: %{github: "https://github.com/avdi/dotenv_elixir"},
|
||||
licenses: ["MIT"]
|
||||
],
|
||||
description: "A port of dotenv to Elixir"
|
||||
]
|
||||
end
|
||||
|
||||
# Configuration for the OTP application
|
||||
def application do
|
||||
[mod: {Dotenv, [:automatic]}]
|
||||
end
|
||||
|
||||
# Returns the list of dependencies in the format:
|
||||
# { :foobar, git: "https://github.com/elixir-lang/foobar.git", tag: "0.1" }
|
||||
#
|
||||
# To specify particular versions, regardless of the tag, do:
|
||||
# { :barbat, "~> 0.1", github: "elixir-lang/barbat.git" }
|
||||
defp deps do
|
||||
[{:ex_doc, ">= 0.0.0", only: :dev}]
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user