philiprehberger-env_validator 0.2.9 → 0.4.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 +4 -4
- data/CHANGELOG.md +17 -2
- data/README.md +46 -1
- data/lib/philiprehberger/env_validator/schema.rb +23 -0
- data/lib/philiprehberger/env_validator/validator.rb +30 -7
- data/lib/philiprehberger/env_validator/version.rb +1 -1
- data/lib/philiprehberger/env_validator.rb +3 -2
- 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: cb9d6d9b1aeee1b8eb35392807aec880212627edbcbb426c8108e1056824dc07
|
|
4
|
+
data.tar.gz: 0366aba96e46ec24ba6a769b4ba17271d29fa89ccf24bc99ca08a528e056d845
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 176cf272fcecb3fbb9e88acd9d11daaf509751265ef6eab0f4c7fddeb45c16550984525a48eb8f7e7711ba8b776bd7c34934da2c3c011c789d69970342aae6d1
|
|
7
|
+
data.tar.gz: 266c6471e7c5d11e0933edce3f639add0bf0a0252c8ab43253af0e5eae6652cc03018edcfd1b7540b7954a3a11b4c5626509741538cded0dcba97008253fd043
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.0] - 2026-04-16
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `Schema#array(name, item_type:, separator:, required:, default:)` for parsing delimited ENV values as lists with per-element type casting (`:string`, `:integer`, `:float`, `:boolean`)
|
|
14
|
+
|
|
15
|
+
## [0.3.0] - 2026-04-10
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- `prefix:` option for `EnvValidator.define` to group related variables under a shared prefix
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- Trim `.rubocop.yml` to minimal config per guide standards
|
|
22
|
+
- Update issue templates to match guide (add gem version field, alternatives field)
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- Merge duplicate `[0.2.2]` CHANGELOG entries into single entry
|
|
26
|
+
|
|
10
27
|
## [0.2.9] - 2026-04-08
|
|
11
28
|
|
|
12
29
|
### Changed
|
|
@@ -50,8 +67,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
50
67
|
### Changed
|
|
51
68
|
- Update rubocop configuration for Windows compatibility
|
|
52
69
|
|
|
53
|
-
## [0.2.2] - 2026-03-21
|
|
54
|
-
|
|
55
70
|
### Fixed
|
|
56
71
|
- Standardize Installation section in README
|
|
57
72
|
|
data/README.md
CHANGED
|
@@ -82,6 +82,25 @@ config.key?(:PORT) # => true
|
|
|
82
82
|
config.slice(:PORT) # => { "PORT" => 3000 }
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
### Prefix
|
|
86
|
+
|
|
87
|
+
Group related variables with a shared prefix:
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
env = { "REDIS_HOST" => "localhost", "REDIS_PORT" => "6379", "REDIS_PASSWORD" => "secret" }
|
|
91
|
+
|
|
92
|
+
config = Philiprehberger::EnvValidator.define(env: env, prefix: "REDIS_") do
|
|
93
|
+
string :HOST, required: true
|
|
94
|
+
integer :PORT, default: 6379
|
|
95
|
+
string :PASSWORD
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
config[:HOST] # => "localhost"
|
|
99
|
+
config[:PORT] # => 6379
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The prefix is prepended when looking up each variable in the environment. Result keys use the short name (without prefix). Error messages include the full prefixed name.
|
|
103
|
+
|
|
85
104
|
### Validation Errors
|
|
86
105
|
|
|
87
106
|
```ruby
|
|
@@ -94,6 +113,30 @@ end
|
|
|
94
113
|
# Missing required variable: DATABASE_URL; Missing required variable: API_KEY
|
|
95
114
|
```
|
|
96
115
|
|
|
116
|
+
### Arrays (Delimited Lists)
|
|
117
|
+
|
|
118
|
+
Parse a delimited ENV value into an array of typed elements:
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
env = {
|
|
122
|
+
"TAGS" => "ruby,rails,hotwire",
|
|
123
|
+
"PORTS" => "3000,3001,3002",
|
|
124
|
+
"PATHS" => "/usr/bin:/usr/local/bin"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
config = Philiprehberger::EnvValidator.define(env: env) do
|
|
128
|
+
array :TAGS
|
|
129
|
+
array :PORTS, item_type: :integer
|
|
130
|
+
array :PATHS, separator: ":"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
config[:TAGS] # => ["ruby", "rails", "hotwire"]
|
|
134
|
+
config[:PORTS] # => [3000, 3001, 3002]
|
|
135
|
+
config[:PATHS] # => ["/usr/bin", "/usr/local/bin"]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Each element is stripped of surrounding whitespace and cast to `item_type`. An empty or missing ENV value yields `[]` (or the configured `default:`). If any element fails to cast a `ValidationError` is raised.
|
|
139
|
+
|
|
97
140
|
### Supported Types
|
|
98
141
|
|
|
99
142
|
| Type | Method | Accepts |
|
|
@@ -102,12 +145,14 @@ end
|
|
|
102
145
|
| Integer | `integer` | Numeric strings (`"42"`, `"-1"`) |
|
|
103
146
|
| Float | `float` | Numeric strings (`"3.14"`, `"1"`) |
|
|
104
147
|
| Boolean | `boolean` | `true/false/1/0/yes/no/on/off` (case-insensitive) |
|
|
148
|
+
| Array | `array` | Delimited string cast to a list of typed elements |
|
|
105
149
|
|
|
106
150
|
## API
|
|
107
151
|
|
|
108
152
|
| Method / Class | Description |
|
|
109
153
|
|----------------|-------------|
|
|
110
|
-
| `EnvValidator.define(env:, &block)` | Define schema and validate |
|
|
154
|
+
| `EnvValidator.define(env:, prefix:, &block)` | Define schema and validate |
|
|
155
|
+
| `Schema#array(name, item_type:, separator:, required:, default:)` | Declare a delimited list ENV var parsed into a typed array |
|
|
111
156
|
| `Result#fetch(name)` / `Result#[name]` | Get a validated value |
|
|
112
157
|
| `Result#keys` | List all defined variable names |
|
|
113
158
|
| `Result#key?(name)` | Check if a variable was defined |
|
|
@@ -52,6 +52,29 @@ module Philiprehberger
|
|
|
52
52
|
def boolean(name, required: false, default: nil, choices: nil)
|
|
53
53
|
@definitions[name.to_s] = { type: :boolean, required: required, default: default, choices: choices }
|
|
54
54
|
end
|
|
55
|
+
|
|
56
|
+
# Define an array variable parsed from a delimited string.
|
|
57
|
+
#
|
|
58
|
+
# The ENV value is split on `separator`, each element is stripped of
|
|
59
|
+
# surrounding whitespace, and each element is cast to `item_type`
|
|
60
|
+
# using the same type caster the other schema methods use.
|
|
61
|
+
#
|
|
62
|
+
# @param name [Symbol, String] the ENV variable name
|
|
63
|
+
# @param item_type [Symbol] element type (:string, :integer, :float, :boolean)
|
|
64
|
+
# @param separator [String] delimiter between elements (default: ',')
|
|
65
|
+
# @param required [Boolean] whether the variable is required
|
|
66
|
+
# @param default [Array, nil] default value if not set
|
|
67
|
+
# @return [void]
|
|
68
|
+
def array(name, item_type: :string, separator: ',', required: false, default: nil)
|
|
69
|
+
@definitions[name.to_s] = {
|
|
70
|
+
type: :array,
|
|
71
|
+
item_type: item_type,
|
|
72
|
+
separator: separator,
|
|
73
|
+
required: required,
|
|
74
|
+
default: default,
|
|
75
|
+
choices: nil
|
|
76
|
+
}
|
|
77
|
+
end
|
|
55
78
|
end
|
|
56
79
|
end
|
|
57
80
|
end
|
|
@@ -9,9 +9,11 @@ module Philiprehberger
|
|
|
9
9
|
|
|
10
10
|
# @param schema [Schema] the schema to validate against
|
|
11
11
|
# @param env [Hash] the environment hash (default: ENV)
|
|
12
|
-
|
|
12
|
+
# @param prefix [String, nil] optional prefix prepended to variable names during lookup
|
|
13
|
+
def initialize(schema, env: ENV, prefix: nil)
|
|
13
14
|
@schema = schema
|
|
14
15
|
@env = env
|
|
16
|
+
@prefix = prefix
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
# Validate and return a Result.
|
|
@@ -36,25 +38,46 @@ module Philiprehberger
|
|
|
36
38
|
private
|
|
37
39
|
|
|
38
40
|
def resolve(name, definition)
|
|
39
|
-
|
|
41
|
+
env_key = @prefix ? "#{@prefix}#{name}" : name
|
|
42
|
+
raw = @env[env_key]
|
|
40
43
|
|
|
41
|
-
return
|
|
44
|
+
return resolve_array(env_key, raw, definition) if definition[:type] == :array
|
|
45
|
+
return resolve_missing(env_key, definition) if raw.nil? || raw.empty?
|
|
42
46
|
|
|
43
|
-
value = cast(raw, definition[:type],
|
|
44
|
-
validate_choices(
|
|
47
|
+
value = cast(raw, definition[:type], env_key)
|
|
48
|
+
validate_choices(env_key, value, definition[:choices])
|
|
45
49
|
[value, nil]
|
|
46
50
|
rescue CastError => e
|
|
47
51
|
[nil, e.message]
|
|
48
52
|
end
|
|
49
53
|
|
|
50
|
-
def resolve_missing(
|
|
54
|
+
def resolve_missing(env_key, definition)
|
|
51
55
|
if definition[:required] && definition[:default].nil?
|
|
52
|
-
[nil, "Missing required variable: #{
|
|
56
|
+
[nil, "Missing required variable: #{env_key}"]
|
|
53
57
|
else
|
|
54
58
|
[definition[:default], nil]
|
|
55
59
|
end
|
|
56
60
|
end
|
|
57
61
|
|
|
62
|
+
def resolve_array(env_key, raw, definition)
|
|
63
|
+
return resolve_missing_array(env_key, definition) if raw.nil?
|
|
64
|
+
return [[], nil] if raw.empty?
|
|
65
|
+
|
|
66
|
+
elements = raw.split(definition[:separator]).map(&:strip)
|
|
67
|
+
values = elements.map { |element| cast(element, definition[:item_type], env_key) }
|
|
68
|
+
[values, nil]
|
|
69
|
+
rescue CastError => e
|
|
70
|
+
[nil, e.message]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def resolve_missing_array(env_key, definition)
|
|
74
|
+
if definition[:required] && definition[:default].nil?
|
|
75
|
+
[nil, "Missing required variable: #{env_key}"]
|
|
76
|
+
else
|
|
77
|
+
[definition[:default] || [], nil]
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
58
81
|
def validate_choices(name, value, choices)
|
|
59
82
|
return if choices.nil? || choices.include?(value)
|
|
60
83
|
|
|
@@ -18,14 +18,15 @@ module Philiprehberger
|
|
|
18
18
|
# Define and validate environment variables.
|
|
19
19
|
#
|
|
20
20
|
# @param env [Hash] the environment hash (default: ENV)
|
|
21
|
+
# @param prefix [String, nil] optional prefix prepended to variable names during lookup
|
|
21
22
|
# @yield [schema] configure the schema
|
|
22
23
|
# @yieldparam schema [Schema]
|
|
23
24
|
# @return [Result] validated values
|
|
24
25
|
# @raise [ValidationError] if validation fails
|
|
25
|
-
def self.define(env: ENV, &block)
|
|
26
|
+
def self.define(env: ENV, prefix: nil, &block)
|
|
26
27
|
schema = Schema.new
|
|
27
28
|
schema.instance_eval(&block)
|
|
28
|
-
Validator.new(schema, env: env).validate!
|
|
29
|
+
Validator.new(schema, env: env, prefix: prefix).validate!
|
|
29
30
|
end
|
|
30
31
|
end
|
|
31
32
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: philiprehberger-env_validator
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Philip Rehberger
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Define environment variable schemas with type casting, required/optional
|
|
14
14
|
flags, and defaults. Validates at boot time and provides typed accessors.
|