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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7880d4b817b1eb742182c5967ba6881626978a31303900cb1e7428674beab40
4
- data.tar.gz: b20afee2c7ca8ebe026e1c10bf52126466e9d2bd2488ac2bd61c295c90e582d0
3
+ metadata.gz: cb9d6d9b1aeee1b8eb35392807aec880212627edbcbb426c8108e1056824dc07
4
+ data.tar.gz: 0366aba96e46ec24ba6a769b4ba17271d29fa89ccf24bc99ca08a528e056d845
5
5
  SHA512:
6
- metadata.gz: 44de6ab04e8c33df4a7692c96feef5da5073e72659bf1068129231e5707b60423779d180eab81c7993d7d0dcdc3e36f952ef05a4cd6ce9b5546d9c02b1a54fca
7
- data.tar.gz: db17df01d68d556079242e450ddb28cd3cfe96c737fb9cfbc1891fd2ddcd77bfc83de16da869c5cb683bf072f56adb10b8c20a05ea1da9e6b01daffa5d456bbd
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
- def initialize(schema, env: ENV)
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
- raw = @env[name]
41
+ env_key = @prefix ? "#{@prefix}#{name}" : name
42
+ raw = @env[env_key]
40
43
 
41
- return resolve_missing(name, definition) if raw.nil? || raw.empty?
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], name)
44
- validate_choices(name, value, definition[: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(name, definition)
54
+ def resolve_missing(env_key, definition)
51
55
  if definition[:required] && definition[:default].nil?
52
- [nil, "Missing required variable: #{name}"]
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
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Philiprehberger
4
4
  module EnvValidator
5
- VERSION = '0.2.9'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
@@ -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.2.9
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-09 00:00:00.000000000 Z
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.