env_parser 1.3.3 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +65 -65
- data/docs/EnvParser/AutoregisterFileNotFound.html +1 -1
- data/docs/EnvParser/Error.html +1 -1
- data/docs/EnvParser/TypeAlreadyDefinedError.html +1 -1
- data/docs/EnvParser/Types/BaseTypes.html +1 -1
- data/docs/EnvParser/Types/ChronologyTypes.html +1 -1
- data/docs/EnvParser/Types/InternetTypes.html +1 -1
- data/docs/EnvParser/Types.html +1 -1
- data/docs/EnvParser/UnknownTypeError.html +1 -1
- data/docs/EnvParser/UnparseableAutoregisterSpec.html +1 -1
- data/docs/EnvParser/ValueNotAllowedError.html +1 -1
- data/docs/EnvParser/ValueNotConvertibleError.html +1 -1
- data/docs/EnvParser.html +7 -2
- data/docs/_index.html +1 -1
- data/docs/file.README.html +1 -1
- data/docs/index.html +1 -1
- data/docs/top-level-namespace.html +1 -1
- data/lib/env_parser/types/internet_types.rb +22 -0
- data/lib/env_parser/version.rb +1 -1
- data/lib/env_parser.rb +20 -4
- data/spec/env_parser/types/internet_types_spec.rb +50 -0
- data/spec/env_parser_spec.rb +25 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4106f96ced2bcf4948b4547012b017e8632bf43450e86d9639eaf54aa9802ffb
|
4
|
+
data.tar.gz: c6e54495905a39126f320226a118b6c83405860a8ec502e7711e28ed9ad57de9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fb35a0bee0ec626b5c070e426cd5214ce42e9be4eef861ce922c9ee0366c75dbddfcf9b352ca5c5d5806cd0e35ed25575181e35babf56b4b748260133215d46
|
7
|
+
data.tar.gz: ddc6daa85de95c97f2a914f8ff563c9e6fd128f14ca8566a2af153458a6d782fe73831b60d34b503e7beee00285d069354a216ef5b1b261a5a4072d5fa7930ed
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -16,13 +16,13 @@ Things can get out of control pretty fast, especially as the number of environme
|
|
16
16
|
- If your project uses [Bundler](https://github.com/bundler/bundler):
|
17
17
|
- Add one of the following to your application's Gemfile:
|
18
18
|
```ruby
|
19
|
-
|
20
|
-
|
19
|
+
# For on-demand usage ...
|
20
|
+
#
|
21
21
|
gem 'env_parser'
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
# To automatically register ENV
|
24
|
+
# constants per ".env_parser.yml" ...
|
25
|
+
#
|
26
26
|
gem 'env_parser', require: 'env_parser/autoregister'
|
27
27
|
```
|
28
28
|
- And then run a:
|
@@ -39,33 +39,33 @@ Things can get out of control pretty fast, especially as the number of environme
|
|
39
39
|
## Syntax Cheat Sheet
|
40
40
|
|
41
41
|
```ruby
|
42
|
-
|
43
|
-
|
42
|
+
# Returns an ENV value parsed "as" a specific type:
|
43
|
+
#
|
44
44
|
EnvParser.parse env_key_as_a_symbol
|
45
|
-
as: …
|
46
|
-
if_unset: …
|
47
|
-
from_set: …
|
48
|
-
validated_by: ->(value) { … }
|
45
|
+
as: … # ➜ required
|
46
|
+
if_unset: … # ➜ optional; default value
|
47
|
+
from_set: … # ➜ optional; an Array or Range
|
48
|
+
validated_by: ->(value) { … } # ➜ optional; may also be given as a block
|
49
49
|
|
50
|
-
|
51
|
-
|
50
|
+
# Parse an ENV value and register it as a constant:
|
51
|
+
#
|
52
52
|
EnvParser.register env_key_as_a_symbol
|
53
|
-
as: …
|
54
|
-
within: …
|
55
|
-
if_unset: …
|
56
|
-
from_set: …
|
57
|
-
validated_by: ->(value) { … }
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
EnvParser.autoregister
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
EnvParser.add_env_bindings
|
68
|
-
|
53
|
+
as: … # ➜ required
|
54
|
+
within: … # ➜ optional; Class or Module
|
55
|
+
if_unset: … # ➜ optional; default value
|
56
|
+
from_set: … # ➜ optional; an Array or Range
|
57
|
+
validated_by: ->(value) { … } # ➜ optional; may also be given as a block
|
58
|
+
|
59
|
+
# Registers all ENV variables as spec'ed in ".env_parser.yml":
|
60
|
+
#
|
61
|
+
EnvParser.autoregister # Note this is automatically called if your
|
62
|
+
# Gemfile included the "env_parser" gem with
|
63
|
+
# the "require: 'env_parser/autoregister'" option.
|
64
|
+
|
65
|
+
# Lets you call "parse" and "register" on ENV itself:
|
66
|
+
#
|
67
|
+
EnvParser.add_env_bindings # ENV.parse will now be a proxy for EnvParser.parse
|
68
|
+
# and ENV.register will now be a proxy for EnvParser.register
|
69
69
|
```
|
70
70
|
|
71
71
|
|
@@ -78,9 +78,9 @@ EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
|
78
78
|
At its core, EnvParser is a straight-forward parser for string values (since that's all `ENV` ever gives you), allowing you to read a given string **_as_** a variety of types.
|
79
79
|
|
80
80
|
```ruby
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
# Returns ENV['TIMEOUT_MS'] as an Integer,
|
82
|
+
# or a sensible default (0) if ENV['TIMEOUT_MS'] is unset.
|
83
|
+
#
|
84
84
|
timeout_ms = EnvParser.parse ENV['TIMEOUT_MS'], as: :integer
|
85
85
|
```
|
86
86
|
|
@@ -91,9 +91,9 @@ EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
|
91
91
|
EnvParser is all about ~~simplification~~ ~~less typing~~ *laziness*. If you pass in a symbol instead of a string, EnvParser will look to `ENV` and use the value from the corresponding (string) key.
|
92
92
|
|
93
93
|
```ruby
|
94
|
-
|
95
|
-
|
96
|
-
|
94
|
+
# YAY, LESS TYPING! 😃
|
95
|
+
# These two are the same:
|
96
|
+
#
|
97
97
|
more_typing = EnvParser.parse ENV['TIMEOUT_MS'], as: :integer
|
98
98
|
less_typing = EnvParser.parse :TIMEOUT_MS, as: :integer
|
99
99
|
```
|
@@ -103,20 +103,20 @@ EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
|
103
103
|
The `EnvParser.register` method lets you "promote" `ENV` variables into their own constants, already parsed into the correct type.
|
104
104
|
|
105
105
|
```ruby
|
106
|
-
ENV['API_KEY']
|
106
|
+
ENV['API_KEY'] # => 'unbreakable p4$$w0rd'
|
107
107
|
|
108
108
|
EnvParser.register :API_KEY, as: :string
|
109
|
-
API_KEY
|
109
|
+
API_KEY # => 'unbreakable p4$$w0rd'
|
110
110
|
```
|
111
111
|
|
112
112
|
By default, `EnvParser.register` will create the requested constant within the Kernel module (making it available everywhere), but you can specify any class or module you like.
|
113
113
|
|
114
114
|
```ruby
|
115
|
-
ENV['BEST_VIDEO']
|
115
|
+
ENV['BEST_VIDEO'] # => 'https://youtu.be/L_jWHffIx5E'
|
116
116
|
|
117
117
|
EnvParser.register :BEST_VIDEO, as: :string, within: URI
|
118
|
-
URI::BEST_VIDEO
|
119
|
-
BEST_VIDEO
|
118
|
+
URI::BEST_VIDEO # => 'https://youtu.be/L_jWHffIx5E'
|
119
|
+
BEST_VIDEO # => raises NameError
|
120
120
|
```
|
121
121
|
|
122
122
|
You can also register multiple constants with a single call, which is a bit cleaner.
|
@@ -126,7 +126,7 @@ EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
|
126
126
|
EnvParser.register :PASSWORD, as: :string
|
127
127
|
EnvParser.register :MOCK_API, as: :boolean, within: MyClassOrModule }
|
128
128
|
|
129
|
-
|
129
|
+
# ... is equivalent to ... #
|
130
130
|
|
131
131
|
EnvParser.register USERNAME: { as: :string },
|
132
132
|
PASSWORD: { as: :string },
|
@@ -138,31 +138,31 @@ EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
|
138
138
|
Calling `EnvParser.add_env_bindings` binds proxy `parse` and `register` methods onto `ENV`. With these bindings in place, you can call `parse` or `register` on `ENV` itself, which is more legible and feels more straight-forward.
|
139
139
|
|
140
140
|
```ruby
|
141
|
-
ENV['SHORT_PI']
|
142
|
-
ENV['BETTER_PI']
|
141
|
+
ENV['SHORT_PI'] # => '3.1415926'
|
142
|
+
ENV['BETTER_PI'] # => '["flaky crust", "strawberry filling"]'
|
143
143
|
|
144
|
-
|
145
|
-
|
144
|
+
# Bind the proxy methods.
|
145
|
+
#
|
146
146
|
EnvParser.add_env_bindings
|
147
147
|
|
148
|
-
ENV.parse :SHORT_PI, as: :float
|
149
|
-
ENV.register :BETTER_PI, as: :array
|
148
|
+
ENV.parse :SHORT_PI, as: :float # => 3.1415926
|
149
|
+
ENV.register :BETTER_PI, as: :array # Your constant is set!
|
150
150
|
```
|
151
151
|
|
152
152
|
Note that the proxy `ENV.parse` method will (naturally) *always* interpret the value given as an `ENV` key (converting it to a string, if necessary), which is slightly different from the original `EnvParser.parse` method.
|
153
153
|
|
154
154
|
```ruby
|
155
|
-
ENV['SHORT_PI']
|
155
|
+
ENV['SHORT_PI'] # => '3.1415926'
|
156
156
|
|
157
|
-
EnvParser.parse 'SHORT_PI', as: :float
|
158
|
-
EnvParser.parse :SHORT_PI , as: :float
|
157
|
+
EnvParser.parse 'SHORT_PI', as: :float # => 'SHORT_PI' as a float: 0.0
|
158
|
+
EnvParser.parse :SHORT_PI , as: :float # => ENV['SHORT_PI'] as a float: 3.1415926
|
159
159
|
|
160
|
-
|
161
|
-
|
160
|
+
# Bind the proxy methods.
|
161
|
+
#
|
162
162
|
EnvParser.add_env_bindings
|
163
163
|
|
164
|
-
ENV.parse 'SHORT_PI', as: :float
|
165
|
-
ENV.parse :SHORT_PI , as: :float
|
164
|
+
ENV.parse 'SHORT_PI', as: :float # => ENV['SHORT_PI'] as a float: 3.1415926
|
165
|
+
ENV.parse :SHORT_PI , as: :float # => ENV['SHORT_PI'] as a float: 3.1415926
|
166
166
|
```
|
167
167
|
|
168
168
|
Note also that the `ENV.parse` and `ENV.register` binding is done safely and without polluting the method space for other objects.
|
@@ -177,14 +177,14 @@ EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
|
177
177
|
If the `ENV` variable you want is unset (`nil`) or blank (`''`), the return value is a sensible default for the given **_as_** type: 0 or 0.0 for numbers, an empty string/array/hash, etc. Sometimes you want a non-trivial default, however. The **_if_unset_** option lets you specify a default that better meets your needs.
|
178
178
|
|
179
179
|
```ruby
|
180
|
-
ENV.parse :MISSING_VAR, as: :integer
|
181
|
-
ENV.parse :MISSING_VAR, as: :integer, if_unset: 250
|
180
|
+
ENV.parse :MISSING_VAR, as: :integer # => 0
|
181
|
+
ENV.parse :MISSING_VAR, as: :integer, if_unset: 250 # => 250
|
182
182
|
```
|
183
183
|
|
184
184
|
Note these default values are used as-is with no type conversion, so exercise caution.
|
185
185
|
|
186
186
|
```ruby
|
187
|
-
ENV.parse :MISSING_VAR, as: :integer, if_unset: 'Careful!'
|
187
|
+
ENV.parse :MISSING_VAR, as: :integer, if_unset: 'Careful!' # => 'Careful!' (NOT AN INTEGER)
|
188
188
|
```
|
189
189
|
|
190
190
|
- **Selecting From A Set**
|
@@ -195,9 +195,9 @@ EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
|
195
195
|
ENV.parse :API_TO_USE, as: :symbol, from_set: %i[internal external]
|
196
196
|
ENV.parse :NETWORK_PORT, as: :integer, from_set: (1..65535), if_unset: 80
|
197
197
|
|
198
|
-
|
199
|
-
|
200
|
-
ENV.parse :TWELVE, as: :integer, from_set: (1..5)
|
198
|
+
# And if the value is not in the allowed set ...
|
199
|
+
#
|
200
|
+
ENV.parse :TWELVE, as: :integer, from_set: (1..5) # => raises EnvParser::ValueNotAllowedError
|
201
201
|
```
|
202
202
|
|
203
203
|
- **Custom Validation Of Parsed Values**
|
@@ -205,12 +205,12 @@ EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
|
205
205
|
You can write your own, more complex validations by passing in a **_validated_by_** lambda or an equivalent block. The lambda/block should take one value and return true if the given value passes the custom validation.
|
206
206
|
|
207
207
|
```ruby
|
208
|
-
|
209
|
-
|
208
|
+
# Via a "validated_by" lambda ...
|
209
|
+
#
|
210
210
|
ENV.parse :MUST_BE_LOWERCASE, as: :string, validated_by: ->(value) { value == value.downcase }
|
211
211
|
|
212
|
-
|
213
|
-
|
212
|
+
# ... or with a block!
|
213
|
+
#
|
214
214
|
ENV.parse(:MUST_BE_LOWERCASE, as: :string) { |value| value == value.downcase }
|
215
215
|
ENV.parse(:CONNECTION_RETRIES, as: :integer, &:positive?)
|
216
216
|
```
|
@@ -269,7 +269,7 @@ EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
|
269
269
|
EnvParser.register :PASSWORD, as: :string
|
270
270
|
EnvParser.register :MOCK_API, as: :boolean, within: MyClassOrModule }
|
271
271
|
|
272
|
-
|
272
|
+
# ... is equivalent to ... #
|
273
273
|
|
274
274
|
EnvParser.register USERNAME: { as: :string },
|
275
275
|
PASSWORD: { as: :string },
|
@@ -133,7 +133,7 @@ feature).</p>
|
|
133
133
|
</div>
|
134
134
|
|
135
135
|
<div id="footer">
|
136
|
-
Generated on Sun Dec 25 21:
|
136
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
137
137
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
138
138
|
0.9.28 (ruby-3.0.4).
|
139
139
|
</div>
|
data/docs/EnvParser/Error.html
CHANGED
@@ -128,7 +128,7 @@
|
|
128
128
|
</div>
|
129
129
|
|
130
130
|
<div id="footer">
|
131
|
-
Generated on Sun Dec 25 21:
|
131
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
132
132
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
133
133
|
0.9.28 (ruby-3.0.4).
|
134
134
|
</div>
|
@@ -132,7 +132,7 @@
|
|
132
132
|
</div>
|
133
133
|
|
134
134
|
<div id="footer">
|
135
|
-
Generated on Sun Dec 25 21:
|
135
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
136
136
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
137
137
|
0.9.28 (ruby-3.0.4).
|
138
138
|
</div>
|
@@ -169,7 +169,7 @@ valid, parseable JSON).</p>
|
|
169
169
|
</div>
|
170
170
|
|
171
171
|
<div id="footer">
|
172
|
-
Generated on Sun Dec 25 21:
|
172
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
173
173
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
174
174
|
0.9.28 (ruby-3.0.4).
|
175
175
|
</div>
|
@@ -150,7 +150,7 @@
|
|
150
150
|
</div>
|
151
151
|
|
152
152
|
<div id="footer">
|
153
|
-
Generated on Sun Dec 25 21:
|
153
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
154
154
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
155
155
|
0.9.28 (ruby-3.0.4).
|
156
156
|
</div>
|
@@ -150,7 +150,7 @@
|
|
150
150
|
</div>
|
151
151
|
|
152
152
|
<div id="footer">
|
153
|
-
Generated on Sun Dec 25 21:
|
153
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
154
154
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
155
155
|
0.9.28 (ruby-3.0.4).
|
156
156
|
</div>
|
data/docs/EnvParser/Types.html
CHANGED
@@ -118,7 +118,7 @@ Exists only for documentation’s sake.</p>
|
|
118
118
|
</div>
|
119
119
|
|
120
120
|
<div id="footer">
|
121
|
-
Generated on Sun Dec 25 21:
|
121
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
122
122
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
123
123
|
0.9.28 (ruby-3.0.4).
|
124
124
|
</div>
|
@@ -132,7 +132,7 @@
|
|
132
132
|
</div>
|
133
133
|
|
134
134
|
<div id="footer">
|
135
|
-
Generated on Sun Dec 25 21:
|
135
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
136
136
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
137
137
|
0.9.28 (ruby-3.0.4).
|
138
138
|
</div>
|
@@ -133,7 +133,7 @@ feature).</p>
|
|
133
133
|
</div>
|
134
134
|
|
135
135
|
<div id="footer">
|
136
|
-
Generated on Sun Dec 25 21:
|
136
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
137
137
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
138
138
|
0.9.28 (ruby-3.0.4).
|
139
139
|
</div>
|
@@ -134,7 +134,7 @@ check.</p>
|
|
134
134
|
</div>
|
135
135
|
|
136
136
|
<div id="footer">
|
137
|
-
Generated on Sun Dec 25 21:
|
137
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
138
138
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
139
139
|
0.9.28 (ruby-3.0.4).
|
140
140
|
</div>
|
@@ -132,7 +132,7 @@
|
|
132
132
|
</div>
|
133
133
|
|
134
134
|
<div id="footer">
|
135
|
-
Generated on Sun Dec 25 21:
|
135
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
136
136
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
137
137
|
0.9.28 (ruby-3.0.4).
|
138
138
|
</div>
|
data/docs/EnvParser.html
CHANGED
@@ -95,7 +95,7 @@
|
|
95
95
|
<dl>
|
96
96
|
<dt>Defined in:</dt>
|
97
97
|
<dd>lib/env_parser.rb<span class="defines">,<br />
|
98
|
-
lib/env_parser/errors.rb</span>
|
98
|
+
lib/env_parser/errors.rb,<br /> lib/env_parser/version.rb</span>
|
99
99
|
</dd>
|
100
100
|
</dl>
|
101
101
|
|
@@ -147,6 +147,11 @@
|
|
147
147
|
</dt>
|
148
148
|
<dd><pre class="code"><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>.env_parser.yml</span><span class='tstring_end'>'</span></span><span class='period'>.</span><span class='id identifier rubyid_freeze'>freeze</span></pre></dd>
|
149
149
|
|
150
|
+
<dt id="VERSION-constant" class="">VERSION =
|
151
|
+
|
152
|
+
</dt>
|
153
|
+
<dd><pre class="code"><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>1.3.3</span><span class='tstring_end'>'</span></span><span class='period'>.</span><span class='id identifier rubyid_freeze'>freeze</span></pre></dd>
|
154
|
+
|
150
155
|
</dl>
|
151
156
|
|
152
157
|
|
@@ -1197,7 +1202,7 @@ validation must give its own “validated_by” Proc.</p>
|
|
1197
1202
|
</div>
|
1198
1203
|
|
1199
1204
|
<div id="footer">
|
1200
|
-
Generated on Sun Dec 25 21:
|
1205
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
1201
1206
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
1202
1207
|
0.9.28 (ruby-3.0.4).
|
1203
1208
|
</div>
|
data/docs/_index.html
CHANGED
@@ -233,7 +233,7 @@
|
|
233
233
|
</div>
|
234
234
|
|
235
235
|
<div id="footer">
|
236
|
-
Generated on Sun Dec 25 21:
|
236
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
237
237
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
238
238
|
0.9.28 (ruby-3.0.4).
|
239
239
|
</div>
|
data/docs/file.README.html
CHANGED
@@ -396,7 +396,7 @@ USERNAME:
|
|
396
396
|
</div></div>
|
397
397
|
|
398
398
|
<div id="footer">
|
399
|
-
Generated on Sun Dec 25 21:
|
399
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
400
400
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
401
401
|
0.9.28 (ruby-3.0.4).
|
402
402
|
</div>
|
data/docs/index.html
CHANGED
@@ -396,7 +396,7 @@ USERNAME:
|
|
396
396
|
</div></div>
|
397
397
|
|
398
398
|
<div id="footer">
|
399
|
-
Generated on Sun Dec 25 21:
|
399
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
400
400
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
401
401
|
0.9.28 (ruby-3.0.4).
|
402
402
|
</div>
|
@@ -100,7 +100,7 @@
|
|
100
100
|
</div>
|
101
101
|
|
102
102
|
<div id="footer">
|
103
|
-
Generated on Sun Dec 25 21:
|
103
|
+
Generated on Sun Dec 25 21:11:48 2022 by
|
104
104
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
105
|
0.9.28 (ruby-3.0.4).
|
106
106
|
</div>
|
@@ -48,6 +48,18 @@ module EnvParser::Types
|
|
48
48
|
# Note this does not guarantee RFC5322-conformity.
|
49
49
|
# </td>
|
50
50
|
# </tr>
|
51
|
+
# <tr>
|
52
|
+
# <td>:version / :semver</td>
|
53
|
+
# <td>MatchData</td>
|
54
|
+
# <td><code>nil</code></td>
|
55
|
+
# <td>
|
56
|
+
# The resulting MatchData has named captures for "major", "minor", "patch", "prerelease", and "buildmetadata".
|
57
|
+
# <br />
|
58
|
+
# The Regex used for generating this MatchData is available at: https://regex101.com/r/Ly7O1x/3/
|
59
|
+
# <br />
|
60
|
+
# See https://semver.org for additional info.
|
61
|
+
# </td>
|
62
|
+
# </tr>
|
51
63
|
# </tbody>
|
52
64
|
# </table>
|
53
65
|
#
|
@@ -95,5 +107,15 @@ module EnvParser::Types
|
|
95
107
|
|
96
108
|
value
|
97
109
|
end
|
110
|
+
|
111
|
+
EnvParser.define_type(:version, aliases: :semver, if_unset: nil) do |value|
|
112
|
+
# We're using the official semver.org-provided regex.
|
113
|
+
semver = %r{^(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-(?<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$} ## rubocop:disable Layout/LineLength
|
114
|
+
|
115
|
+
match_data = value.match(semver)
|
116
|
+
raise(EnvParser::ValueNotConvertibleError, 'not a semver-compliant value') unless match_data
|
117
|
+
|
118
|
+
match_data
|
119
|
+
end
|
98
120
|
end
|
99
121
|
end
|
data/lib/env_parser/version.rb
CHANGED
data/lib/env_parser.rb
CHANGED
@@ -132,12 +132,12 @@ class EnvParser
|
|
132
132
|
# variable names and whose values are the options set for each variable's {.register} call.
|
133
133
|
#
|
134
134
|
# <pre>
|
135
|
-
#
|
135
|
+
# # Example shortcut usage:
|
136
136
|
#
|
137
137
|
# EnvParser.register :A, from: one_hash, as: :integer
|
138
138
|
# EnvParser.register :B, from: another_hash, as: :string, if_unset: 'none'
|
139
139
|
#
|
140
|
-
#
|
140
|
+
# # ... is equivalent to ...
|
141
141
|
#
|
142
142
|
# EnvParser.register(
|
143
143
|
# A: { from: one_hash, as: :integer }
|
@@ -152,6 +152,19 @@ class EnvParser
|
|
152
152
|
# @option options [Hash] from (ENV)
|
153
153
|
# The source Hash from which to pull the value referenced by the "name" key.
|
154
154
|
#
|
155
|
+
# @option options [Symbol] named
|
156
|
+
# The name the constant should be given. Valid only when a "within" value is *explicitly*
|
157
|
+
# given. This allows for decoupling ENV variable names from the constant name defined
|
158
|
+
# within its target class or module, allowing for the ENV variables to be namespaced in
|
159
|
+
# some way.
|
160
|
+
#
|
161
|
+
# <pre>
|
162
|
+
# EnvParser.register(
|
163
|
+
# CUSTOM_CLIENT_DEFAULT_HOSTNAME: { as: :string, named: :DEFAULT_HOSTNAME, within: CustomClient },
|
164
|
+
# CUSTOM_CLIENT_DEFAULT_PORT: { as: :integer, named: :DEFAULT_PORT, within: CustomClient }
|
165
|
+
# )
|
166
|
+
# </pre>
|
167
|
+
#
|
155
168
|
# @option options [Module, Class] within (Kernel)
|
156
169
|
# The module or class in which the constant should be created. Creates global constants by
|
157
170
|
# default.
|
@@ -185,6 +198,9 @@ class EnvParser
|
|
185
198
|
from = options.fetch(:from, ENV)
|
186
199
|
within = options.fetch(:within, Kernel)
|
187
200
|
|
201
|
+
named = name
|
202
|
+
named = options.fetch(:named, name) if options.key? :within
|
203
|
+
|
188
204
|
# ENV *seems* like a Hash and it does *some* Hash-y things, but it is NOT a Hash and that can
|
189
205
|
# bite you in some cases. Making sure we're working with a straight-up Hash saves a lot of
|
190
206
|
# sanity checks later on. This is also a good place to make sure we're working with a String
|
@@ -199,7 +215,7 @@ class EnvParser
|
|
199
215
|
|
200
216
|
value = from[name]
|
201
217
|
value = parse(value, options, &validation_block)
|
202
|
-
within.const_set(
|
218
|
+
within.const_set(named.upcase.to_sym, value.dup.freeze)
|
203
219
|
|
204
220
|
value
|
205
221
|
end
|
@@ -248,7 +264,7 @@ class EnvParser
|
|
248
264
|
|
249
265
|
autoregister_spec.deep_symbolize_keys!
|
250
266
|
autoregister_spec.transform_values! do |spec|
|
251
|
-
sanitized = spec.slice(:as, :within, :if_unset, :from_set)
|
267
|
+
sanitized = spec.slice(:as, :named, :within, :if_unset, :from_set)
|
252
268
|
sanitized[:as] = sanitized[:as].to_sym if sanitized.key? :as
|
253
269
|
sanitized[:within] = sanitized[:within].constantize if sanitized.key? :within
|
254
270
|
|
@@ -42,4 +42,54 @@ RSpec.describe EnvParser::Types::InternetTypes do
|
|
42
42
|
|
43
43
|
expect { EnvParser.parse('not an email address', as: :email_address) }.to raise_error(EnvParser::ValueNotConvertibleError)
|
44
44
|
end
|
45
|
+
|
46
|
+
it 'can parse version numbers' do
|
47
|
+
%i[version semver].each do |type|
|
48
|
+
expect(EnvParser.parse(nil, as: type)).to eq(nil)
|
49
|
+
expect(EnvParser.parse('', as: type)).to eq(nil)
|
50
|
+
|
51
|
+
# Our list of valid version strings is a subset of those in the official semver.org-provided regex suite.
|
52
|
+
# rubocop:disable Layout
|
53
|
+
#
|
54
|
+
valid_version_strings = {
|
55
|
+
'0.0.4' => { major: '0' , minor: '0', patch: '4', prerelease: nil , buildmetadata: nil },
|
56
|
+
'1.2.3' => { major: '1' , minor: '2', patch: '3', prerelease: nil , buildmetadata: nil },
|
57
|
+
'1.1.2-prerelease+meta' => { major: '1' , minor: '1', patch: '2', prerelease: 'prerelease' , buildmetadata: 'meta' },
|
58
|
+
'1.1.2+meta' => { major: '1' , minor: '1', patch: '2', prerelease: nil , buildmetadata: 'meta' },
|
59
|
+
'1.1.2+meta-valid' => { major: '1' , minor: '1', patch: '2', prerelease: nil , buildmetadata: 'meta-valid' },
|
60
|
+
'1.0.0-alpha' => { major: '1' , minor: '0', patch: '0', prerelease: 'alpha' , buildmetadata: nil },
|
61
|
+
'1.0.0-beta' => { major: '1' , minor: '0', patch: '0', prerelease: 'beta' , buildmetadata: nil },
|
62
|
+
'1.0.0-alpha.beta' => { major: '1' , minor: '0', patch: '0', prerelease: 'alpha.beta' , buildmetadata: nil },
|
63
|
+
'1.0.0-alpha.beta.1' => { major: '1' , minor: '0', patch: '0', prerelease: 'alpha.beta.1', buildmetadata: nil },
|
64
|
+
'1.0.0-alpha.1' => { major: '1' , minor: '0', patch: '0', prerelease: 'alpha.1' , buildmetadata: nil },
|
65
|
+
'1.0.0-alpha0.valid' => { major: '1' , minor: '0', patch: '0', prerelease: 'alpha0.valid', buildmetadata: nil },
|
66
|
+
'1.0.0-alpha.0valid' => { major: '1' , minor: '0', patch: '0', prerelease: 'alpha.0valid', buildmetadata: nil },
|
67
|
+
'1.0.0-rc.1+build.1' => { major: '1' , minor: '0', patch: '0', prerelease: 'rc.1' , buildmetadata: 'build.1' },
|
68
|
+
'2.0.0-rc.1+build.123' => { major: '2' , minor: '0', patch: '0', prerelease: 'rc.1' , buildmetadata: 'build.123' },
|
69
|
+
'1.2.3-beta' => { major: '1' , minor: '2', patch: '3', prerelease: 'beta' , buildmetadata: nil },
|
70
|
+
'10.2.3-DEV-SNAPSHOT' => { major: '10', minor: '2', patch: '3', prerelease: 'DEV-SNAPSHOT', buildmetadata: nil },
|
71
|
+
'1.2.3-SNAPSHOT-123' => { major: '1' , minor: '2', patch: '3', prerelease: 'SNAPSHOT-123', buildmetadata: nil },
|
72
|
+
'2.0.0+build.1848' => { major: '2' , minor: '0', patch: '0', prerelease: nil , buildmetadata: 'build.1848' },
|
73
|
+
'2.0.1-alpha.1227' => { major: '2' , minor: '0', patch: '1', prerelease: 'alpha.1227' , buildmetadata: nil },
|
74
|
+
'1.0.0-alpha+beta' => { major: '1' , minor: '0', patch: '0', prerelease: 'alpha' , buildmetadata: 'beta' },
|
75
|
+
'1.0.0-0A.is.legal' => { major: '1' , minor: '0', patch: '0', prerelease: '0A.is.legal' , buildmetadata: nil }
|
76
|
+
}
|
77
|
+
# rubocop:enable Layout
|
78
|
+
|
79
|
+
valid_version_strings.each do |version, expected_matches|
|
80
|
+
parsed_value = EnvParser.parse(version, as: type)
|
81
|
+
|
82
|
+
expect(parsed_value).to_not eq(nil)
|
83
|
+
expected_matches.each { |match_name, expected_value| expect(parsed_value[match_name]).to eq(expected_value) }
|
84
|
+
end
|
85
|
+
|
86
|
+
# Our list of invalid version strings is a subset of those in the official semver.org-provided regex suite.
|
87
|
+
#
|
88
|
+
invalid_version_strings = ['1', '1.2', '1.2.3-0123', '1.2.3-0123.0123', '1.1.2+.123', '+invalid', '-invalid', '-invalid+invalid',
|
89
|
+
'-invalid.01', 'alpha', 'alpha.1', 'alpha+beta', '1.0.0-alpha..', '1.0.0-alpha..1', '01.1.1', '1.01.1',
|
90
|
+
'1.1.01', '1.2.3.DEV', '1.2-SNAPSHOT', '+justmeta', '9.8.7+meta+meta', '9.8.7-whatever+meta+meta']
|
91
|
+
|
92
|
+
invalid_version_strings.each { |version| expect { EnvParser.parse(version, as: type) }.to raise_error(EnvParser::ValueNotConvertibleError) }
|
93
|
+
end
|
94
|
+
end
|
45
95
|
end
|
data/spec/env_parser_spec.rb
CHANGED
@@ -60,9 +60,16 @@ RSpec.describe EnvParser do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'creates module constants' do
|
63
|
-
source_hash = {
|
64
|
-
EnvParser.register(:
|
65
|
-
expect(Sample::
|
63
|
+
source_hash = { DEF: '456' }
|
64
|
+
EnvParser.register(:DEF, from: source_hash, as: :integer, within: Sample)
|
65
|
+
expect(Sample::DEF).to eq(456)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'creates named module constants' do
|
69
|
+
source_hash = { GHI: '789' }
|
70
|
+
EnvParser.register(:GHI, from: source_hash, as: :integer, named: :JKL, within: Sample)
|
71
|
+
expect { Sample::GHI }.to raise_error(NameError)
|
72
|
+
expect(Sample::JKL).to eq(789)
|
66
73
|
end
|
67
74
|
|
68
75
|
it 'will accept a hash keyed by variable names' do
|
@@ -117,6 +124,13 @@ RSpec.describe EnvParser do
|
|
117
124
|
expect(Sample::WXYZ).to eq(5678)
|
118
125
|
end
|
119
126
|
|
127
|
+
it 'creates module constants' do
|
128
|
+
ENV['ORIGINAL_NAME'] = '9999'
|
129
|
+
ENV.register(:ORIGINAL_NAME, as: :integer, named: :DIFFERENT_NAME, within: Sample)
|
130
|
+
expect { Sample::ORIGINAL_NAME }.to raise_error(NameError)
|
131
|
+
expect(Sample::DIFFERENT_NAME).to eq(9999)
|
132
|
+
end
|
133
|
+
|
120
134
|
it 'will accept a hash keyed by variable names' do
|
121
135
|
ENV['FIFTH'] = 'fifth'
|
122
136
|
ENV['SIXTH'] = '99'
|
@@ -156,6 +170,11 @@ RSpec.describe EnvParser do
|
|
156
170
|
CLASS_CONSTANT:
|
157
171
|
as: :string
|
158
172
|
within: String
|
173
|
+
|
174
|
+
NAMED_CLASS_CONSTANT:
|
175
|
+
as: :string
|
176
|
+
named: :OTHER_CLASS_CONSTANT
|
177
|
+
within: String
|
159
178
|
YAML
|
160
179
|
|
161
180
|
file.path
|
@@ -164,11 +183,14 @@ RSpec.describe EnvParser do
|
|
164
183
|
ENV['SOME_INT'] = '99'
|
165
184
|
ENV['SOME_STRING'] = 'twelve'
|
166
185
|
ENV['CLASS_CONSTANT'] = 'tricky'
|
186
|
+
ENV['NAMED_CLASS_CONSTANT'] = 'quizzical'
|
167
187
|
EnvParser.autoregister filename
|
168
188
|
|
169
189
|
expect(SOME_INT).to eq(99)
|
170
190
|
expect(SOME_STRING).to eq('twelve')
|
171
191
|
expect(String::CLASS_CONSTANT).to eq('tricky')
|
192
|
+
expect { String::NAMED_CLASS_CONSTANT }.to raise_error(NameError)
|
193
|
+
expect(String::OTHER_CLASS_CONSTANT).to eq('quizzical')
|
172
194
|
end
|
173
195
|
|
174
196
|
it 'properly handles file-not-found' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: env_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nestor Custodio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|