convex-env 1.0.2 → 2.0.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.
- package/README.md +47 -16
- package/dist/index.d.mts +54 -12
- package/dist/index.mjs +84 -20
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h2 align="center">Convex Env</h2>
|
|
6
|
-
<p align="center">
|
|
6
|
+
<p align="center">Type-safe access to environment variables in Convex</p>
|
|
7
7
|
|
|
8
8
|
### Overview
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Similar to [t3-env](https://github.com/t3-oss/t3-env), but native to [Convex](https://www.convex.dev).
|
|
11
11
|
|
|
12
12
|
Validators currently supported:
|
|
13
13
|
|
|
@@ -15,9 +15,9 @@ Validators currently supported:
|
|
|
15
15
|
- v.number()
|
|
16
16
|
- v.boolean()
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
You can use `v.optional()` on _any_ supported validator, see [example](#usage) below
|
|
19
19
|
|
|
20
|
-
<span style="color: red;"><strong>IMPORTANT</strong></span>: The <code>env</code> object from <code>createEnv</code> should only be used in the Convex runtime, the values on it will not be accessible client
|
|
20
|
+
<span style="color: red;"><strong>IMPORTANT</strong></span>: The <code>env</code> object from <code>createEnv</code> should only be used in the Convex runtime, the values on it will not be accessible client-side.
|
|
21
21
|
|
|
22
22
|
### Installation
|
|
23
23
|
|
|
@@ -79,7 +79,7 @@ export const createAuth = (ctx: GenericCtx<DataModel>) => {
|
|
|
79
79
|
};
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
You can
|
|
82
|
+
You can optionally pass values manually
|
|
83
83
|
|
|
84
84
|
```typescript
|
|
85
85
|
// convex/convex.env.ts
|
|
@@ -87,24 +87,55 @@ You can also pass values manually
|
|
|
87
87
|
import { createEnv } from "convex-env";
|
|
88
88
|
import { v } from "convex/values";
|
|
89
89
|
|
|
90
|
-
export const env = createEnv(
|
|
91
|
-
{
|
|
90
|
+
export const env = createEnv({
|
|
91
|
+
schema: {
|
|
92
92
|
CONVEX_SITE_URL: v.string(),
|
|
93
|
-
BETTER_AUTH_SECRET: v.string(),
|
|
94
|
-
GOOGLE_CLIENT_ID: v.string(),
|
|
95
|
-
GOOGLE_CLIENT_SECRET: v.string(),
|
|
96
93
|
MAX_REQUESTS_PER_USER: v.number(),
|
|
97
94
|
DEBUG_MODE: v.optional(v.boolean()),
|
|
98
95
|
},
|
|
99
|
-
{
|
|
96
|
+
values: {
|
|
100
97
|
CONVEX_SITE_URL: process.env.CONVEX_SITE_URL,
|
|
101
|
-
BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,
|
|
102
|
-
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
|
|
103
|
-
GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET,
|
|
104
98
|
MAX_REQUESTS_PER_USER: process.env.MAX_REQUESTS_PER_USER,
|
|
105
99
|
DEBUG_MODE: process.env.DEBUG_MODE,
|
|
106
|
-
}
|
|
107
|
-
);
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If you're running into an issue where it says an environment variable isn't found when you **know for a fact** that it is there, then you may need to use `verifyEnv` to verify the existence and type separately from the creation of the env object.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// convex/convex.env.ts
|
|
108
|
+
|
|
109
|
+
import { createEnv } from "convex-env";
|
|
110
|
+
import { v } from "convex/values";
|
|
111
|
+
|
|
112
|
+
export const schema = {
|
|
113
|
+
CONVEX_SITE_URL: v.string(),
|
|
114
|
+
MAX_REQUESTS_PER_USER: v.number(),
|
|
115
|
+
DEBUG_MODE: v.optional(v.boolean()),
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const env = createEnv({
|
|
119
|
+
schema,
|
|
120
|
+
// optional, defaults to process.env
|
|
121
|
+
values: {
|
|
122
|
+
CONVEX_SITE_URL: process.env.CONVEX_SITE_URL,
|
|
123
|
+
MAX_REQUESTS_PER_USER: process.env.MAX_REQUESTS_PER_USER,
|
|
124
|
+
DEBUG_MODE: process.env.DEBUG_MODE,
|
|
125
|
+
},
|
|
126
|
+
options: {
|
|
127
|
+
skipValidation: true,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// convex/convex.config.ts
|
|
134
|
+
|
|
135
|
+
import { schema } from "./convex.env";
|
|
136
|
+
import { verifyEnv } from "convex-env";
|
|
137
|
+
|
|
138
|
+
verifyEnv(schema);
|
|
108
139
|
```
|
|
109
140
|
|
|
110
141
|
### Why use it?
|
package/dist/index.d.mts
CHANGED
|
@@ -5,15 +5,18 @@ type AllowedPrimitiveValidators = VString | VFloat64 | VBoolean;
|
|
|
5
5
|
type AllowedOptionalValidators = VOptional<AllowedPrimitiveValidators>;
|
|
6
6
|
type AllowedValidators = AllowedPrimitiveValidators | AllowedOptionalValidators;
|
|
7
7
|
type InferredOuput<V extends AllowedValidators> = Infer<V>;
|
|
8
|
+
type Values<Schema> = Partial<Record<keyof Schema, string | undefined>>;
|
|
9
|
+
type CreateEnvOptions = {
|
|
10
|
+
skipValidation?: boolean;
|
|
11
|
+
};
|
|
8
12
|
//#endregion
|
|
9
13
|
//#region src/index.d.ts
|
|
10
14
|
/**
|
|
11
|
-
* WARNING: The object returned by `createEnv` should only be accessed within the Convex runtime.
|
|
12
|
-
* The values on the returned object will NOT be accessible client side.
|
|
13
15
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* @
|
|
16
|
+
* WARNING: The object returned by `createEnv` should only be accessed within the Convex runtime. The values on the returned object will NOT be accessible client-side.
|
|
17
|
+
*
|
|
18
|
+
* @param args - You can either pass in the schema object directly, or an object with the schema, values, and options. See examples below.
|
|
19
|
+
* @returns An object with the same keys as the schema, but with validated type-safe values.
|
|
17
20
|
*
|
|
18
21
|
* @public
|
|
19
22
|
*
|
|
@@ -26,16 +29,55 @@ type InferredOuput<V extends AllowedValidators> = Infer<V>;
|
|
|
26
29
|
*
|
|
27
30
|
* @example
|
|
28
31
|
* const env = createEnv({
|
|
32
|
+
* schema: {
|
|
33
|
+
* FOO: v.string(),
|
|
34
|
+
* BAR: v.number(),
|
|
35
|
+
* BAZ: v.optional(v.boolean()),
|
|
36
|
+
* },
|
|
37
|
+
* values: {
|
|
38
|
+
* FOO: process.env.FOO,
|
|
39
|
+
* BAR: "42",
|
|
40
|
+
* BAZ: "true",
|
|
41
|
+
* },
|
|
42
|
+
* options: {
|
|
43
|
+
* skipValidation: true,
|
|
44
|
+
* },
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
declare const createEnv: <Schema extends Record<string, AllowedValidators>>(args: Schema | {
|
|
49
|
+
schema: Schema;
|
|
50
|
+
values?: Values<Schema>;
|
|
51
|
+
options?: CreateEnvOptions;
|
|
52
|
+
}) => { [K in keyof Schema]: InferredOuput<Schema[K]> };
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @description You may want to verify the existence and type of the environment variables separately from the creation of the env object. If so, use this function in convex.config.ts, and use the skipValidation option when calling createEnv.
|
|
56
|
+
*
|
|
57
|
+
* @param args - You can either pass in the schema object directly, or an object with the schema and values. See examples below.
|
|
58
|
+
* @returns void
|
|
59
|
+
*
|
|
60
|
+
* @public
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* const schema = {
|
|
29
64
|
* FOO: v.string(),
|
|
30
65
|
* BAR: v.number(),
|
|
31
66
|
* BAZ: v.boolean(),
|
|
32
|
-
* }
|
|
33
|
-
*
|
|
34
|
-
* BAR: process.env.BAR,
|
|
35
|
-
* BAZ: process.env.BAZ,
|
|
36
|
-
* });
|
|
67
|
+
* };
|
|
68
|
+
* verifyEnv(schema);
|
|
37
69
|
*
|
|
70
|
+
* @example
|
|
71
|
+
* const schema = {
|
|
72
|
+
* FOO: v.string(),
|
|
73
|
+
* BAR: v.number(),
|
|
74
|
+
* BAZ: v.boolean(),
|
|
75
|
+
* };
|
|
76
|
+
* verifyEnv({ schema, values: { FOO: process.env.FOO, BAR: "42", BAZ: "true" } });
|
|
38
77
|
*/
|
|
39
|
-
declare const
|
|
78
|
+
declare const verifyEnv: <Schema extends Record<string, AllowedValidators>>(args: Schema | {
|
|
79
|
+
schema: Schema;
|
|
80
|
+
values?: Values<Schema>;
|
|
81
|
+
}) => void;
|
|
40
82
|
//#endregion
|
|
41
|
-
export { createEnv };
|
|
83
|
+
export { createEnv, verifyEnv };
|
package/dist/index.mjs
CHANGED
|
@@ -24,12 +24,11 @@ const validateAndTransformBoolean = (value) => {
|
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region src/index.ts
|
|
26
26
|
/**
|
|
27
|
-
* WARNING: The object returned by `createEnv` should only be accessed within the Convex runtime.
|
|
28
|
-
* The values on the returned object will NOT be accessible client side.
|
|
29
27
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* @
|
|
28
|
+
* WARNING: The object returned by `createEnv` should only be accessed within the Convex runtime. The values on the returned object will NOT be accessible client-side.
|
|
29
|
+
*
|
|
30
|
+
* @param args - You can either pass in the schema object directly, or an object with the schema, values, and options. See examples below.
|
|
31
|
+
* @returns An object with the same keys as the schema, but with validated type-safe values.
|
|
33
32
|
*
|
|
34
33
|
* @public
|
|
35
34
|
*
|
|
@@ -42,25 +41,42 @@ const validateAndTransformBoolean = (value) => {
|
|
|
42
41
|
*
|
|
43
42
|
* @example
|
|
44
43
|
* const env = createEnv({
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
44
|
+
* schema: {
|
|
45
|
+
* FOO: v.string(),
|
|
46
|
+
* BAR: v.number(),
|
|
47
|
+
* BAZ: v.optional(v.boolean()),
|
|
48
|
+
* },
|
|
49
|
+
* values: {
|
|
50
|
+
* FOO: process.env.FOO,
|
|
51
|
+
* BAR: "42",
|
|
52
|
+
* BAZ: "true",
|
|
53
|
+
* },
|
|
54
|
+
* options: {
|
|
55
|
+
* skipValidation: true,
|
|
56
|
+
* },
|
|
52
57
|
* });
|
|
53
58
|
*
|
|
54
59
|
*/
|
|
55
|
-
const createEnv = (
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
const createEnv = (args) => {
|
|
61
|
+
let schema;
|
|
62
|
+
let inputValues;
|
|
63
|
+
let options;
|
|
64
|
+
const isSchemaObject = (arg) => {
|
|
65
|
+
return "schema" in arg;
|
|
66
|
+
};
|
|
67
|
+
if (isSchemaObject(args)) {
|
|
68
|
+
schema = args.schema;
|
|
69
|
+
inputValues = args.values;
|
|
70
|
+
options = args.options;
|
|
71
|
+
} else schema = args;
|
|
72
|
+
const values = inputValues ?? process.env;
|
|
73
|
+
return Object.keys(schema).map((key) => {
|
|
58
74
|
try {
|
|
59
|
-
const validator =
|
|
60
|
-
const envValue =
|
|
61
|
-
if (validator.isOptional === "required" && envValue === void 0) throw new Error("Variable is required but not found in env");
|
|
75
|
+
const validator = schema[key];
|
|
76
|
+
const envValue = values[key];
|
|
77
|
+
if (validator.isOptional === "required" && envValue === void 0 && options?.skipValidation !== true) throw new Error("Variable is required but not found in env");
|
|
62
78
|
const transformedValue = transformed(envValue, validator);
|
|
63
|
-
if (validate(validator, transformedValue) === false) throw new Error(`Variable failed validation`);
|
|
79
|
+
if (validate(validator, transformedValue) === false && options?.skipValidation !== true) throw new Error(`Variable failed validation`);
|
|
64
80
|
return [key, transformedValue];
|
|
65
81
|
} catch (error) {
|
|
66
82
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -71,6 +87,54 @@ const createEnv = (entries, inputEnv) => {
|
|
|
71
87
|
return acc;
|
|
72
88
|
}, {});
|
|
73
89
|
};
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
* @description You may want to verify the existence and type of the environment variables separately from the creation of the env object. If so, use this function in convex.config.ts, and use the skipValidation option when calling createEnv.
|
|
93
|
+
*
|
|
94
|
+
* @param args - You can either pass in the schema object directly, or an object with the schema and values. See examples below.
|
|
95
|
+
* @returns void
|
|
96
|
+
*
|
|
97
|
+
* @public
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const schema = {
|
|
101
|
+
* FOO: v.string(),
|
|
102
|
+
* BAR: v.number(),
|
|
103
|
+
* BAZ: v.boolean(),
|
|
104
|
+
* };
|
|
105
|
+
* verifyEnv(schema);
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* const schema = {
|
|
109
|
+
* FOO: v.string(),
|
|
110
|
+
* BAR: v.number(),
|
|
111
|
+
* BAZ: v.boolean(),
|
|
112
|
+
* };
|
|
113
|
+
* verifyEnv({ schema, values: { FOO: process.env.FOO, BAR: "42", BAZ: "true" } });
|
|
114
|
+
*/
|
|
115
|
+
const verifyEnv = (args) => {
|
|
116
|
+
let schema;
|
|
117
|
+
let inputValues;
|
|
118
|
+
const isSchemaObject = (arg) => {
|
|
119
|
+
return "schema" in arg;
|
|
120
|
+
};
|
|
121
|
+
if (isSchemaObject(args)) {
|
|
122
|
+
schema = args.schema;
|
|
123
|
+
inputValues = args.values;
|
|
124
|
+
} else schema = args;
|
|
125
|
+
const values = inputValues ?? process.env;
|
|
126
|
+
Object.keys(schema).map((key) => {
|
|
127
|
+
try {
|
|
128
|
+
const validator = schema[key];
|
|
129
|
+
const envValue = values[key];
|
|
130
|
+
if (validator.isOptional === "required" && envValue === void 0) throw new Error("Variable is required but not found in env");
|
|
131
|
+
if (validate(validator, transformed(envValue, validator)) === false) throw new Error(`Variable failed validation`);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
134
|
+
throw new Error(`Error verifying environment variable ${key}: ${errorMessage}`);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
};
|
|
74
138
|
|
|
75
139
|
//#endregion
|
|
76
|
-
export { createEnv };
|
|
140
|
+
export { createEnv, verifyEnv };
|
package/package.json
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "convex-env",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
5
|
-
"
|
|
4
|
+
"version": "2.0.0",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "Type-safe access to environment variables in Convex",
|
|
6
7
|
"exports": {
|
|
7
8
|
".": "./dist/index.mjs",
|
|
8
9
|
"./package.json": "./package.json"
|
|
9
10
|
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"convex",
|
|
13
|
+
"env",
|
|
14
|
+
"environment variables"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/bentsignal/convex-env.git"
|
|
19
|
+
},
|
|
10
20
|
"main": "./dist/index.mjs",
|
|
11
21
|
"module": "./dist/index.mjs",
|
|
12
22
|
"types": "./dist/index.d.mts",
|