tty-config 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +103 -18
  4. data/lib/tty/config.rb +66 -129
  5. data/lib/tty/config/dependency_loader.rb +55 -0
  6. data/lib/tty/config/generator.rb +57 -0
  7. data/lib/tty/config/marshaller.rb +56 -0
  8. data/lib/tty/config/marshaller_registry.rb +43 -0
  9. data/lib/tty/config/marshallers.rb +35 -0
  10. data/lib/tty/config/marshallers/hcl_marshaller.rb +25 -0
  11. data/lib/tty/config/marshallers/ini_marshaller.rb +28 -0
  12. data/lib/tty/config/marshallers/java_props_marshaller.rb +25 -0
  13. data/lib/tty/config/marshallers/json_marshaller.rb +25 -0
  14. data/lib/tty/config/marshallers/toml_marshaller.rb +25 -0
  15. data/lib/tty/config/marshallers/yaml_marshaller.rb +29 -0
  16. data/lib/tty/config/version.rb +1 -1
  17. metadata +54 -32
  18. data/Rakefile +0 -8
  19. data/bin/console +0 -14
  20. data/bin/setup +0 -8
  21. data/spec/spec_helper.rb +0 -54
  22. data/spec/unit/alias_setting_spec.rb +0 -72
  23. data/spec/unit/append_spec.rb +0 -26
  24. data/spec/unit/autoload_env_spec.rb +0 -62
  25. data/spec/unit/delete_spec.rb +0 -22
  26. data/spec/unit/exist_spec.rb +0 -24
  27. data/spec/unit/fetch_spec.rb +0 -45
  28. data/spec/unit/generate_spec.rb +0 -70
  29. data/spec/unit/merge_spec.rb +0 -22
  30. data/spec/unit/new_spec.rb +0 -6
  31. data/spec/unit/normalize_hash_spec.rb +0 -21
  32. data/spec/unit/read_spec.rb +0 -118
  33. data/spec/unit/remove_spec.rb +0 -16
  34. data/spec/unit/set_from_env_spec.rb +0 -78
  35. data/spec/unit/set_if_empty_spec.rb +0 -26
  36. data/spec/unit/set_spec.rb +0 -62
  37. data/spec/unit/validate_spec.rb +0 -76
  38. data/spec/unit/write_spec.rb +0 -197
  39. data/tasks/console.rake +0 -11
  40. data/tasks/coverage.rake +0 -11
  41. data/tasks/spec.rake +0 -29
  42. data/tty-config.gemspec +0 -28
@@ -1,21 +0,0 @@
1
- RSpec.describe TTY::Config, '#normalize_hash' do
2
- it "normalizes keys via method to symbols" do
3
- hash = {
4
- "settings" => {
5
- "base" => "USD",
6
- "color" => true,
7
- "exchange" => "CCCAGG"
8
- },
9
- "coins" => ["BTC", "ETH", "TRX", "DASH"]
10
- }
11
-
12
- expect(TTY::Config.normalize_hash(hash)).to eq({
13
- settings: {
14
- base: "USD",
15
- color: true,
16
- exchange: "CCCAGG"
17
- },
18
- coins: ["BTC", "ETH", "TRX", "DASH"]
19
- })
20
- end
21
- end
@@ -1,118 +0,0 @@
1
- RSpec.describe TTY::Config, '#read' do
2
- it "read from an empty file" do
3
- file = fixtures_path('empty.yml')
4
- config = TTY::Config.new
5
-
6
- config.read(file)
7
-
8
- expect(config.to_hash).to eq({})
9
- end
10
-
11
- it "reads from a specified file" do
12
- file = fixtures_path('investments.yml')
13
- config = TTY::Config.new
14
-
15
- config.read(file)
16
-
17
- expect(config.fetch(:settings, :base)).to eq('USD')
18
- end
19
-
20
- it "searched for a file to read from" do
21
- config = TTY::Config.new
22
- config.filename = 'investments'
23
- config.append_path(fixtures_path)
24
-
25
- config.read
26
-
27
- expect(config.fetch(:settings, :base)).to eq('USD')
28
- end
29
-
30
- it "reads from a specified file and merges with defaults" do
31
- file = fixtures_path('investments.yml')
32
- config = TTY::Config.new
33
- config.set(:settings, :base, value: 'EUR')
34
- config.set(:settings, :top, value: 50)
35
-
36
- config.read(file)
37
-
38
- expect(config.fetch(:settings, :base)).to eq('USD')
39
- expect(config.fetch(:settings, :exchange)).to eq('CCCAGG')
40
- expect(config.fetch(:settings, :top)).to eq(50)
41
- end
42
-
43
- it "reads a json format" do
44
- file = fixtures_path('investments.json')
45
- config = TTY::Config.new
46
-
47
- config.read(file)
48
-
49
- expect(config.filename).to eq('investments')
50
- expect(config.extname).to eq('.json')
51
- expect(config.fetch(:settings, :base)).to eq('USD')
52
- expect(config.fetch(:coins)).to eq(["BTC", "ETH", "TRX", "DASH"])
53
- end
54
-
55
- it "reads a toml format" do
56
- file = fixtures_path('investments.toml')
57
- config = TTY::Config.new
58
-
59
- config.read(file)
60
-
61
- expect(config.filename).to eq('investments')
62
- expect(config.extname).to eq('.toml')
63
- expect(config.fetch(:settings, :base)).to eq('USD')
64
- expect(config.fetch(:coins)).to eq(["BTC", "ETH", "TRX", "DASH"])
65
- end
66
-
67
- it "reads an ini format" do
68
- file = fixtures_path('investments.ini')
69
- config = TTY::Config.new
70
-
71
- config.read(file)
72
-
73
- expect(config.filename).to eq('investments')
74
- expect(config.extname).to eq('.ini')
75
- expect(config.fetch(:settings, :base)).to eq('USD')
76
- expect(config.fetch(:coins).split(',')).to eq(["BTC", "ETH", "TRX", "DASH"])
77
- end
78
-
79
- it "reads custom format" do
80
- file = fixtures_path('.env')
81
- config = TTY::Config.new
82
-
83
- config.read(file, format: :ini)
84
-
85
- expect(config.filename).to eq('.env')
86
- expect(config.extname).to eq('')
87
- expect(config.fetch(:settings, :base)).to eq('USD')
88
- expect(config.fetch(:coins).split(',')).to eq(["BTC", "ETH", "TRX", "DASH"])
89
- end
90
-
91
- it "fails to find a file to read" do
92
- config = TTY::Config.new
93
- expect {
94
- config.read
95
- }.to raise_error(TTY::Config::ReadError,
96
- "No file found to read configuration from!")
97
- end
98
-
99
- it "fails to read a file" do
100
- config = TTY::Config.new
101
- file = fixtures_path('unknown.yml')
102
-
103
- expect {
104
- config.read(file)
105
- }.to raise_error(TTY::Config::ReadError,
106
- "Configuration file `#{file}` does not exist!")
107
- end
108
-
109
- it "fails to load dependency for reading file format" do
110
- config = TTY::Config.new
111
- file = fixtures_path('investments.yml')
112
- allow(config).to receive(:require).with('yaml').and_raise(LoadError)
113
-
114
- expect {
115
- config.read(file)
116
- }.to raise_error(TTY::Config::ReadError, "Gem `yaml` is missing. Please install it to read .yml configuration format.")
117
- end
118
- end
@@ -1,16 +0,0 @@
1
- RSpec.describe TTY::Config, '#remove' do
2
- it "removes a value from a key" do
3
- config = TTY::Config.new
4
- config.set(:values) { [:foo, :bar] }
5
- values = config.remove(:bar, from: :values)
6
- expect(values).to eq([:foo])
7
- expect(config.fetch(:values)).to eq([:foo])
8
- end
9
-
10
- it "removes multiple values from a nested key" do
11
- config = TTY::Config.new
12
- config.set(:foo, :bar, :baz) { [1,2,3,4] }
13
- config.remove(2,4, from: [:foo, :bar, :baz])
14
- expect(config.fetch(:foo, :bar, :baz)).to eq([1,3])
15
- end
16
- end
@@ -1,78 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Config, '#set_from_env' do
4
- it "fetches env variables" do
5
- allow(ENV).to receive(:[]).with('HOST').and_return('localhost')
6
- allow(ENV).to receive(:[]).with('PORT').and_return('7727')
7
-
8
- config = TTY::Config.new
9
- config.set_from_env(:host)
10
- config.set_from_env(:port)
11
-
12
- expect(config.fetch(:host)).to eq('localhost')
13
- expect(config.fetch(:port)).to eq('7727')
14
- end
15
-
16
- it "fetches multipart env variables" do
17
- allow(ENV).to receive(:[]).with('FOO_BAR_BAZ').and_return('1')
18
- config = TTY::Config.new
19
- config.set_from_env(:foo_bar_baz)
20
-
21
- expect(config.fetch(:foo_bar_baz)).to eq('1')
22
- end
23
-
24
- it "prefixes env variables" do
25
- allow(ENV).to receive(:[]).with('MYTOOL_HOST').and_return('localhost')
26
- allow(ENV).to receive(:[]).with('MYTOOL_PORT').and_return('7727')
27
-
28
- config = TTY::Config.new
29
- config.env_prefix = 'mytool'
30
- config.set_from_env(:host)
31
- config.set_from_env(:port)
32
-
33
- expect(config.fetch(:host)).to eq('localhost')
34
- expect(config.fetch(:port)).to eq('7727')
35
- end
36
-
37
- it "allows to set env vars for deeply nested keys" do
38
- allow(ENV).to receive(:[]).with('HOST').and_return('localhost')
39
-
40
- config = TTY::Config.new
41
- config.set_from_env(:foo, :bar) { "HOST" }
42
-
43
- expect(config.fetch(:foo, :bar)).to eq('localhost')
44
- end
45
-
46
- it "allows to set env vars with prefix for deeply nested keys" do
47
- allow(ENV).to receive(:[]).with('MYTOOL_HOST').and_return('localhost')
48
-
49
- config = TTY::Config.new
50
- config.env_prefix = 'mytool'
51
- config.set_from_env(:foo, :bar) { "HOST" }
52
-
53
- expect(config.fetch(:foo, :bar)).to eq('localhost')
54
- end
55
-
56
- it "allows to set env vars for deeply nested keys as string" do
57
- allow(ENV).to receive(:[]).with('HOST').and_return('localhost')
58
-
59
- config = TTY::Config.new
60
- config.set_from_env('foo.bar') { "HOST" }
61
-
62
- expect(config.fetch(:foo, :bar)).to eq('localhost')
63
- end
64
-
65
- it "fails if env var is not specified for deeply nested keys as string" do
66
- config = TTY::Config.new
67
- expect {
68
- config.set_from_env('foo.bar')
69
- }.to raise_error(ArgumentError, 'Need to set env var in block')
70
- end
71
-
72
- it "fails if env var is not specified for deeply nested keys" do
73
- config = TTY::Config.new
74
- expect {
75
- config.set_from_env(:foo, :bar)
76
- }.to raise_error(ArgumentError, 'Need to set env var in block')
77
- end
78
- end
@@ -1,26 +0,0 @@
1
- RSpec.describe TTY::Config, '#set_if_empty' do
2
- it "sets value for empty" do
3
- config = TTY::Config.new
4
- config.set_if_empty(:foo, value: :bar)
5
- expect(config.fetch(:foo)).to eq(:bar)
6
- end
7
-
8
- it "sets value for empty deeply nested key" do
9
- config = TTY::Config.new({foo: {}})
10
- config.set_if_empty(:foo, :bar, :baz, value: 2)
11
- expect(config.fetch(:foo, :bar, :baz)).to eq(2)
12
- end
13
-
14
- it "sets value for a nested key as string delimited by dot" do
15
- config = TTY::Config.new
16
- config.set_if_empty("foo.bar.baz", value: 1)
17
- expect(config.fetch('foo', 'bar', 'baz')).to eq(1)
18
- end
19
-
20
- it "doesn't override existing value" do
21
- config = TTY::Config.new
22
- config.set(:foo, value: 1)
23
- config.set_if_empty(:foo, value: 2)
24
- expect(config.fetch(:foo)).to eq(1)
25
- end
26
- end
@@ -1,62 +0,0 @@
1
- RSpec.describe TTY::Config, '#set' do
2
- it "sets value" do
3
- config = TTY::Config.new
4
- config.set(:foo, value: :bar)
5
- expect(config.fetch(:foo)).to eq(:bar)
6
- end
7
-
8
- it "sets value as block" do
9
- config = TTY::Config.new
10
- config.set(:foo) { "bar" }
11
- expect(config.fetch(:foo)).to eq("bar")
12
- end
13
-
14
- it "sets value for deep ensted key" do
15
- config = TTY::Config.new
16
- value = config.set(:foo, :bar, :baz, value: 2)
17
- expect(value).to eq(2)
18
- expect(config.fetch(:foo, :bar, :baz)).to eq(2)
19
- end
20
-
21
- it "sets value as block for deep ensted key" do
22
- config = TTY::Config.new
23
- value = config.set(:foo, :bar, :baz) { 2 }
24
- expect(value.call).to eq(2)
25
- expect(config.fetch(:foo, :bar, :baz)).to eq(2)
26
- end
27
-
28
- it "sets value for deep nested string key delimited by ." do
29
- config = TTY::Config.new
30
- value = config.set("foo.bar.baz", value: 2)
31
- expect(value).to eq(2)
32
- expect(config.fetch('foo', 'bar', 'baz')).to eq(2)
33
- end
34
-
35
- it "sets value as block for deep nested string key delimited by ." do
36
- config = TTY::Config.new
37
- value = config.set("foo.bar.baz") { 2 }
38
- expect(value.call).to eq(2)
39
- expect(config.fetch('foo', 'bar', 'baz')).to eq(2)
40
- end
41
-
42
- it "overrides existing value" do
43
- config = TTY::Config.new({foo: {bar: 1}})
44
- expect(config.fetch(:foo, :bar)).to eq(1)
45
- config.set(:foo, :bar) { 2 }
46
- expect(config.fetch(:foo, :bar)).to eq(2)
47
- end
48
-
49
- it "raises an exception when value & block provided" do
50
- config = TTY::Config.new
51
- expect {
52
- config.set(:foo, value: :bar) { :baz }
53
- }.to raise_error(ArgumentError, "Can't set both value and block")
54
- end
55
-
56
- it "raises an exception when no value or block provided" do
57
- config = TTY::Config.new
58
- expect {
59
- config.set(:foo, :bar, 2)
60
- }.to raise_error(ArgumentError, "Need to set either value or block")
61
- end
62
- end
@@ -1,76 +0,0 @@
1
- RSpec.describe TTY::Config, '#validate' do
2
- let(:validation) {
3
- -> (key, value) do
4
- unless value.is_a?(Integer)
5
- raise TTY::Config::ValidationError, "Failed validation for key=#{key}"
6
- end
7
- end
8
- }
9
-
10
- it "validates string value successfully" do
11
- config = TTY::Config.new
12
- config.validate(:foo, :bar, &validation)
13
- config.set(:foo, :bar, value: 2)
14
- expect(config.fetch(:foo, :bar)).to eq(2)
15
- end
16
-
17
- it "validates a proc value successfully" do
18
- config = TTY::Config.new
19
- config.validate(:foo, :bar, &validation)
20
- config.set(:foo, :bar, value: -> { 2 })
21
- expect(config.fetch(:foo, :bar)).to eq(2)
22
- end
23
-
24
- it "validates a block value successfully" do
25
- config = TTY::Config.new
26
- config.validate(:foo, :bar, &validation)
27
- config.set(:foo, :bar) { 2 }
28
- expect(config.fetch(:foo, :bar)).to eq(2)
29
- end
30
-
31
- it "raises an error when set value fails validation" do
32
- config = TTY::Config.new
33
- config.validate(:foo, :bar, &validation)
34
- expect {
35
- config.set(:foo, :bar, value: '2')
36
- }.to raise_error(TTY::Config::ValidationError,
37
- 'Failed validation for key=foo.bar')
38
- end
39
-
40
- it "raises an error when set value as a proc fails validation" do
41
- config = TTY::Config.new
42
- config.validate(:foo, :bar, &validation)
43
- config.set(:foo, :bar, value: -> { '2' })
44
- expect {
45
- config.fetch(:foo, :bar)
46
- }.to raise_error(TTY::Config::ValidationError,
47
- 'Failed validation for key=foo.bar')
48
- end
49
-
50
- it "raises an eror when ste value as a block fails validation" do
51
- config = TTY::Config.new
52
- config.validate(:foo, :bar, &validation)
53
- config.set(:foo, :bar) { '2' }
54
- expect {
55
- config.fetch(:foo, :bar)
56
- }.to raise_error(TTY::Config::ValidationError,
57
- 'Failed validation for key=foo.bar')
58
- end
59
-
60
- it "applies multiple validations" do
61
- config = TTY::Config.new
62
- config.validate(:foo, :bar) do |key, val|
63
- unless val.is_a?(Integer)
64
- raise TTY::Config::ValidationError, 'Not integer'
65
- end
66
- end
67
- config.validate(:foo, :bar) do |key, val|
68
- unless val > 100
69
- raise TTY::Config::ValidationError , 'Value out of range'
70
- end
71
- end
72
- expect {
73
- config.set(:foo, :bar, value: 99)
74
- }.to raise_error(TTY::Config::ValidationError, 'Value out of range')
75
- end
76
- end
@@ -1,197 +0,0 @@
1
- RSpec.describe TTY::Config, '#write', type: :cli do
2
- it "writes configuration to a specified file" do
3
- config = TTY::Config.new
4
- config.set(:settings, :base, value: 'USD')
5
- config.set(:settings, :exchange, value: 'CCCAGG')
6
- config.set(:coins, value: ['BTC', 'TRX', 'DASH'])
7
- file = tmp_path('config.yml')
8
-
9
- config.write(file)
10
-
11
- expect(::File.read(file)).to eq <<-EOS
12
- ---
13
- settings:
14
- base: USD
15
- exchange: CCCAGG
16
- coins:
17
- - BTC
18
- - TRX
19
- - DASH
20
- EOS
21
- end
22
-
23
- it "writes by default to the current directory" do
24
- config = TTY::Config.new
25
- config.set('settings', 'base', value: 'USD')
26
- config.set('settings', 'exchange', value: 'CCCAGG')
27
- config.set('coins', value: ['BTC', 'TRX', 'DASH'])
28
-
29
- config.write
30
-
31
- file = dir_path('config.yml')
32
- expect(::File.read(file)).to eq <<-EOS
33
- ---
34
- settings:
35
- base: USD
36
- exchange: CCCAGG
37
- coins:
38
- - BTC
39
- - TRX
40
- - DASH
41
- EOS
42
- FileUtils.rm_rf(file)
43
- end
44
-
45
- it "doesn't override already existing file" do
46
- config = TTY::Config.new
47
- config.set('settings', 'base', value: 'USD')
48
- file = tmp_path('config.yml')
49
-
50
- config.write(file)
51
-
52
- expect {
53
- config.write(file)
54
- }.to raise_error(TTY::Config::WriteError,
55
- "File `#{file}` already exists. Use :force option to overwrite.")
56
- end
57
-
58
- it "allows to overwrite already existing file" do
59
- config = TTY::Config.new
60
- config.set('settings', 'base', value: 'USD')
61
- file = tmp_path('config.yml')
62
-
63
- config.write(file)
64
-
65
- config.write(file, force: true)
66
- end
67
-
68
- it "writes json format" do
69
- config = TTY::Config.new
70
- config.set(:settings, :base, value: 'USD')
71
- config.set(:settings, :exchange, value: 'CCCAGG')
72
- config.set(:coins, value: ['BTC', 'TRX', 'DASH'])
73
- file = tmp_path('config.json')
74
-
75
- config.write(file)
76
-
77
- expect(config.extname).to eq('.json')
78
- expect(::File.read(file)).to eq <<-EOS.chomp
79
- {
80
- "settings": {
81
- "base": "USD",
82
- "exchange": "CCCAGG"
83
- },
84
- "coins": [
85
- "BTC",
86
- "TRX",
87
- "DASH"
88
- ]
89
- }
90
- EOS
91
- end
92
-
93
- it "writes toml format and assigns default filename and extension" do
94
- config = TTY::Config.new
95
- config.set(:settings, :base, value: 'USD')
96
- config.set(:settings, :exchange, value: 'CCCAGG')
97
- config.set(:coins, value: ['BTC', 'TRX', 'DASH'])
98
- file = tmp_path('investments.toml')
99
-
100
- config.write(file)
101
-
102
- expect(config.filename).to eq('investments')
103
- expect(config.extname).to eq('.toml')
104
- expect(::File.read(file)).to eq <<-EOS
105
- coins = ["BTC","TRX","DASH"]
106
-
107
- [settings]
108
- base = "USD"
109
- exchange = "CCCAGG"
110
- EOS
111
- end
112
-
113
- it "allows to change default file extension" do
114
- config = TTY::Config.new
115
- config.filename = 'investments'
116
- config.extname = '.toml'
117
- config.set(:settings, :base, value: 'USD')
118
- config.set(:settings, :exchange, value: 'CCCAGG')
119
- config.set(:coins, value: ['BTC', 'TRX', 'DASH'])
120
-
121
- config.write
122
-
123
- file = dir_path('investments.toml')
124
- expect(::File.read(file)).to eq <<-EOS
125
- coins = ["BTC","TRX","DASH"]
126
-
127
- [settings]
128
- base = "USD"
129
- exchange = "CCCAGG"
130
- EOS
131
- FileUtils.rm_rf(file)
132
- end
133
-
134
- it "writes ini format and assigns default filename and extension" do
135
- config = TTY::Config.new
136
- config.set(:settings, :base, value: 'USD')
137
- config.set(:settings, :exchange, value: 'CCCAGG')
138
- config.set(:coins, value: "BTC,TRX,DASH")
139
- file = tmp_path('investments.ini')
140
-
141
- config.write(file)
142
-
143
- expect(config.filename).to eq('investments')
144
- expect(config.extname).to eq('.ini')
145
- expect(::File.read(file)).to eq <<-EOS
146
- coins = BTC,TRX,DASH
147
-
148
- [settings]
149
- base = USD
150
- exchange = CCCAGG
151
- EOS
152
- end
153
-
154
- it "writes custom format with custom file extension" do
155
- config = TTY::Config.new
156
- config.set(:settings, :base, value: 'USD')
157
- config.set(:settings, :exchange, value: 'CCCAGG')
158
- config.set(:coins, value: ['BTC', 'TRX', 'DASH'])
159
- file = tmp_path('investments.conf')
160
-
161
- config.write(file, format: :yaml)
162
- expect(config.filename).to eq('investments')
163
- expect(config.extname).to eq('.conf')
164
- expect(::File.read(file)).to eq <<-EOS
165
- ---
166
- settings:
167
- base: USD
168
- exchange: CCCAGG
169
- coins:
170
- - BTC
171
- - TRX
172
- - DASH
173
- EOS
174
- end
175
-
176
- it "cannot write unknown file format" do
177
- config = TTY::Config.new
178
- config.set(:settings, :base, value: 'USD')
179
- file = tmp_path('config.txt')
180
-
181
- expect {
182
- config.write(file)
183
- }.to raise_error(TTY::Config::UnsupportedExtError,
184
- "Config file format `.txt` is not supported.")
185
- end
186
-
187
- it "fails to load dependency for writing file format" do
188
- config = TTY::Config.new
189
- file = tmp_path('investments.yml')
190
- allow(config).to receive(:require).with('yaml').and_raise(LoadError)
191
- stub_const("YAML", double(dump: 'ok'))
192
-
193
- expect {
194
- config.write(file)
195
- }.to raise_error(TTY::Config::WriteError, "Gem `yaml` is missing. Please install it to read .yml configuration format.")
196
- end
197
- end