env_parser 1.3.3 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dffb38fe58381e11c8b63aebe34fccaec31e4c59c5a1c61274824e0c09aaf9e3
4
- data.tar.gz: '088dfcdefdcc661b1d344526da81007e6bfa274b93b0b512807705543f9591c2'
3
+ metadata.gz: 4106f96ced2bcf4948b4547012b017e8632bf43450e86d9639eaf54aa9802ffb
4
+ data.tar.gz: c6e54495905a39126f320226a118b6c83405860a8ec502e7711e28ed9ad57de9
5
5
  SHA512:
6
- metadata.gz: 0cbf4b4148bf9c4040358d7bd90d4f722fee975f6966f459026e53d7d5692e7f8167fd99fa67c0c97bfa590e0d5753e32021db3cd496d4c0a5ee5bb3865131a5
7
- data.tar.gz: 1a268110295c48d65a186e6113ef174d5aa51f7491f6c88f41f38ac7d9243fc794cc499e933b51010c3e3773fcca6225ab3cffede4a46a28c9ba66317e85ccc7
6
+ metadata.gz: 2fb35a0bee0ec626b5c070e426cd5214ce42e9be4eef861ce922c9ee0366c75dbddfcf9b352ca5c5d5806cd0e35ed25575181e35babf56b4b748260133215d46
7
+ data.tar.gz: ddc6daa85de95c97f2a914f8ff563c9e6fd128f14ca8566a2af153458a6d782fe73831b60d34b503e7beee00285d069354a216ef5b1b261a5a4072d5fa7930ed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- env_parser (1.3.2)
4
+ env_parser (1.3.3)
5
5
  activesupport (>= 6.1.0, < 7.1)
6
6
  chronic
7
7
  chronic_duration
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
- ## For on-demand usage ...
20
- ##
19
+ # For on-demand usage ...
20
+ #
21
21
  gem 'env_parser'
22
22
 
23
- ## To automatically register ENV
24
- ## constants per ".env_parser.yml" ...
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
- ## Returns an ENV value parsed "as" a specific type:
43
- ##
42
+ # Returns an ENV value parsed "as" a specific type:
43
+ #
44
44
  EnvParser.parse env_key_as_a_symbol
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
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
- ## Parse an ENV value and register it as a constant:
51
- ##
50
+ # Parse an ENV value and register it as a constant:
51
+ #
52
52
  EnvParser.register env_key_as_a_symbol
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
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
- ## Returns ENV['TIMEOUT_MS'] as an Integer,
82
- ## or a sensible default (0) if ENV['TIMEOUT_MS'] is unset.
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
- ## YAY, LESS TYPING! 😃
95
- ## These two are the same:
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'] ## => 'unbreakable p4$$w0rd'
106
+ ENV['API_KEY'] # => 'unbreakable p4$$w0rd'
107
107
 
108
108
  EnvParser.register :API_KEY, as: :string
109
- API_KEY ## => 'unbreakable p4$$w0rd'
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'] ## => 'https://youtu.be/L_jWHffIx5E'
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 ## => 'https://youtu.be/L_jWHffIx5E'
119
- BEST_VIDEO ## => raises NameError
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
- ## ... is equivalent to ... ##
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'] ## => '3.1415926'
142
- ENV['BETTER_PI'] ## => '["flaky crust", "strawberry filling"]'
141
+ ENV['SHORT_PI'] # => '3.1415926'
142
+ ENV['BETTER_PI'] # => '["flaky crust", "strawberry filling"]'
143
143
 
144
- ## Bind the proxy methods.
145
- ##
144
+ # Bind the proxy methods.
145
+ #
146
146
  EnvParser.add_env_bindings
147
147
 
148
- ENV.parse :SHORT_PI, as: :float ## => 3.1415926
149
- ENV.register :BETTER_PI, as: :array ## Your constant is set!
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'] ## => '3.1415926'
155
+ ENV['SHORT_PI'] # => '3.1415926'
156
156
 
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
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
- ## Bind the proxy methods.
161
- ##
160
+ # Bind the proxy methods.
161
+ #
162
162
  EnvParser.add_env_bindings
163
163
 
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
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 ## => 0
181
- ENV.parse :MISSING_VAR, as: :integer, if_unset: 250 ## => 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!' ## => 'Careful!' (NOT AN INTEGER)
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
- ## And if the value is not in the allowed set ...
199
- ##
200
- ENV.parse :TWELVE, as: :integer, from_set: (1..5) ## => raises EnvParser::ValueNotAllowedError
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
- ## Via a "validated_by" lambda ...
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
- ## ... or with a block!
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
- ## ... is equivalent to ... ##
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:09:36 2022 by
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>
@@ -128,7 +128,7 @@
128
128
  </div>
129
129
 
130
130
  <div id="footer">
131
- Generated on Sun Dec 25 21:09:36 2022 by
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:09:36 2022 by
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:09:36 2022 by
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:09:36 2022 by
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:09:36 2022 by
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>
@@ -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:09:36 2022 by
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:09:36 2022 by
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:09:36 2022 by
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:09:36 2022 by
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:09:36 2022 by
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'>&#39;</span><span class='tstring_content'>.env_parser.yml</span><span class='tstring_end'>&#39;</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'>&#39;</span><span class='tstring_content'>1.3.3</span><span class='tstring_end'>&#39;</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:09:36 2022 by
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:09:35 2022 by
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>
@@ -396,7 +396,7 @@ USERNAME:
396
396
  </div></div>
397
397
 
398
398
  <div id="footer">
399
- Generated on Sun Dec 25 21:09:36 2022 by
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:09:36 2022 by
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:09:36 2022 by
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
@@ -1,3 +1,3 @@
1
1
  class EnvParser
2
- VERSION = '1.3.3'.freeze
2
+ VERSION = '1.6.0'.freeze
3
3
  end
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
- # ## Example shortcut usage:
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
- # ## ... is equivalent to ...
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(name.upcase.to_sym, value.dup.freeze)
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
@@ -60,9 +60,16 @@ RSpec.describe EnvParser do
60
60
  end
61
61
 
62
62
  it 'creates module constants' do
63
- source_hash = { XYZ: '456' }
64
- EnvParser.register(:XYZ, from: source_hash, as: :integer, within: Sample)
65
- expect(Sample::XYZ).to eq(456)
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.3.3
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-26 00:00:00.000000000 Z
11
+ date: 2022-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport