Class: Ace::Core::Molecules::EnvLoader

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/core/molecules/env_loader.rb

Overview

.env file loading and environment variable management

Class Method Summary collapse

Class Method Details

.auto_load(root = Dir.pwd) ⇒ Hash

Find and load .env files in standard locations

Parameters:

  • root (String) (defaults to: Dir.pwd)

    Project root directory

Returns:

  • (Hash)

    Variables that were loaded



89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/ace/core/molecules/env_loader.rb', line 89

def self.auto_load(root = Dir.pwd)
  root = Ace::Support::Fs::Atoms::PathExpander.expand(root)

  # Standard .env file locations in priority order
  env_files = [
    File.join(root, ".env.local"),
    File.join(root, ".env")
  ]

  # Load files that exist
  existing = env_files.select { |f| File.exist?(f) }
  load_multiple(*existing, overwrite: false) unless existing.empty?
end

.load_and_set(filepath, overwrite: true) ⇒ Hash

Load .env file and set environment variables

Parameters:

  • filepath (String)

    Path to .env file

  • overwrite (Boolean) (defaults to: true)

    Whether to overwrite existing vars

Returns:

  • (Hash)

    Variables that were set



33
34
35
36
# File 'lib/ace/core/molecules/env_loader.rb', line 33

def self.load_and_set(filepath, overwrite: true)
  vars = load_file(filepath)
  set_environment(vars, overwrite: overwrite)
end

.load_cascade(search_paths: nil) ⇒ Hash

Load .env files from cascade without setting ENV

Parameters:

  • search_paths (Array<String>, nil) (defaults to: nil)

    Optional search paths

Returns:

  • (Hash)

    Merged variables from all .env files



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/ace/core/molecules/env_loader.rb', line 106

def self.load_cascade(search_paths: nil)
  require_relative "../config_discovery"

  discovery = ConfigDiscovery.new(start_path: search_paths&.first)
  merged_vars = {}

  # Find all .env files in cascade (returns in priority order)
  env_files = discovery.find_all_config_files(".env")

  # Load each file and merge (later files override earlier)
  env_files.reverse_each do |filepath|
    next unless File.exist?(filepath)

    file_vars = load_file(filepath)
    merged_vars.merge!(file_vars) if file_vars && !file_vars.empty?
  end

  merged_vars
end

.load_file(filepath) ⇒ Hash

Load .env file and return parsed variables

Parameters:

  • filepath (String)

    Path to .env file

Returns:

  • (Hash)

    Parsed environment variables

Raises:



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/ace/core/molecules/env_loader.rb', line 16

def self.load_file(filepath)
  filepath = Ace::Support::Fs::Atoms::PathExpander.expand(filepath)

  unless File.exist?(filepath)
    return {}
  end

  content = File.read(filepath)
  Atoms::EnvParser.parse(content)
rescue IOError, SystemCallError => e
  raise EnvParseError, "Failed to read .env file #{filepath}: #{e.message}"
end

.load_multiple(*filepaths, overwrite: true) ⇒ Hash

Load multiple .env files in order

Parameters:

  • filepaths (Array<String>)

    Paths to .env files

  • overwrite (Boolean) (defaults to: true)

    Whether to overwrite existing

Returns:

  • (Hash)

    All variables that were set



75
76
77
78
79
80
81
82
83
84
# File 'lib/ace/core/molecules/env_loader.rb', line 75

def self.load_multiple(*filepaths, overwrite: true)
  all_vars = {}

  filepaths.flatten.each do |filepath|
    vars = load_file(filepath)
    all_vars.merge!(vars) if vars && !vars.empty?
  end

  set_environment(all_vars, overwrite: overwrite)
end

.save_file(vars, filepath) ⇒ Object

Save environment variables to .env file

Parameters:

  • vars (Hash)

    Variables to save

  • filepath (String)

    Path to .env file



59
60
61
62
63
64
65
66
67
68
69
# File 'lib/ace/core/molecules/env_loader.rb', line 59

def self.save_file(vars, filepath)
  content = Atoms::EnvParser.format(vars)

  # Create directory if it doesn't exist
  dir = File.dirname(filepath)
  FileUtils.mkdir_p(dir) unless File.directory?(dir)

  File.write(filepath, content)
rescue IOError, SystemCallError => e
  raise EnvParseError, "Failed to save .env file #{filepath}: #{e.message}"
end

.set_environment(vars, overwrite: true) ⇒ Hash

Set environment variables from hash

Parameters:

  • vars (Hash)

    Variables to set

  • overwrite (Boolean) (defaults to: true)

    Whether to overwrite existing

Returns:

  • (Hash)

    Variables that were actually set



42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/ace/core/molecules/env_loader.rb', line 42

def self.set_environment(vars, overwrite: true)
  set_vars = {}

  vars.each do |key, value|
    next unless Atoms::EnvParser.valid_key?(key)
    next if !overwrite && ENV.key?(key)

    ENV[key] = value.to_s
    set_vars[key] = value
  end

  set_vars
end