Skip to content

Commit 2043b2f

Browse files
committed
v2.0.0 🚀
1 parent 1b0f0fe commit 2043b2f

10 files changed

+423
-506
lines changed

README.md

+35-35
Original file line numberDiff line numberDiff line change
@@ -41,70 +41,70 @@ Then add `rescript-envsafe` and `rescript-struct` to `bs-dependencies` in your `
4141
```rescript
4242
%%private(let envSafe = EnvSafe.make())
4343
44-
let nodeEnv =
45-
envSafe->EnvSafe.get(
46-
~name="NODE_ENV",
47-
~struct=S.union([
48-
S.literalVariant(String("production"), #production),
49-
S.literalVariant(String("development"), #development),
50-
S.literalVariant(String("test"), #test),
51-
]),
52-
~devFallback=#development,
53-
(),
54-
)
55-
let port = envSafe->EnvSafe.get(~name="PORT", ~struct=S.int()->S.Int.port(), ~devFallback=3000, ())
56-
let apiUrl =
57-
envSafe->EnvSafe.get(
58-
~name="API_URL",
59-
~struct=S.string()->S.String.url(),
60-
~devFallback="https://example.com/graphql",
61-
(),
62-
)
63-
let auth0ClientId = envSafe->EnvSafe.get(~name="AUTH0_CLIENT_ID", ~struct=S.string(), ())
64-
let auth0Domain = envSafe->EnvSafe.get(~name="AUTH0_DOMAIN", ~struct=S.string(), ())
44+
let nodeEnv = envSafe->EnvSafe.get(
45+
~name="NODE_ENV",
46+
~struct=S.union([
47+
S.literal(#production),
48+
S.literal(#development),
49+
S.literal(#test),
50+
]),
51+
~devFallback=#development,
52+
)
53+
let port = envSafe->EnvSafe.get(
54+
~name="PORT",
55+
~struct=S.int->S.Int.port,
56+
~devFallback=3000
57+
)
58+
let apiUrl = envSafe->EnvSafe.get(
59+
~name="API_URL",
60+
~struct=S.string->S.String.url,
61+
~devFallback="https://example.com/graphql",
62+
)
63+
let auth0ClientId = envSafe->EnvSafe.get(~name="AUTH0_CLIENT_ID", ~struct=S.string)
64+
let auth0Domain = envSafe->EnvSafe.get(~name="AUTH0_DOMAIN", ~struct=S.string)
6565
6666
// 🧠 If you forget to close `envSafe` then invalid vars end up being `undefined` leading to an expected runtime error.
67-
envSafe->EnvSafe.close()
67+
envSafe->EnvSafe.close
6868
```
6969

7070
## API Reference
7171

7272
### **`EnvSafe.make`**
7373

74-
`(~env: EnvSafe.env=?, unit) => EnvSafe.t`
74+
`(~env: EnvSafe.env=?) => EnvSafe.t`
7575

7676
```rescript
77-
%%private(let envSafe = EnvSafe.make(~env=%raw("window.__ENVIRONMENT__"), ()))
77+
%%private(let envSafe = EnvSafe.make(~env=%raw("window.__ENVIRONMENT__")))
7878
```
7979

8080
Creates `envSafe` to start working with environment variables. By default it uses `process.env` as a base for plucking the vars, but it can be overridden using the `env` argument.
8181

8282
### **`EnvSafe.get`**
8383

84-
`(EnvSafe.t, ~name: string, ~struct: S.t<'value>, ~allowEmpty: bool=?, ~devFallback: 'value=?, ~input: option<string>=?, unit) => 'value`
84+
`(EnvSafe.t, ~name: string, ~struct: S.t<'value>, ~allowEmpty: bool=?, ~devFallback: 'value=?, ~input: option<string>=?) => 'value`
8585

8686
```rescript
87-
let port = envSafe->EnvSafe.get(~name="PORT", ~struct=S.int()->S.Int.port(), ~devFallback=3000, ())
87+
let port = envSafe->EnvSafe.get(~name="PORT", ~struct=S.int->S.Int.port, ~devFallback=3000)
8888
```
8989

9090
Gets an environment variable from `envSafe` applying coercion and parsing logic of `struct`.
9191

9292
#### Possible options
9393

94-
| Name | Type | Description |
95-
| ------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
96-
| `name` | `string` | Name of the environment variable |
97-
| `struct` | `S.t<'value>` | A struct created with **[rescript-struct](https://github.com/DZakh/rescript-struct)**. It's used for coercion and parsing. For bool structs coerces `"0", "1", "true", "false", "t", "f"` to boolean values. For int and float structs coerces string to number. |
98-
| `devFallback` | `'value=?` | A fallback value to use only when `NODE_ENV` is not `production`. This is handy for env vars that are required for production environments, but optional for development and testing. If you need to set fallback value for all environments, you can use `S.defaulted` on struct. |
99-
| `input` | `string=?` | As some environments don't allow you to dynamically read env vars, we can manually put it in as well. Example: `input=%raw("process.env.NEXT_PUBLIC_API_URL")`. |
100-
| `allowEmpty` | `bool=false` | Default behavior is `false` which treats empty strings as the value is missing. if explicit empty strings are OK, pass in `true`. |
94+
| Name | Type | Description |
95+
| ------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
96+
| `name` | `string` | Name of the environment variable |
97+
| `struct` | `S.t<'value>` | A struct created with **[rescript-struct](https://github.com/DZakh/rescript-struct)**. It's used for coercion and parsing. For bool structs coerces `"0", "1", "true", "false", "t", "f"` to boolean values. For int and float structs coerces string to number. |
98+
| `devFallback` | `'value=?` | A fallback value to use only when `NODE_ENV` is not `production`. This is handy for env vars that are required for production environments, but optional for development and testing. If you need to set fallback value for all environments, you can use `S.Option.getOr` on struct. |
99+
| `input` | `string=?` | As some environments don't allow you to dynamically read env vars, we can manually put it in as well. Example: `input=%raw("process.env.NEXT_PUBLIC_API_URL")`. |
100+
| `allowEmpty` | `bool=false` | Default behavior is `false` which treats empty strings as the value is missing. if explicit empty strings are OK, pass in `true`. |
101101

102102
### **`EnvSafe.close`**
103103

104-
`(EnvSafe.t, unit) => unit`
104+
`(EnvSafe.t) => unit`
105105

106106
```rescript
107-
envSafe->EnvSafe.close()
107+
envSafe->EnvSafe.close
108108
```
109109

110110
It makes a readable summary of your issues, `console.error`-log an error, `window.alert()` with information about the missing envrionment variable if you're in the browser, throws an error (will exit the process with a code 1 in node).

__tests__/EnvSafe_Example_test.res

+6-44
Original file line numberDiff line numberDiff line change
@@ -9,72 +9,34 @@ test(`Works with Example code`, t => {
99
"AUTH0_CLIENT_ID": "xxxxx",
1010
"AUTH0_DOMAIN": "xxxxx.auth0.com",
1111
}),
12-
(),
1312
)
1413

1514
t->Assert.is(
1615
envSafe->EnvSafe.get(
1716
~name="NODE_ENV",
18-
~struct=S.union([
19-
S.literalVariant(String("production"), #production),
20-
S.literalVariant(String("development"), #development),
21-
S.literalVariant(String("test"), #test),
22-
]),
17+
~struct=S.union([S.literal(#production), S.literal(#development), S.literal(#test)]),
2318
~devFallback=#development,
24-
(),
2519
),
2620
#development,
2721
(),
2822
)
2923
t->Assert.is(
30-
envSafe->EnvSafe.get(~name="PORT", ~struct=S.int()->S.Int.port(), ~devFallback=3000, ()),
24+
envSafe->EnvSafe.get(~name="PORT", ~struct=S.int->S.Int.port, ~devFallback=3000),
3125
80,
3226
(),
3327
)
3428
t->Assert.is(
3529
envSafe->EnvSafe.get(
3630
~name="API_URL",
37-
~struct=S.string()->S.String.url(),
31+
~struct=S.string->S.String.url,
3832
~devFallback="https://example.com/graphql",
39-
(),
4033
),
4134
"https://example.com/foo",
4235
(),
4336
)
44-
t->Assert.is(envSafe->EnvSafe.get(~name="AUTH0_CLIENT_ID", ~struct=S.string(), ()), "xxxxx", ())
45-
t->Assert.is(
46-
envSafe->EnvSafe.get(~name="AUTH0_DOMAIN", ~struct=S.string(), ()),
47-
"xxxxx.auth0.com",
48-
(),
49-
)
37+
t->Assert.is(envSafe->EnvSafe.get(~name="AUTH0_CLIENT_ID", ~struct=S.string), "xxxxx", ())
38+
t->Assert.is(envSafe->EnvSafe.get(~name="AUTH0_DOMAIN", ~struct=S.string), "xxxxx.auth0.com", ())
5039
t->Assert.notThrows(() => {
51-
envSafe->EnvSafe.close()
40+
envSafe->EnvSafe.close
5241
}, ())
5342
})
54-
55-
// %%private(let envSafe = EnvSafe.make())
56-
57-
// let nodeEnv =
58-
// envSafe->EnvSafe.get(
59-
// ~name="NODE_ENV",
60-
// ~struct=S.union([
61-
// S.literalVariant(String("production"), #production),
62-
// S.literalVariant(String("development"), #development),
63-
// S.literalVariant(String("test"), #test),
64-
// ]),
65-
// ~devFallback=#development,
66-
// (),
67-
// )
68-
// let port = envSafe->EnvSafe.get(~name="PORT", ~struct=S.int()->S.Int.port(), ~devFallback=3000, ())
69-
// let apiUrl =
70-
// envSafe->EnvSafe.get(
71-
// ~name="API_URL",
72-
// ~struct=S.string()->S.String.url(),
73-
// ~devFallback="https://example.com/graphql",
74-
// (),
75-
// )
76-
// let auth0ClientId = envSafe->EnvSafe.get(~name="AUTH0_CLIENT_ID", ~struct=S.string(), ())
77-
// let auth0Domain = envSafe->EnvSafe.get(~name="AUTH0_DOMAIN", ~struct=S.string(), ())
78-
79-
// // It's important to close EnvSafe to report an error and exit the process.
80-
// envSafe->EnvSafe.close()

0 commit comments

Comments
 (0)