unifig-env 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6dd90ff75c3bdc6a91214a289e1075f3c99c55e77ab6c7cbecc6a972a1e6a933
4
- data.tar.gz: 1865d23646a0377f368880ec973404e2ddc50d467d343f4cb723062f585b363c
3
+ metadata.gz: 4f2d1338c397c1f5c2ceaa7819cb67e06ed6eea4c54e225c8ed398dcc82bc107
4
+ data.tar.gz: 6a8df43fd3c7cab42cea78a768749d5ab83fbc60cc0570397d77efbcf5d09802
5
5
  SHA512:
6
- metadata.gz: 2cd00b09159eb1311ac39de13c259109af5d6b349026f51786eb23b55649a1232cc575573bcb1f85517383e1cf605ad5d577f0786e05c2e3f5c6d539583ca0ef
7
- data.tar.gz: 6f55ca98475a3265c7bd8b88cd8f258960a1844a3b5854a02f10dfa2a277595c9e7032c31ec17a609d12d431bb33c81a74961fd4e5b0c21cacfa29a14390f530
6
+ metadata.gz: febd724191f72d90b8f26d075cb3f939803e0a8f975c3afb4e77836068fd41f5535d31401b697cdd18df986c4736f7c8757d84b6dacb8c70f1deca48cbd4e818
7
+ data.tar.gz: 75208b5aa9ffdac96cd7ab6f4bd91a7afacb7679720ef2fc9654d6331570e0f88f10297127c48ee304c6c892c54e82c6b3f53d14bbf0c7deac596b182ebd80d7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # [0.3.1][] (2022-10-18)
2
+
3
+ ## Added
4
+
5
+ - An `env-file` provider for dotenv (e.g. `.env`) files.
6
+
1
7
  # [0.3.0][] (2022-09-01)
2
8
 
3
9
  ## Changed
@@ -14,6 +20,7 @@
14
20
 
15
21
  Initial release.
16
22
 
23
+ [0.3.1]: https://github.com/AaronLasseigne/unifig-env/compare/v0.3.0...v0.3.1
17
24
  [0.3.0]: https://github.com/AaronLasseigne/unifig-env/compare/v0.2.0...v0.3.0
18
25
  [0.2.0]: https://github.com/AaronLasseigne/unifig-env/compare/v0.1.0...v0.2.0
19
26
  [0.1.0]: https://github.com/AaronLasseigne/unifig-env/compare/v0.0.0...v0.1.0
data/README.md CHANGED
@@ -10,13 +10,13 @@ Adds a provider to support loading environment variables to [Unifig][].
10
10
  Add it to your Gemfile:
11
11
 
12
12
  ``` rb
13
- gem 'unifig-env', '~> 0.3.0'
13
+ gem 'unifig-env', '~> 0.3.1'
14
14
  ```
15
15
 
16
16
  Or install it manually:
17
17
 
18
18
  ``` sh
19
- $ gem install unifig-env --version '~> 0.3.0'
19
+ $ gem install unifig-env --version '~> 0.3.1'
20
20
  ```
21
21
 
22
22
  This project uses [Semantic Versioning][].
@@ -24,6 +24,8 @@ Check out [GitHub releases][] for a detailed list of changes.
24
24
 
25
25
  ## Usage
26
26
 
27
+ ### Environment
28
+
27
29
  Use `env` as your provider or add it to your list of providers:
28
30
 
29
31
  ``` yml
@@ -35,6 +37,27 @@ HOST:
35
37
 
36
38
  This will pull `"HOST"` from `ENV` and add it to Unifig.
37
39
 
40
+ ### Environment File
41
+
42
+ Use `env-file` as your provider or add it to your list of providers:
43
+
44
+ ``` yml
45
+ unifig:
46
+ providers: env-file
47
+ ```
48
+
49
+ By default, it looks for `.env` in the local directory.
50
+ The file can be specified by passing `file` to the configuration.
51
+
52
+ ``` yml
53
+ unifig:
54
+ providers:
55
+ list: env-file
56
+ config:
57
+ env-file:
58
+ file: my.env
59
+ ```
60
+
38
61
  ## Contributing
39
62
 
40
63
  If you want to contribute to Unifig:Env, please read [our contribution guidelines][].
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'strscan'
4
+
5
+ module Unifig
6
+ module Env
7
+ # @private
8
+ module Parser
9
+ Error = Class.new(Unifig::Error)
10
+
11
+ WHITESPACE = /\s*/.freeze
12
+ COMMENT = /\#.*$/.freeze
13
+ EXPORT = /export\s+/.freeze
14
+ KEY = /[^=\s]+/.freeze
15
+ ASSIGNMENT = /\s*=\s*/.freeze
16
+ SINGLE_LINE_VALUE = /\S+/.freeze
17
+ QUOTE = /['"]/.freeze
18
+ TO_END_OF_LINE = /\s*(?:\#.*)?$/.freeze
19
+
20
+ class << self
21
+ def call(file_path)
22
+ content = File.read(file_path)
23
+
24
+ vars = {}
25
+ parser = StringScanner.new(content.strip)
26
+ until parser.eos?
27
+ parser.skip(WHITESPACE)
28
+
29
+ next if parser.skip(COMMENT)
30
+
31
+ parser.skip(EXPORT)
32
+ key = extract!(parser, KEY, 'Missing env key on line %i')
33
+ extract!(parser, ASSIGNMENT, 'Missing env var assignment on line %i')
34
+ quote = parser.scan(QUOTE)
35
+ value =
36
+ if quote
37
+ parser.scan(/.*?#{quote}/m).chop
38
+ else
39
+ parser.scan(SINGLE_LINE_VALUE)
40
+ end
41
+
42
+ extract!(parser, TO_END_OF_LINE, 'Invalid env var value on line %i')
43
+
44
+ vars[key] = value
45
+ end
46
+
47
+ vars
48
+ end
49
+
50
+ private
51
+
52
+ def line(parser)
53
+ parser.string[0...parser.pos].scan(/$/).count
54
+ end
55
+
56
+ def extract!(parser, pattern, error_msg)
57
+ parser.scan(pattern).tap do |match|
58
+ raise Error, error_msg % line(parser) if match.nil?
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Unifig
4
4
  module Env
5
- VERSION = '0.3.0'
5
+ VERSION = '0.3.1'
6
6
  end
7
7
  end
data/lib/unifig/env.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'unifig'
4
+
3
5
  require_relative 'env/version'
6
+ require_relative 'env/parser'
4
7
  require_relative 'providers/env'
8
+ require_relative 'providers/env-file'
5
9
 
6
10
  module Unifig
7
11
  # @private
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unifig
4
+ module Providers
5
+ # @private
6
+ module EnvFile
7
+ PATH = File.join(Dir.pwd, '.env')
8
+ private_constant :PATH
9
+
10
+ class << self
11
+ def name
12
+ :'env-file'
13
+ end
14
+
15
+ def retrieve(var_names, config)
16
+ env_vars = Unifig::Env::Parser.call(config.fetch(:file, PATH))
17
+
18
+ var_names.to_h do |name|
19
+ [name, env_vars[name.to_s]]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -8,7 +8,7 @@ module Unifig
8
8
  :env
9
9
  end
10
10
 
11
- def self.retrieve(var_names)
11
+ def self.retrieve(var_names, _config)
12
12
  var_names.to_h do |name|
13
13
  [name, ::ENV[name.to_s]]
14
14
  end
@@ -0,0 +1,89 @@
1
+ require 'tempfile'
2
+
3
+ RSpec.describe Unifig::Env::Parser do
4
+ describe '.call' do
5
+ let(:file_content) do
6
+ <<~ENV
7
+ # standalone comment
8
+ ONE=1
9
+ export TWO=2
10
+ THREE = 3 # in-line comment
11
+
12
+ MULTI_LINE="
13
+ first
14
+ second
15
+ "
16
+ ENV
17
+ end
18
+ let(:file) do
19
+ file = Tempfile.new('.env', Dir.pwd)
20
+ file.write(file_content)
21
+ file.close
22
+ file
23
+ end
24
+ let(:config) { { file: file.path } }
25
+
26
+ after do
27
+ file.unlink
28
+ end
29
+
30
+ it 'returns a hash representing the env vars loaded from the file' do
31
+ result = described_class.call(file.path)
32
+
33
+ expect(result).to be_an_instance_of(Hash)
34
+ expect(result.keys.size).to be 4
35
+ expect(result['ONE']).to eql '1'
36
+ expect(result['TWO']).to eql '2'
37
+ expect(result['THREE']).to eql '3'
38
+ expect(result['MULTI_LINE']).to eql "\nfirst\nsecond\n"
39
+ end
40
+
41
+ context 'with a missing key' do
42
+ let(:file_content) { '=1' }
43
+
44
+ it 'throws an error' do
45
+ expect do
46
+ described_class.call(file.path)
47
+ end.to raise_error Unifig::Env::Parser::Error, 'Missing env key on line 1'
48
+ end
49
+ end
50
+
51
+ context 'with no equal sign' do
52
+ let(:file_content) { 'ONE' }
53
+
54
+ it 'throws an error' do
55
+ expect do
56
+ described_class.call(file.path)
57
+ end.to raise_error Unifig::Env::Parser::Error, 'Missing env var assignment on line 1'
58
+ end
59
+ end
60
+
61
+ context 'with an invalid value' do
62
+ let(:file_content) { 'ONE=1 2' }
63
+
64
+ it 'throws an error' do
65
+ expect do
66
+ described_class.call(file.path)
67
+ end.to raise_error Unifig::Env::Parser::Error, 'Invalid env var value on line 1'
68
+ end
69
+ end
70
+
71
+ context 'an error later in the file' do
72
+ let(:file_content) do
73
+ <<~ENV
74
+ ONE=1
75
+ TWO=2
76
+
77
+ FOUR=4 invalid
78
+ FIVE=5
79
+ ENV
80
+ end
81
+
82
+ it 'puts the correct line' do
83
+ expect do
84
+ described_class.call(file.path)
85
+ end.to raise_error Unifig::Env::Parser::Error, 'Invalid env var value on line 4'
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,45 @@
1
+ require 'tempfile'
2
+
3
+ RSpec.describe Unifig::Providers::EnvFile do
4
+ describe '.name' do
5
+ it 'returns the provider name' do
6
+ expect(described_class.name).to be :'env-file'
7
+ end
8
+ end
9
+
10
+ describe '.retrieve' do
11
+ let(:file) do
12
+ file = Tempfile.new('.env', Dir.pwd)
13
+ file.write <<~ENV
14
+ # standalone comment
15
+ ONE=1
16
+ export TWO=2
17
+ THREE = 3 # in-line comment
18
+
19
+ MULTI_LINE="
20
+ first
21
+ second
22
+ "
23
+ ENV
24
+ file.close
25
+ file
26
+ end
27
+ let(:config) { { file: file.path } }
28
+
29
+ after do
30
+ file.unlink
31
+ end
32
+
33
+ it 'returns a hash of only the available vars' do
34
+ result = described_class.retrieve(%i[ONE TWO THREE MULTI_LINE INVALID], config)
35
+
36
+ expect(result).to be_an_instance_of(Hash)
37
+ expect(result.keys.size).to be 5
38
+ expect(result[:ONE]).to eql '1'
39
+ expect(result[:TWO]).to eql '2'
40
+ expect(result[:THREE]).to eql '3'
41
+ expect(result[:MULTI_LINE]).to eql "\nfirst\nsecond\n"
42
+ expect(result[:INVALID]).to be_nil
43
+ end
44
+ end
45
+ end
@@ -8,18 +8,18 @@ RSpec.describe Unifig::Providers::Env do
8
8
  describe '.retrieve' do
9
9
  before do
10
10
  allow(ENV).to receive(:[]).and_return(nil)
11
- allow(ENV).to receive(:[]).with('FOO').and_return('foo')
12
- allow(ENV).to receive(:[]).with('BAR').and_return('bar')
11
+ allow(ENV).to receive(:[]).with('ONE').and_return('1')
12
+ allow(ENV).to receive(:[]).with('TWO').and_return('2')
13
13
  end
14
14
 
15
15
  it 'returns a hash of only the available vars' do
16
- result = described_class.retrieve(%i[FOO BAR BAZ])
16
+ result = described_class.retrieve(%i[ONE TWO INVALID], {})
17
17
 
18
18
  expect(result).to be_an_instance_of(Hash)
19
19
  expect(result.keys.size).to be 3
20
- expect(result[:FOO]).to eql 'foo'
21
- expect(result[:BAR]).to eql 'bar'
22
- expect(result[:BAZ]).to be_nil
20
+ expect(result[:ONE]).to eql '1'
21
+ expect(result[:TWO]).to eql '2'
22
+ expect(result[:INVALID]).to be_nil
23
23
  end
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unifig-env
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Lasseigne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-01 00:00:00.000000000 Z
11
+ date: 2022-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: unifig
@@ -36,9 +36,13 @@ files:
36
36
  - LICENSE.txt
37
37
  - README.md
38
38
  - lib/unifig/env.rb
39
+ - lib/unifig/env/parser.rb
39
40
  - lib/unifig/env/version.rb
41
+ - lib/unifig/providers/env-file.rb
40
42
  - lib/unifig/providers/env.rb
41
43
  - spec/spec_helper.rb
44
+ - spec/unifig/env/parser_spec.rb
45
+ - spec/unifig/providers/env-file_spec.rb
42
46
  - spec/unifig/providers/env_spec.rb
43
47
  homepage: https://github.com/AaronLasseigne/unifig-env
44
48
  licenses:
@@ -69,4 +73,6 @@ specification_version: 4
69
73
  summary: Adds a provider to support loading environment variables to Unifig.
70
74
  test_files:
71
75
  - spec/spec_helper.rb
76
+ - spec/unifig/env/parser_spec.rb
77
+ - spec/unifig/providers/env-file_spec.rb
72
78
  - spec/unifig/providers/env_spec.rb