Skip to content

Commit

Permalink
Merge pull request #11 from Arkoniak/update_docs
Browse files Browse the repository at this point in the history
Updated docs
  • Loading branch information
Arkoniak authored Apr 21, 2021
2 parents c570e7e + 60d6a36 commit b3e49ac
Show file tree
Hide file tree
Showing 6 changed files with 399 additions and 101 deletions.
115 changes: 14 additions & 101 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| [![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://Arkoniak.github.io/ConfigEnv.jl/stable)[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://Arkoniak.github.io/ConfigEnv.jl/dev) | [![Build](https://github.com/Arkoniak/ConfigEnv.jl/workflows/CI/badge.svg)](https://github.com/Arkoniak/ConfigEnv.jl/actions)[![Coverage](https://codecov.io/gh/Arkoniak/ConfigEnv.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/Arkoniak/ConfigEnv.jl) | [![pkgeval](https://juliahub.com/docs/ConfigEnv/pkgeval.svg)](https://juliahub.com/ui/Packages/ConfigEnv/y83nC)[![version](https://juliahub.com/docs/ConfigEnv/version.svg)](https://juliahub.com/ui/Packages/ConfigEnv/y83nC) |

`ConfigEnv.jl` is an environment configuration package that loads environment variables from a `.env` file into [`ENV`](https://docs.julialang.org/en/latest/manual/environment-variables/) in the same manner as [python-dotenv](https://github.com/theskumar/python-dotenv) library.
`ConfigEnv.jl` is an environment configuration package that loads environment variables from a `.env` file into [`ENV`](https://docs.julialang.org/en/latest/manual/environment-variables/). This package was inspired by [python-dotenv](https://github.com/theskumar/python-dotenv) library and [the Twelve-Factor App](https://12factor.net/config) methodology.

## Installation

`ConfigEnv.jl` is a registered package, so it can be installed with

```julia
julia> Pkg.add("ConfigEnv")
julia> using Pkg; Pkg.add("ConfigEnv")
```

or
Expand All @@ -26,14 +26,12 @@ v1.6> add ConfigEnv
Create a `.env` file in your project. You can add environment-specific variables using the rule `NAME=VALUE`.
For example:

```dosini
```
#.env file
DB_HOST=127.0.0.1
DB_USER=foo
DB_PASS=123456
USER = foo
PASSWORD = bar
```

After that you can use it in your application
Usually it is a good idea to put this file into your `.gitignore` file, so secrets wouldn't leak to the public space. After that you can use it in your application

```julia
using ConfigEnv
Expand All @@ -44,100 +42,15 @@ dotenv() # loads environment variables from .env
This way `ENV` obtains key values pairs you set in your `.env` file.

```julia
julia> ENV["DB_PASS"]
"123456"
```

## Configuration

Main command is `dotenv` which reads your .env file, parse the content, stores it to
[`ENV`](https://docs.julialang.org/en/latest/manual/environment-variables/),
and finally return a `EnvProxyDict`.

```julia
julia> cfg = dotenv()

julia> println(cfg)
ConfigEnv.EnvProxyDict(Dict("FOO" => "BAR"))
julia> ENV["PASSWORD"]
"bar"
```

`EnvProxyDict` acts as a proxy to `ENV` dictionary, if `key` is not found in `EnvProxyDict` it will try to return value from `ENV`.
## Features

```julia
julia> ENV["XYZ"] = "ABC"
julia> cfg = dotenv()
julia> println(cfg)
ConfigEnv.EnvProxyDict(Dict("FOO" => "BAR"))
julia> cfg["FOO"]
"BAR"
julia> cfg["XYZ"]
"ABC"
```

### Options

#### Paths

By default `dotenv` use local `.env` file, but you can specify a custom path for your `.env` file.

```julia
dotenv("custom.env") # Loads `custom.env` file
```

You can supply more than one configuration file

```julia
dotenv("custom1.env", "custom2.env")
```

Alternatively, you can combine different configuration files together using `merge` function or multiplication sign `*`

```julia
cfg1 = dotenv("custom1.env")
cfg2 = dotenv("custom2.env")

cfg = merge(cfg1, cfg2)

# or equivalently

cfg = cfg1 * cfg2
```
if duplicate keys encountered, then values from the rightmost dictionary is used.

Take note that `dotenv` function replace previous `ENV` environment variables by default. If you want to keep original version of `ENV` you should use `overwrite` argument

```julia
ENV["FOO"] = "BAR"
cfg = dotenv(overwrite = false)

cfg["FOO"] # "BAZ"
ENV["FOO"] # "BAR"
```

Since many dotenv packages uses another default setting when environment is not overwritten, function `dotenvx` was introduced. This function is just an alias to `dotenv(overwrite = false)`, but it can be more convenient to use.

```julia
ENV["FOO"] = "BAR"
cfg = dotenvx() # Same as `dotenv(overwrite = false)`

cfg["FOO"] # "BAZ"
ENV["FOO"] # "BAR"
```
`ConfigEnv.jl` provides following features in order to make environment configuration more flexible

### Rules

You can write your `.env` file using the following rules:

- `FOO = BAR` becomes `ENV["FOO"] = "BAR"`
- empty lines are skipped
- `#` are comments
- empty content is treated as an empty string, i.e. `EMPTY=` becomes `ENV["EMPTY"] = ""`
- external single and double quotes are removed, i.e. `SINGLE_QUOTE='quoted'` becomes `ENV["SINGLE_QUOTE"] = "quoted"`
- inside double quotes, new lines are expanded, i.e.
```
MULTILINE = "new
line"
```
becomes `ENV["MULTILINE"] = "new\nline"`
- inner quotes are automatically escaped, i.e. `JSON={"foo": "bar"}` becomes `ENV["JSON"] = "{\"foo\": \"bar\"}"`
- extra spaces are removed from both ends of the value, i.e. `FOO=" some value "` becomes `ENV["FOO"] = "some value"`
- load data from configuration files to `ENV` in overwriting and non overwriting mode;
- reading data from `String` and `IO` objects;
- merging data from different configuration files;
- templating variables with an arbitrary templating depth and introspection tools for discovering unresolved templates and circular dependencies.
2 changes: 2 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ makedocs(;
),
pages=[
"Home" => "index.md",
"Usage" => "usage.md"
"Examples" => "scenarios.md"
],
)

Expand Down
17 changes: 17 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@ CurrentModule = ConfigEnv
```

# ConfigEnv
`ConfigEnv.jl` is an environment configuration package that loads environment variables from a `.env` file into [`ENV`](https://docs.julialang.org/en/latest/manual/environment-variables/). This package was inspired by [python-dotenv](https://github.com/theskumar/python-dotenv) library and [the Twelve-Factor App](https://12factor.net/config) methodology.

## Installation

`ConfigEnv.jl` is a registered package, so it can be installed with

```julia
julia> using Pkg; Pkg.add("ConfigEnv")
```

or

```julia
# switch to pkg mode
julia> ]
v1.6> add ConfigEnv
```

```@index
```
Expand Down
136 changes: 136 additions & 0 deletions docs/src/scenarios.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
```@meta
CurrentModule = ConfigEnv
```

# Examples

In this section you can find different scenarios of various complexity, which shows how to utilize features of `ConfigEnv.jl`.

## Simple ENV manipulations

If the package that you are using provides support for environmental variables, than all you have to do is write proper `.env` and populate `ENV` with `dotenv` function.

For example, here is how one can setup and use `Telegram.jl` functions

Configure `.env`
```
# .env
TELEGRAM_BOT_TOKEN = <YOUR TELEGRAM BOT TOKEN>
TELEGRAM_BOT_CHAT_ID = <YOUR TELEGRAM CHAT ID>
```

and use it in an application
```julia
using Telegram, Telegram.API
using ConfigEnv

dotenv()

sendMessage(text = "Hello, world!") # uses TELEGRAM_BOT_TOKEN and TELEGRAM_BOT_CHAT_ID
```

## Multifile configuration
One can use merge feature to factor out repeating parts of environment configuration. For example, one can use the following file file structure

```
/
.root_env
dir1/
.env
file1.jl
dir2/
.env
file2.jl
```

In this case `.root_env` can contain
```
HOST = localhost
PORT = 1234
```

and `.env` in `dir1` can be
```
USER = FOO
PASSWORD = BAR
```

Then `file1.jl` can use the following construction
```julia
using ConfigEnv

dotenv(".env", "../.root_env")
```

As a result, all four variables are set in the environment. By using different user/password in `.env` of `dir2` one can obtain directory dependent environments without repeating `HOST` and `PORT` values.

## Templating configuration

Expanding on the previous example, imagine that you have different user/password pairs for production and testing environments. Than you can organise your `.env` files as follows

```
# .root_env
USER_PRODUCTION = FOO
USER_TEST = TEST
PASSWORD_PRODUCTION = BAR
PASSWORD_TEST = 123
USER = ${USER_${ENVIR}}
PASSWORD = ${PASSWORD_${ENVIR}}
```

```
# dir1/.env
ENVIR = PRODUCTION
```
Then in your `file1.jl` you can get the following
```julia
using ConfigEnv

dotenv("../.root_env", ".env")

ENV["USER"] # FOO
ENV["PASSWORD"] # BAR
```

So variables `USER` and `PASWORD` will be set according to the value of `ENVIR`.

## Using `IO` objects

One can even go further and use templates together with `IO` objects to dynamically update application configuration. For example, if application looks like
```
/
.env
app.jl
```

with `.env` similar to the previous example
```
USER_PRODUCTION = FOO
USER_TEST = TEST
PASSWORD_PRODUCTION = BAR
PASSWORD_TEST = 123
USER = ${USER_${ENVIR}}
PASSWORD = ${PASSWORD_${ENVIR}}
```

and there is a `.env`
```
ENVIR = PRODUCTION
```
located on some server in local network, then one can use the following construction in `app.jl`

```julia
using ConfigEnv
using HTTP

dotenv(IOBuffer(HTTP.get("http://127.0.0.1/.env").body), ".env")

ENV["USER"] # FOO
ENV["PASSWORD"] # BAR
```

So it is possible to change application mode from `production` to `test`, just by changing value of the `.env` file on server.
Loading

0 comments on commit b3e49ac

Please sign in to comment.