Skip to content

Commit 22cb349

Browse files
authored
feat: add slice environment variables (#8)
1 parent 53fe8c9 commit 22cb349

10 files changed

Lines changed: 1632 additions & 228 deletions

File tree

.golangci.yml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ linters:
66
- exhaustruct
77
- wrapcheck
88
- wsl
9+
- tagalign
910
settings:
1011
lll:
1112
# Max line length, lines longer will be reported.
@@ -15,17 +16,6 @@ linters:
1516
# Tab width in spaces.
1617
# Default: 1
1718
tab-width: 1
18-
tagliatelle:
19-
# Checks the struct tag name case.
20-
case:
21-
rules:
22-
json: snake
23-
yaml: snake
24-
mapstructure: snake
25-
whatever: snake
26-
recvcheck:
27-
exclusions:
28-
- "*.UnmarshalJSON"
2919
wsl_v5:
3020
allow-first-in-block: true
3121
allow-whole-block: false

any.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,6 @@ func NewEnvAnyVariable(name string) EnvAny {
3434
}
3535
}
3636

37-
// UnmarshalJSON implements json.Unmarshaler.
38-
func (ev *EnvAny) UnmarshalJSON(b []byte) error {
39-
type Plain EnvAny
40-
41-
var rawValue Plain
42-
43-
err := json.Unmarshal(b, &rawValue)
44-
if err != nil {
45-
return err
46-
}
47-
48-
*ev = EnvAny(rawValue)
49-
50-
return nil
51-
}
52-
5337
// IsZero checks if the instance is empty.
5438
func (ev EnvAny) IsZero() bool {
5539
return (ev.Variable == nil || *ev.Variable == "") &&

environment.go

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
package goenvconf
33

44
import (
5-
"encoding/json"
65
"errors"
76
"os"
87
"strconv"
@@ -39,27 +38,6 @@ func NewEnvStringVariable(name string) EnvString {
3938
}
4039
}
4140

42-
// UnmarshalJSON implements json.Unmarshaler.
43-
func (ev *EnvString) UnmarshalJSON(b []byte) error {
44-
type Plain EnvString
45-
46-
var rawValue Plain
47-
48-
err := json.Unmarshal(b, &rawValue)
49-
if err != nil {
50-
return err
51-
}
52-
53-
value := EnvString(rawValue)
54-
if value.IsZero() {
55-
return ErrEnvironmentValueRequired
56-
}
57-
58-
*ev = value
59-
60-
return nil
61-
}
62-
6341
// IsZero checks if the instance is empty.
6442
func (ev EnvString) IsZero() bool {
6543
return (ev.Variable == nil || *ev.Variable == "") &&
@@ -185,27 +163,6 @@ func (ev EnvInt) Equal(target EnvInt) bool {
185163
(ev.Variable != nil && target.Variable != nil && *ev.Variable == *target.Variable)
186164
}
187165

188-
// UnmarshalJSON implements json.Unmarshaler.
189-
func (ev *EnvInt) UnmarshalJSON(b []byte) error {
190-
type Plain EnvInt
191-
192-
var rawValue Plain
193-
194-
err := json.Unmarshal(b, &rawValue)
195-
if err != nil {
196-
return err
197-
}
198-
199-
value := EnvInt(rawValue)
200-
if value.IsZero() {
201-
return ErrEnvironmentValueRequired
202-
}
203-
204-
*ev = value
205-
206-
return nil
207-
}
208-
209166
// Get gets literal value or from system environment.
210167
func (ev EnvInt) Get() (int64, error) {
211168
if ev.IsZero() {
@@ -310,27 +267,6 @@ func (ev EnvBool) Equal(target EnvBool) bool {
310267
(ev.Variable != nil && target.Variable != nil && *ev.Variable == *target.Variable)
311268
}
312269

313-
// UnmarshalJSON implements json.Unmarshaler.
314-
func (ev *EnvBool) UnmarshalJSON(b []byte) error {
315-
type Plain EnvBool
316-
317-
var rawValue Plain
318-
319-
err := json.Unmarshal(b, &rawValue)
320-
if err != nil {
321-
return err
322-
}
323-
324-
value := EnvBool(rawValue)
325-
if value.IsZero() {
326-
return ErrEnvironmentValueRequired
327-
}
328-
329-
*ev = value
330-
331-
return nil
332-
}
333-
334270
// Get gets literal value or from system environment.
335271
func (ev EnvBool) Get() (bool, error) {
336272
if ev.IsZero() {
@@ -435,27 +371,6 @@ func (ev EnvFloat) Equal(target EnvFloat) bool {
435371
(ev.Variable != nil && target.Variable != nil && *ev.Variable == *target.Variable)
436372
}
437373

438-
// UnmarshalJSON implements json.Unmarshaler.
439-
func (ev *EnvFloat) UnmarshalJSON(b []byte) error {
440-
type Plain EnvFloat
441-
442-
var rawValue Plain
443-
444-
err := json.Unmarshal(b, &rawValue)
445-
if err != nil {
446-
return err
447-
}
448-
449-
value := EnvFloat(rawValue)
450-
if value.IsZero() {
451-
return ErrEnvironmentValueRequired
452-
}
453-
454-
*ev = value
455-
456-
return nil
457-
}
458-
459374
// Get gets literal value or from system environment.
460375
func (ev EnvFloat) Get() (float64, error) {
461376
if ev.IsZero() {

error.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package goenvconf
2+
3+
import "fmt"
4+
5+
var (
6+
// ErrEnvironmentValueRequired occurs when both value and env fields are null or empty.
7+
ErrEnvironmentValueRequired = ParseEnvError{
8+
Code: "EmptyEnv",
9+
Detail: "require either value or env",
10+
}
11+
12+
// ErrEnvironmentVariableValueRequired the error that occurs when the value from environment variable is empty.
13+
ErrEnvironmentVariableValueRequired = ParseEnvError{
14+
Code: "EmptyVar",
15+
Detail: "the environment variable value is empty",
16+
}
17+
)
18+
19+
const (
20+
// ErrCodeParseEnvFailed is the error code when parsing environment variable failed.
21+
ErrCodeParseEnvFailed = "ParseEnvFailed"
22+
)
23+
24+
// ParseEnvError structures a detailed error for parsed env.
25+
type ParseEnvError struct {
26+
Code string `json:"code" jsonschema:"enum=EmptyEnv,enum=EmptyVar,enum=ParseEnvFailed"`
27+
Detail string `json:"detail"`
28+
Hint string `json:"hint,omitempty"`
29+
}
30+
31+
// NewParseEnvFailedError creates a [ParseEnvError] for parsing env variable errors.
32+
func NewParseEnvFailedError(detail string, hint string) ParseEnvError {
33+
return ParseEnvError{
34+
Code: ErrCodeParseEnvFailed,
35+
Detail: detail,
36+
Hint: hint,
37+
}
38+
}
39+
40+
// Error returns the error message.
41+
func (pee ParseEnvError) Error() string {
42+
if pee.Hint != "" {
43+
return fmt.Sprintf("%s: %s. Hint: %s", pee.Code, pee.Detail, pee.Hint)
44+
}
45+
46+
return pee.Code + ": " + pee.Detail
47+
}

map.go

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package goenvconf
22

33
import (
4-
"encoding/json"
54
"maps"
65
"os"
76
)
@@ -52,22 +51,6 @@ func (ev EnvMapString) Equal(target EnvMapString) bool {
5251
(ev.Value != nil && target.Value != nil && maps.Equal(ev.Value, target.Value))
5352
}
5453

55-
// UnmarshalJSON implements json.Unmarshaler.
56-
func (ev *EnvMapString) UnmarshalJSON(b []byte) error {
57-
type Plain EnvMapString
58-
59-
var rawValue Plain
60-
61-
err := json.Unmarshal(b, &rawValue)
62-
if err != nil {
63-
return err
64-
}
65-
66-
*ev = EnvMapString(rawValue)
67-
68-
return nil
69-
}
70-
7154
// Get gets literal value or from system environment.
7255
func (ev EnvMapString) Get() (map[string]string, error) {
7356
if ev.Variable != nil && *ev.Variable != "" {
@@ -142,22 +125,6 @@ func (ev EnvMapInt) Equal(target EnvMapInt) bool {
142125
(ev.Value != nil && target.Value != nil && maps.Equal(ev.Value, target.Value))
143126
}
144127

145-
// UnmarshalJSON implements json.Unmarshaler.
146-
func (ev *EnvMapInt) UnmarshalJSON(b []byte) error {
147-
type Plain EnvMapInt
148-
149-
var rawValue Plain
150-
151-
err := json.Unmarshal(b, &rawValue)
152-
if err != nil {
153-
return err
154-
}
155-
156-
*ev = EnvMapInt(rawValue)
157-
158-
return nil
159-
}
160-
161128
// Get gets literal value or from system environment.
162129
func (ev EnvMapInt) Get() (map[string]int64, error) {
163130
if ev.Variable != nil && *ev.Variable != "" {
@@ -232,22 +199,6 @@ func (ev EnvMapFloat) Equal(target EnvMapFloat) bool {
232199
(ev.Value != nil && target.Value != nil && maps.Equal(ev.Value, target.Value))
233200
}
234201

235-
// UnmarshalJSON implements json.Unmarshaler.
236-
func (ev *EnvMapFloat) UnmarshalJSON(b []byte) error {
237-
type Plain EnvMapFloat
238-
239-
var rawValue Plain
240-
241-
err := json.Unmarshal(b, &rawValue)
242-
if err != nil {
243-
return err
244-
}
245-
246-
*ev = EnvMapFloat(rawValue)
247-
248-
return nil
249-
}
250-
251202
// Get gets literal value or from system environment.
252203
func (ev EnvMapFloat) Get() (map[string]float64, error) {
253204
if ev.Variable != nil && *ev.Variable != "" {
@@ -322,22 +273,6 @@ func (ev EnvMapBool) Equal(target EnvMapBool) bool {
322273
(ev.Value != nil && target.Value != nil && maps.Equal(ev.Value, target.Value))
323274
}
324275

325-
// UnmarshalJSON implements json.Unmarshaler.
326-
func (ev *EnvMapBool) UnmarshalJSON(b []byte) error {
327-
type Plain EnvMapBool
328-
329-
var rawValue Plain
330-
331-
err := json.Unmarshal(b, &rawValue)
332-
if err != nil {
333-
return err
334-
}
335-
336-
*ev = EnvMapBool(rawValue)
337-
338-
return nil
339-
}
340-
341276
// Get gets literal value or from system environment.
342277
func (ev EnvMapBool) Get() (map[string]bool, error) {
343278
if ev.Variable != nil && *ev.Variable != "" {

map_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func TestEnvMapString_GetCustom(t *testing.T) {
6868
Name: "invalid_map_format",
6969
Input: NewEnvMapStringVariable("INVALID_MAP"),
7070
GetFunc: mockGetEnvFuncForMaps(map[string]string{"INVALID_MAP": "invalid_format_no_equals"}, false),
71-
ErrorMsg: ErrParseStringFailed.Error(),
71+
ErrorMsg: "ParseEnvFailed",
7272
},
7373
}
7474

@@ -133,7 +133,7 @@ func TestEnvMapInt_GetCustom(t *testing.T) {
133133
Name: "invalid_int_value",
134134
Input: NewEnvMapIntVariable("INVALID_MAP"),
135135
GetFunc: mockGetEnvFuncForMaps(map[string]string{"INVALID_MAP": "key=not_a_number"}, false),
136-
ErrorMsg: ErrParseStringFailed.Error(),
136+
ErrorMsg: "ParseEnvFailed",
137137
},
138138
}
139139

@@ -198,7 +198,7 @@ func TestEnvMapFloat_GetCustom(t *testing.T) {
198198
Name: "invalid_float_value",
199199
Input: NewEnvMapFloatVariable("INVALID_MAP"),
200200
GetFunc: mockGetEnvFuncForMaps(map[string]string{"INVALID_MAP": "key=not_a_float"}, false),
201-
ErrorMsg: ErrParseStringFailed.Error(),
201+
ErrorMsg: "ParseEnvFailed",
202202
},
203203
}
204204

@@ -263,7 +263,7 @@ func TestEnvMapBool_GetCustom(t *testing.T) {
263263
Name: "invalid_bool_value",
264264
Input: NewEnvMapBoolVariable("INVALID_MAP"),
265265
GetFunc: mockGetEnvFuncForMaps(map[string]string{"INVALID_MAP": "key=not_a_bool"}, false),
266-
ErrorMsg: ErrParseStringFailed.Error(),
266+
ErrorMsg: "ParseEnvFailed",
267267
},
268268
}
269269

0 commit comments

Comments
 (0)