dotenv

package module
v1.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 14, 2023 License: MIT Imports: 5 Imported by: 2

README

Go high level wrapper around godotenv

Go Go Reference

It allows to load one or multiple .env file(s) according to original rules. It searches for .env file(s) in current and parent dirs, until it find at least one of them.

Instalation

go get https://github.com/dsh2dsh/expx-dotenv

Usage

env := dotenv.New()
if err := env.Load(); err != nil {
	log.Fatalf("error loading .env files: %v", err)
}

or with chained calls:

env := dotenv.New()
if err := env.WithDepth(1).WithEnvSuffix("test").Load(); err != nil {
	log.Fatalf("error loading .env files: %v", err)
}

Load environment variables and parse them into a struct:

env := dotenv.New()
cfg := struct {
		SomeOpt string `env:"ENV_VAR1"`
}{
		SomeOpt: "some default value, because we don't have .env file(s)",
}
if err := env.LoadTo(&cfg); err != nil {
		log.Fatalf("error loading .env files: %v", err)
}
fmt.Println(cfg.SomeOpt)
// Output: some default value, because we don't have .env file(s)

Documentation

Overview

Package dotenv is a high level wrapper around godotenv. It allows to load one or multiple .env file(s) according to original rules. It searches for .env file(s) in current and parent dirs, until it find at least one of them.

Example
package main

import (
	"log"

	dotenv "github.com/dsh2dsh/expx-dotenv"
)

func main() {
	if err := dotenv.New().Load(); err != nil {
		log.Fatalf("error loading .env files: %v", err)
	}
}
Output:

Example (ChainedCalls)
package main

import (
	"log"

	dotenv "github.com/dsh2dsh/expx-dotenv"
)

func main() {
	if err := dotenv.New().WithDepth(1).WithEnvSuffix("test").Load(); err != nil {
		log.Fatalf("error loading .env files: %v", err)
	}
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Load added in v1.3.2

func Load(callbacks ...func() error) error

Load loads .env files using default Loader. See Loader.Load for details about callbacks.

Types

type Filer added in v1.3.0

type Filer interface {
	// Stat returns a FileInfo describing the named file, see [os.Stat].
	Stat(name string) (os.FileInfo, error)
}

Filler implements access to OS functions

type Loader

type Loader struct {
	// contains filtered or unexported fields
}

Loader is a loader of .env files. Don't create it directly, use New instead.

func New

func New(opts ...Option) *Loader

New creates and returns an instance of .env loader Loader. By default it searches for .env file(s) until it reaches of the root or any parent dir where go.mod file exists.

Creation time options can be changed by opts.

func (*Loader) FileExistsInDir

func (self *Loader) FileExistsInDir(dirName, fname string) (bool, error)

FileExistsInDir checks if file named fname exists in dir named dirName and returns true, if it exists, or false.

May be useful in a callback, configured by Loader.WithRootCallback.

func (*Loader) Load

func (self *Loader) Load(callbacks ...func() error) error

Load loads .env files in current dir if any of them exists. If nothing was found it tries parent dir and parent of parent dir and so on, until it'll find any of .env files or will reach any of configured condition:

  1. Visited dir is at level configured by Loader.WithDepth, where level 1 is current dir, level 2 is parent dir and so on.
  2. Visited dir is a root dir configured by Loader.WithRootDir.
  3. Visited dir has any of file with names configured by Loader.WithRootFiles.
  4. A callback function was configured by Loader.WithRootCallback and that function returned true for visited dir.

If name of environment wasn't configured by Loader.WithEnvVarName or Loader.WithEnvSuffix, Load is looking for:

  1. env.local
  2. .env

If name of environment was configured, "production" for instance, it's looking for:

  1. .env.production.local
  2. .env.local
  3. .env.production
  4. .env

Load uses godotenv.Load and according to how it works any already defined env variable can't be redefined by next .env file and has priority. So if variable "A" defined in .env.local file, it can't be redefined by variable "A" from .env file. Or if env variable "A" somehow defined before calling Load, it keeps its value and can't be redefined by .env files.

After succesfull loading of .env file(s) it calls functions from cbs one by one. It stops calling callbacks after first error. Here an example of using env to parse env vars into a struct:

cfg := struct {
	SomeOpt string `env:"ENV_VAR1"`
}{
	SomeOpt: "some default value, because we don't have .env file(s)",
}

err := dotenv.New().Load(func() error {
	return env.Parse(&cfg)
})
if err != nil {
	log.Fatalf("error loading .env files: %v", err)
}

func (*Loader) WithDepth

func (self *Loader) WithDepth(n int) *Loader

WithDepth configures Loader.Load don't go up deeper and stop searching for .env files at n level. Current dir has n == 1, first parent dir has n == 2 and so on.

func (*Loader) WithEnvSuffix

func (self *Loader) WithEnvSuffix(s string) *Loader

WithEnvSuffix directly sets name of current environment to s. See Loader.WithEnvVarName above for details.

func (*Loader) WithEnvVarName

func (self *Loader) WithEnvVarName(s string) *Loader

WithEnvVarName reads name of current environment from s environment variable and configures Loader.Load for searching and loading of .env.CURENV* files. For instance with s == "production" it'll search also for ".env.production.local" and ".env.production". With s == "test" - ".env.test.local" and ".env.test". And so on.

This example configures env to read environment name from "ENV" environment variable:

env := dotenv.New()
env.WithEnvVarName("ENV")

So if "ENV" environment variable contains "test", next call to Loader.Load will try to load ".env.test*" files. See Loader.Load for details.

func (*Loader) WithRootCallback

func (self *Loader) WithRootCallback(fn func(path string) (bool, error),
) *Loader

WithRootCallback configures Loader.Load to call fn function for every dir it visits. It passes absolute path of current dir as path param and expects two return values:

  1. true means stop at this dir
  2. any error

Loader.FileExistsInDir may be useful in here.

Example
package main

import (
	dotenv "github.com/dsh2dsh/expx-dotenv"
)

func main() {
	env := dotenv.New()
	env.WithRootCallback(func(path string) (bool, error) {
		return env.FileExistsInDir(path, ".git") //nolint: wrapcheck
	})
}
Output:

func (*Loader) WithRootDir

func (self *Loader) WithRootDir(path string) *Loader

WithRootDir configures Loader.Load to stop at path dir and don't go up.

Example
package main

import (
	"os"

	dotenv "github.com/dsh2dsh/expx-dotenv"
)

func main() {
	// "ENV_ROOT" environment variable contains name of current environment.
	dotenv.New().WithRootDir(os.Getenv("ENV_ROOT"))
}
Output:

func (*Loader) WithRootFiles

func (self *Loader) WithRootFiles(fnames ...string) *Loader

WithRootFiles configures Loader.Load to stop at current dir or any parent dir, which contains any of file (or dir) with name from fnames list.

Example
package main

import (
	dotenv "github.com/dsh2dsh/expx-dotenv"
)

func main() {
	// stop at dir, which contains ".git"
	dotenv.New().WithRootFiles(".git")
}
Output:

type Option added in v1.3.0

type Option func(l *Loader)

Option configures Loader somehow

func WithFiler added in v1.3.0

func WithFiler(f Filer) Option

WithFiler configures Loader with custom implementation of Filer interface.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL