@mrinal1224/safe-env 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mrinal Bhattacharya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,204 @@
1
+ # 🛡️ Safe Env
2
+
3
+ > Type-safe environment variable validation for Node.js & TypeScript.
4
+
5
+ Stop discovering missing or invalid `.env` variables after your application has already started. **Safe Env** validates and parses environment configuration at startup while giving you inferred TypeScript types.
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@mrinal/safe-env"><img src="https://img.shields.io/npm/v/@mrinal/safe-env?style=for-the-badge&label=npm" alt="npm version" /></a>
9
+ <a href="https://github.com/mrinal1224/Safe-Env/stargazers"><img src="https://img.shields.io/github/stars/mrinal1224/Safe-Env?style=for-the-badge" alt="GitHub stars" /></a>
10
+ <a href="https://github.com/mrinal1224/Safe-Env/blob/main/LICENSE"><img src="https://img.shields.io/github/license/mrinal1224/Safe-Env?style=for-the-badge" alt="License" /></a>
11
+ <a href="https://github.com/mrinal1224/Safe-Env/actions"><img src="https://img.shields.io/github/actions/workflow/status/mrinal1224/Safe-Env/ci.yml?branch=main&style=for-the-badge&label=CI" alt="CI status" /></a>
12
+ </p>
13
+
14
+ ---
15
+
16
+ ## 🚨 The Problem
17
+
18
+ Most Node.js applications eventually contain code like this:
19
+
20
+ ```ts
21
+ const port = process.env.PORT;
22
+ const jwtSecret = process.env.JWT_SECRET;
23
+ const databaseUrl = process.env.DATABASE_URL;
24
+ ```
25
+
26
+ Environment variables are exposed as strings and can be missing, malformed, or inconsistent with what your application expects.
27
+
28
+ Safe Env gives you one schema for both runtime validation and TypeScript inference.
29
+
30
+ ---
31
+
32
+ ## ✨ Quick Start
33
+
34
+ ```bash
35
+ npm install @mrinal/safe-env
36
+ ```
37
+
38
+ ```ts
39
+ import { createEnv, z } from "@mrinal/safe-env";
40
+
41
+ export const env = createEnv({
42
+ PORT: z.number().default(3000),
43
+ JWT_SECRET: z.string().min(32),
44
+ NODE_ENV: z.enum(["development", "production"] as const),
45
+ DEBUG: z.boolean().optional(),
46
+ });
47
+ ```
48
+
49
+ The result is inferred automatically:
50
+
51
+ ```ts
52
+ env.PORT // number
53
+ env.JWT_SECRET // string
54
+ env.NODE_ENV // "development" | "production"
55
+ env.DEBUG // boolean | undefined
56
+ ```
57
+
58
+ ---
59
+
60
+ ## 🧠 How It Works
61
+
62
+ ```text
63
+ process.env
64
+
65
+
66
+ Schema Definition
67
+
68
+
69
+ Parse + Validate
70
+
71
+ ├── ✅ Valid → Typed Config
72
+
73
+ └── ❌ Invalid → SafeEnvError
74
+ ```
75
+
76
+ Create the configuration object once and use `env` throughout the rest of your application instead of reading `process.env` everywhere.
77
+
78
+ ---
79
+
80
+ ## 🔧 Validators
81
+
82
+ | Validator | Example |
83
+ | --- | --- |
84
+ | String | `z.string()` |
85
+ | Number | `z.number()` |
86
+ | Boolean | `z.boolean()` |
87
+ | Enum | `z.enum(["development", "production"] as const)` |
88
+ | Optional | `z.string().optional()` |
89
+ | Default | `z.number().default(3000)` |
90
+ | Minimum length | `z.string().min(32)` |
91
+ | Maximum length | `z.string().max(100)` |
92
+
93
+ ---
94
+
95
+ ## ❌ Validation Errors
96
+
97
+ Safe Env validates the complete schema and reports configuration problems together, so you can fix several variables in one run.
98
+
99
+ Example:
100
+
101
+ ```text
102
+ [safe-env] environment: Invalid environment configuration:
103
+ • [safe-env] PORT: must be a valid finite number, received "abc"
104
+ • [safe-env] JWT_SECRET: Missing required environment variable: JWT_SECRET
105
+ ```
106
+
107
+ > Do not include secret values in custom error messages or logs in production.
108
+
109
+ ---
110
+
111
+ ## 📦 Package Support
112
+
113
+ Safe Env is shipped as a small TypeScript library with:
114
+
115
+ - ESM support
116
+ - CommonJS support
117
+ - Generated declaration files
118
+ - Node.js `>=20`
119
+ - No runtime dependencies
120
+
121
+ ---
122
+
123
+ ## 🧪 Development
124
+
125
+ ```bash
126
+ git clone https://github.com/mrinal1224/Safe-Env.git
127
+ cd Safe-Env
128
+ npm install
129
+ npm run typecheck
130
+ npm test
131
+ npm run build
132
+ ```
133
+
134
+ For coverage:
135
+
136
+ ```bash
137
+ npm run coverage
138
+ ```
139
+
140
+ GitHub Actions runs typechecking, tests and the package build for pushes to `main` and pull requests.
141
+
142
+ ---
143
+
144
+ ## 🗺️ Roadmap
145
+
146
+ ### v0.1
147
+
148
+ - [x] Runtime parsing
149
+ - [x] String / number / boolean validators
150
+ - [x] Enum validator
151
+ - [x] Optional values
152
+ - [x] Default values
153
+ - [x] String length constraints
154
+ - [x] Aggregated validation errors
155
+ - [x] Type inference
156
+ - [x] ESM + CommonJS package exports
157
+
158
+ ### v0.2
159
+
160
+ - [ ] URL validator
161
+ - [ ] Email validator
162
+ - [ ] Regex validator
163
+ - [ ] Custom validators
164
+ - [ ] Transformations
165
+ - [ ] Nested configuration
166
+ - [ ] Better error metadata
167
+
168
+ ### v1.0
169
+
170
+ - [ ] Stable API
171
+ - [ ] Comprehensive integration tests
172
+ - [ ] Documentation site
173
+ - [ ] Automated semantic releases
174
+ - [ ] NestJS integration
175
+
176
+ ---
177
+
178
+ ## 🤝 Contributing
179
+
180
+ Contributions are welcome. Please keep the public API small and predictable.
181
+
182
+ Before opening a pull request:
183
+
184
+ ```bash
185
+ npm run typecheck
186
+ npm test
187
+ npm run build
188
+ ```
189
+
190
+ ---
191
+
192
+ ## 👨‍💻 Creator
193
+
194
+ **Mrinal Bhattacharya**
195
+
196
+ Software Engineer · Educator · Open Source Builder
197
+
198
+ GitHub: [@mrinal1224](https://github.com/mrinal1224)
199
+
200
+ ---
201
+
202
+ ## 📄 License
203
+
204
+ MIT © 2026 Mrinal Bhattacharya
package/dist/index.cjs ADDED
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ SafeEnvError: () => SafeEnvError,
24
+ createEnv: () => createEnv,
25
+ z: () => z
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+
29
+ // src/errors.ts
30
+ var SafeEnvError = class extends Error {
31
+ key;
32
+ constructor(key, message) {
33
+ super(`[safe-env] ${key}: ${message}`);
34
+ this.name = "SafeEnvError";
35
+ this.key = key;
36
+ }
37
+ };
38
+
39
+ // src/createEnv.ts
40
+ function createEnv(schema, source = process.env) {
41
+ const result = {};
42
+ const errors = [];
43
+ for (const [key, validator] of Object.entries(schema)) {
44
+ try {
45
+ result[key] = validator.parse(source[key], key);
46
+ } catch (error) {
47
+ if (error instanceof SafeEnvError) {
48
+ errors.push(error);
49
+ continue;
50
+ }
51
+ if (error instanceof Error) {
52
+ throw error;
53
+ }
54
+ throw new Error(String(error));
55
+ }
56
+ }
57
+ if (errors.length > 0) {
58
+ const message = errors.map((error) => ` \u2022 ${error.message}`).join("\n");
59
+ throw new SafeEnvError("environment", `Invalid environment configuration:
60
+ ${message}`);
61
+ }
62
+ return result;
63
+ }
64
+
65
+ // src/validators/base.ts
66
+ var BaseValidator = class {
67
+ isOptional = false;
68
+ hasDefault = false;
69
+ defaultValue;
70
+ __safeEnvOutput;
71
+ __safeEnvOptional;
72
+ optional() {
73
+ this.isOptional = true;
74
+ return this;
75
+ }
76
+ default(value) {
77
+ this.defaultValue = value;
78
+ this.hasDefault = true;
79
+ return this;
80
+ }
81
+ resolveUndefined(key) {
82
+ if (this.hasDefault) {
83
+ return this.defaultValue;
84
+ }
85
+ if (this.isOptional) {
86
+ return void 0;
87
+ }
88
+ throw new Error(`[safe-env] Missing required environment variable: ${key}`);
89
+ }
90
+ };
91
+
92
+ // src/validators/boolean.ts
93
+ var BooleanValidator = class extends BaseValidator {
94
+ parse(value, key) {
95
+ if (value === void 0) {
96
+ return this.resolveUndefined(key);
97
+ }
98
+ if (value === "true") return true;
99
+ if (value === "false") return false;
100
+ throw new SafeEnvError(
101
+ key,
102
+ `must be "true" or "false", received ${JSON.stringify(value)}`
103
+ );
104
+ }
105
+ };
106
+
107
+ // src/validators/enum.ts
108
+ var EnumValidator = class extends BaseValidator {
109
+ constructor(values) {
110
+ super();
111
+ this.values = values;
112
+ }
113
+ values;
114
+ parse(value, key) {
115
+ if (value === void 0) {
116
+ return this.resolveUndefined(key);
117
+ }
118
+ if (this.values.includes(value)) {
119
+ return value;
120
+ }
121
+ throw new SafeEnvError(
122
+ key,
123
+ `must be one of ${this.values.map((item) => JSON.stringify(item)).join(", ")}, received ${JSON.stringify(value)}`
124
+ );
125
+ }
126
+ };
127
+
128
+ // src/validators/number.ts
129
+ var NumberValidator = class extends BaseValidator {
130
+ parse(value, key) {
131
+ if (value === void 0) {
132
+ return this.resolveUndefined(key);
133
+ }
134
+ const parsed = Number(value);
135
+ if (!Number.isFinite(parsed)) {
136
+ throw new SafeEnvError(key, `must be a valid finite number, received ${JSON.stringify(value)}`);
137
+ }
138
+ return parsed;
139
+ }
140
+ };
141
+
142
+ // src/validators/string.ts
143
+ var StringValidator = class extends BaseValidator {
144
+ minLength;
145
+ maxLength;
146
+ min(length) {
147
+ this.minLength = length;
148
+ return this;
149
+ }
150
+ max(length) {
151
+ this.maxLength = length;
152
+ return this;
153
+ }
154
+ parse(value, key) {
155
+ if (value === void 0) {
156
+ return this.resolveUndefined(key);
157
+ }
158
+ if (this.minLength !== void 0 && value.length < this.minLength) {
159
+ throw new SafeEnvError(
160
+ key,
161
+ `must be at least ${this.minLength} characters long`
162
+ );
163
+ }
164
+ if (this.maxLength !== void 0 && value.length > this.maxLength) {
165
+ throw new SafeEnvError(
166
+ key,
167
+ `must be at most ${this.maxLength} characters long`
168
+ );
169
+ }
170
+ return value;
171
+ }
172
+ };
173
+
174
+ // src/index.ts
175
+ var z = {
176
+ string: () => new StringValidator(),
177
+ number: () => new NumberValidator(),
178
+ boolean: () => new BooleanValidator(),
179
+ enum: (values) => new EnumValidator(values)
180
+ };
181
+ // Annotate the CommonJS export names for ESM import in node:
182
+ 0 && (module.exports = {
183
+ SafeEnvError,
184
+ createEnv,
185
+ z
186
+ });
187
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/createEnv.ts","../src/validators/base.ts","../src/validators/boolean.ts","../src/validators/enum.ts","../src/validators/number.ts","../src/validators/string.ts"],"sourcesContent":["import { createEnv } from \"./createEnv\";\nimport { BooleanValidator } from \"./validators/boolean\";\nimport { EnumValidator } from \"./validators/enum\";\nimport { NumberValidator } from \"./validators/number\";\nimport { StringValidator } from \"./validators/string\";\nimport type { AnyValidator, InferEnv, InferValidator } from \"./types\";\n\nexport { createEnv } from \"./createEnv\";\nexport { SafeEnvError } from \"./errors\";\nexport type { AnyValidator, InferEnv, InferValidator } from \"./types\";\n\nexport const z = {\n string: () => new StringValidator(),\n number: () => new NumberValidator(),\n boolean: () => new BooleanValidator(),\n enum: <const T extends readonly string[]>(values: T) => new EnumValidator(values),\n};\n\nexport type EnvSchema = Record<string, AnyValidator>;\nexport type InferSchema<T extends EnvSchema> = InferEnv<T>;\n\nvoid createEnv;\nvoid (null as unknown as InferValidator<AnyValidator>);\n","export class SafeEnvError extends Error {\n public readonly key: string;\n\n constructor(key: string, message: string) {\n super(`[safe-env] ${key}: ${message}`);\n this.name = \"SafeEnvError\";\n this.key = key;\n }\n}\n","import { SafeEnvError } from \"./errors\";\nimport type { AnyValidator, InferEnv } from \"./types\";\n\nexport function createEnv<T extends Record<string, AnyValidator>>(\n schema: T,\n source: NodeJS.ProcessEnv = process.env,\n): InferEnv<T> {\n const result: Record<string, unknown> = {};\n const errors: SafeEnvError[] = [];\n\n for (const [key, validator] of Object.entries(schema)) {\n try {\n result[key] = validator.parse(source[key], key);\n } catch (error) {\n if (error instanceof SafeEnvError) {\n errors.push(error);\n continue;\n }\n\n if (error instanceof Error) {\n throw error;\n }\n\n throw new Error(String(error));\n }\n }\n\n if (errors.length > 0) {\n const message = errors.map((error) => ` • ${error.message}`).join(\"\\n\");\n throw new SafeEnvError(\"environment\", `Invalid environment configuration:\\n${message}`);\n }\n\n return result as InferEnv<T>;\n}\n","export abstract class BaseValidator<T> {\n protected isOptional = false;\n protected hasDefault = false;\n protected defaultValue!: T;\n\n readonly __safeEnvOutput!: T;\n readonly __safeEnvOptional!: false;\n\n optional(): OptionalValidator<T, this> {\n this.isOptional = true;\n return this as OptionalValidator<T, this>;\n }\n\n default(value: T): DefaultValidator<T, this> {\n this.defaultValue = value;\n this.hasDefault = true;\n return this as DefaultValidator<T, this>;\n }\n\n protected resolveUndefined(key: string): T | undefined {\n if (this.hasDefault) {\n return this.defaultValue;\n }\n\n if (this.isOptional) {\n return undefined;\n }\n\n throw new Error(`[safe-env] Missing required environment variable: ${key}`);\n }\n\n abstract parse(value: string | undefined, key: string): T | undefined;\n}\n\nexport type OptionalValidator<T, V extends BaseValidator<T>> = V & {\n readonly __safeEnvOptional: true;\n};\n\nexport type DefaultValidator<T, V extends BaseValidator<T>> = V & {\n readonly __safeEnvDefault: true;\n};\n","import { BaseValidator } from \"./base\";\nimport { SafeEnvError } from \"../errors\";\n\nexport class BooleanValidator extends BaseValidator<boolean> {\n parse(value: string | undefined, key: string): boolean | undefined {\n if (value === undefined) {\n return this.resolveUndefined(key);\n }\n\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n\n throw new SafeEnvError(\n key,\n `must be \"true\" or \"false\", received ${JSON.stringify(value)}`,\n );\n }\n}\n","import { BaseValidator } from \"./base\";\nimport { SafeEnvError } from \"../errors\";\n\nexport class EnumValidator<T extends readonly string[]> extends BaseValidator<T[number]> {\n constructor(private readonly values: T) {\n super();\n }\n\n parse(value: string | undefined, key: string): T[number] | undefined {\n if (value === undefined) {\n return this.resolveUndefined(key);\n }\n\n if (this.values.includes(value)) {\n return value as T[number];\n }\n\n throw new SafeEnvError(\n key,\n `must be one of ${this.values.map((item) => JSON.stringify(item)).join(\", \")}, received ${JSON.stringify(value)}`,\n );\n }\n}\n","import { BaseValidator } from \"./base\";\nimport { SafeEnvError } from \"../errors\";\n\nexport class NumberValidator extends BaseValidator<number> {\n parse(value: string | undefined, key: string): number | undefined {\n if (value === undefined) {\n return this.resolveUndefined(key);\n }\n\n const parsed = Number(value);\n\n if (!Number.isFinite(parsed)) {\n throw new SafeEnvError(key, `must be a valid finite number, received ${JSON.stringify(value)}`);\n }\n\n return parsed;\n }\n}\n","import { BaseValidator } from \"./base\";\nimport { SafeEnvError } from \"../errors\";\n\nexport class StringValidator extends BaseValidator<string> {\n private minLength?: number;\n private maxLength?: number;\n\n min(length: number): this {\n this.minLength = length;\n return this;\n }\n\n max(length: number): this {\n this.maxLength = length;\n return this;\n }\n\n parse(value: string | undefined, key: string): string | undefined {\n if (value === undefined) {\n return this.resolveUndefined(key);\n }\n\n if (this.minLength !== undefined && value.length < this.minLength) {\n throw new SafeEnvError(\n key,\n `must be at least ${this.minLength} characters long`,\n );\n }\n\n if (this.maxLength !== undefined && value.length > this.maxLength) {\n throw new SafeEnvError(\n key,\n `must be at most ${this.maxLength} characters long`,\n );\n }\n\n return value;\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,65 @@
1
+ declare abstract class BaseValidator<T> {
2
+ protected isOptional: boolean;
3
+ protected hasDefault: boolean;
4
+ protected defaultValue: T;
5
+ readonly __safeEnvOutput: T;
6
+ readonly __safeEnvOptional: false;
7
+ optional(): OptionalValidator<T, this>;
8
+ default(value: T): DefaultValidator<T, this>;
9
+ protected resolveUndefined(key: string): T | undefined;
10
+ abstract parse(value: string | undefined, key: string): T | undefined;
11
+ }
12
+ type OptionalValidator<T, V extends BaseValidator<T>> = V & {
13
+ readonly __safeEnvOptional: true;
14
+ };
15
+ type DefaultValidator<T, V extends BaseValidator<T>> = V & {
16
+ readonly __safeEnvDefault: true;
17
+ };
18
+
19
+ declare class BooleanValidator extends BaseValidator<boolean> {
20
+ parse(value: string | undefined, key: string): boolean | undefined;
21
+ }
22
+
23
+ declare class EnumValidator<T extends readonly string[]> extends BaseValidator<T[number]> {
24
+ private readonly values;
25
+ constructor(values: T);
26
+ parse(value: string | undefined, key: string): T[number] | undefined;
27
+ }
28
+
29
+ declare class NumberValidator extends BaseValidator<number> {
30
+ parse(value: string | undefined, key: string): number | undefined;
31
+ }
32
+
33
+ declare class StringValidator extends BaseValidator<string> {
34
+ private minLength?;
35
+ private maxLength?;
36
+ min(length: number): this;
37
+ max(length: number): this;
38
+ parse(value: string | undefined, key: string): string | undefined;
39
+ }
40
+
41
+ type AnyValidator = BaseValidator<unknown>;
42
+ type InferValidator<T> = T extends BaseValidator<infer Output> ? T extends {
43
+ readonly __safeEnvOptional: true;
44
+ } ? Output | undefined : Output : never;
45
+ type InferEnv<T extends Record<string, AnyValidator>> = {
46
+ [K in keyof T]: InferValidator<T[K]>;
47
+ };
48
+
49
+ declare function createEnv<T extends Record<string, AnyValidator>>(schema: T, source?: NodeJS.ProcessEnv): InferEnv<T>;
50
+
51
+ declare class SafeEnvError extends Error {
52
+ readonly key: string;
53
+ constructor(key: string, message: string);
54
+ }
55
+
56
+ declare const z: {
57
+ string: () => StringValidator;
58
+ number: () => NumberValidator;
59
+ boolean: () => BooleanValidator;
60
+ enum: <const T extends readonly string[]>(values: T) => EnumValidator<T>;
61
+ };
62
+ type EnvSchema = Record<string, AnyValidator>;
63
+ type InferSchema<T extends EnvSchema> = InferEnv<T>;
64
+
65
+ export { type AnyValidator, type EnvSchema, type InferEnv, type InferSchema, type InferValidator, SafeEnvError, createEnv, z };
@@ -0,0 +1,65 @@
1
+ declare abstract class BaseValidator<T> {
2
+ protected isOptional: boolean;
3
+ protected hasDefault: boolean;
4
+ protected defaultValue: T;
5
+ readonly __safeEnvOutput: T;
6
+ readonly __safeEnvOptional: false;
7
+ optional(): OptionalValidator<T, this>;
8
+ default(value: T): DefaultValidator<T, this>;
9
+ protected resolveUndefined(key: string): T | undefined;
10
+ abstract parse(value: string | undefined, key: string): T | undefined;
11
+ }
12
+ type OptionalValidator<T, V extends BaseValidator<T>> = V & {
13
+ readonly __safeEnvOptional: true;
14
+ };
15
+ type DefaultValidator<T, V extends BaseValidator<T>> = V & {
16
+ readonly __safeEnvDefault: true;
17
+ };
18
+
19
+ declare class BooleanValidator extends BaseValidator<boolean> {
20
+ parse(value: string | undefined, key: string): boolean | undefined;
21
+ }
22
+
23
+ declare class EnumValidator<T extends readonly string[]> extends BaseValidator<T[number]> {
24
+ private readonly values;
25
+ constructor(values: T);
26
+ parse(value: string | undefined, key: string): T[number] | undefined;
27
+ }
28
+
29
+ declare class NumberValidator extends BaseValidator<number> {
30
+ parse(value: string | undefined, key: string): number | undefined;
31
+ }
32
+
33
+ declare class StringValidator extends BaseValidator<string> {
34
+ private minLength?;
35
+ private maxLength?;
36
+ min(length: number): this;
37
+ max(length: number): this;
38
+ parse(value: string | undefined, key: string): string | undefined;
39
+ }
40
+
41
+ type AnyValidator = BaseValidator<unknown>;
42
+ type InferValidator<T> = T extends BaseValidator<infer Output> ? T extends {
43
+ readonly __safeEnvOptional: true;
44
+ } ? Output | undefined : Output : never;
45
+ type InferEnv<T extends Record<string, AnyValidator>> = {
46
+ [K in keyof T]: InferValidator<T[K]>;
47
+ };
48
+
49
+ declare function createEnv<T extends Record<string, AnyValidator>>(schema: T, source?: NodeJS.ProcessEnv): InferEnv<T>;
50
+
51
+ declare class SafeEnvError extends Error {
52
+ readonly key: string;
53
+ constructor(key: string, message: string);
54
+ }
55
+
56
+ declare const z: {
57
+ string: () => StringValidator;
58
+ number: () => NumberValidator;
59
+ boolean: () => BooleanValidator;
60
+ enum: <const T extends readonly string[]>(values: T) => EnumValidator<T>;
61
+ };
62
+ type EnvSchema = Record<string, AnyValidator>;
63
+ type InferSchema<T extends EnvSchema> = InferEnv<T>;
64
+
65
+ export { type AnyValidator, type EnvSchema, type InferEnv, type InferSchema, type InferValidator, SafeEnvError, createEnv, z };
package/dist/index.js ADDED
@@ -0,0 +1,158 @@
1
+ // src/errors.ts
2
+ var SafeEnvError = class extends Error {
3
+ key;
4
+ constructor(key, message) {
5
+ super(`[safe-env] ${key}: ${message}`);
6
+ this.name = "SafeEnvError";
7
+ this.key = key;
8
+ }
9
+ };
10
+
11
+ // src/createEnv.ts
12
+ function createEnv(schema, source = process.env) {
13
+ const result = {};
14
+ const errors = [];
15
+ for (const [key, validator] of Object.entries(schema)) {
16
+ try {
17
+ result[key] = validator.parse(source[key], key);
18
+ } catch (error) {
19
+ if (error instanceof SafeEnvError) {
20
+ errors.push(error);
21
+ continue;
22
+ }
23
+ if (error instanceof Error) {
24
+ throw error;
25
+ }
26
+ throw new Error(String(error));
27
+ }
28
+ }
29
+ if (errors.length > 0) {
30
+ const message = errors.map((error) => ` \u2022 ${error.message}`).join("\n");
31
+ throw new SafeEnvError("environment", `Invalid environment configuration:
32
+ ${message}`);
33
+ }
34
+ return result;
35
+ }
36
+
37
+ // src/validators/base.ts
38
+ var BaseValidator = class {
39
+ isOptional = false;
40
+ hasDefault = false;
41
+ defaultValue;
42
+ __safeEnvOutput;
43
+ __safeEnvOptional;
44
+ optional() {
45
+ this.isOptional = true;
46
+ return this;
47
+ }
48
+ default(value) {
49
+ this.defaultValue = value;
50
+ this.hasDefault = true;
51
+ return this;
52
+ }
53
+ resolveUndefined(key) {
54
+ if (this.hasDefault) {
55
+ return this.defaultValue;
56
+ }
57
+ if (this.isOptional) {
58
+ return void 0;
59
+ }
60
+ throw new Error(`[safe-env] Missing required environment variable: ${key}`);
61
+ }
62
+ };
63
+
64
+ // src/validators/boolean.ts
65
+ var BooleanValidator = class extends BaseValidator {
66
+ parse(value, key) {
67
+ if (value === void 0) {
68
+ return this.resolveUndefined(key);
69
+ }
70
+ if (value === "true") return true;
71
+ if (value === "false") return false;
72
+ throw new SafeEnvError(
73
+ key,
74
+ `must be "true" or "false", received ${JSON.stringify(value)}`
75
+ );
76
+ }
77
+ };
78
+
79
+ // src/validators/enum.ts
80
+ var EnumValidator = class extends BaseValidator {
81
+ constructor(values) {
82
+ super();
83
+ this.values = values;
84
+ }
85
+ values;
86
+ parse(value, key) {
87
+ if (value === void 0) {
88
+ return this.resolveUndefined(key);
89
+ }
90
+ if (this.values.includes(value)) {
91
+ return value;
92
+ }
93
+ throw new SafeEnvError(
94
+ key,
95
+ `must be one of ${this.values.map((item) => JSON.stringify(item)).join(", ")}, received ${JSON.stringify(value)}`
96
+ );
97
+ }
98
+ };
99
+
100
+ // src/validators/number.ts
101
+ var NumberValidator = class extends BaseValidator {
102
+ parse(value, key) {
103
+ if (value === void 0) {
104
+ return this.resolveUndefined(key);
105
+ }
106
+ const parsed = Number(value);
107
+ if (!Number.isFinite(parsed)) {
108
+ throw new SafeEnvError(key, `must be a valid finite number, received ${JSON.stringify(value)}`);
109
+ }
110
+ return parsed;
111
+ }
112
+ };
113
+
114
+ // src/validators/string.ts
115
+ var StringValidator = class extends BaseValidator {
116
+ minLength;
117
+ maxLength;
118
+ min(length) {
119
+ this.minLength = length;
120
+ return this;
121
+ }
122
+ max(length) {
123
+ this.maxLength = length;
124
+ return this;
125
+ }
126
+ parse(value, key) {
127
+ if (value === void 0) {
128
+ return this.resolveUndefined(key);
129
+ }
130
+ if (this.minLength !== void 0 && value.length < this.minLength) {
131
+ throw new SafeEnvError(
132
+ key,
133
+ `must be at least ${this.minLength} characters long`
134
+ );
135
+ }
136
+ if (this.maxLength !== void 0 && value.length > this.maxLength) {
137
+ throw new SafeEnvError(
138
+ key,
139
+ `must be at most ${this.maxLength} characters long`
140
+ );
141
+ }
142
+ return value;
143
+ }
144
+ };
145
+
146
+ // src/index.ts
147
+ var z = {
148
+ string: () => new StringValidator(),
149
+ number: () => new NumberValidator(),
150
+ boolean: () => new BooleanValidator(),
151
+ enum: (values) => new EnumValidator(values)
152
+ };
153
+ export {
154
+ SafeEnvError,
155
+ createEnv,
156
+ z
157
+ };
158
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/createEnv.ts","../src/validators/base.ts","../src/validators/boolean.ts","../src/validators/enum.ts","../src/validators/number.ts","../src/validators/string.ts","../src/index.ts"],"sourcesContent":["export class SafeEnvError extends Error {\n public readonly key: string;\n\n constructor(key: string, message: string) {\n super(`[safe-env] ${key}: ${message}`);\n this.name = \"SafeEnvError\";\n this.key = key;\n }\n}\n","import { SafeEnvError } from \"./errors\";\nimport type { AnyValidator, InferEnv } from \"./types\";\n\nexport function createEnv<T extends Record<string, AnyValidator>>(\n schema: T,\n source: NodeJS.ProcessEnv = process.env,\n): InferEnv<T> {\n const result: Record<string, unknown> = {};\n const errors: SafeEnvError[] = [];\n\n for (const [key, validator] of Object.entries(schema)) {\n try {\n result[key] = validator.parse(source[key], key);\n } catch (error) {\n if (error instanceof SafeEnvError) {\n errors.push(error);\n continue;\n }\n\n if (error instanceof Error) {\n throw error;\n }\n\n throw new Error(String(error));\n }\n }\n\n if (errors.length > 0) {\n const message = errors.map((error) => ` • ${error.message}`).join(\"\\n\");\n throw new SafeEnvError(\"environment\", `Invalid environment configuration:\\n${message}`);\n }\n\n return result as InferEnv<T>;\n}\n","export abstract class BaseValidator<T> {\n protected isOptional = false;\n protected hasDefault = false;\n protected defaultValue!: T;\n\n readonly __safeEnvOutput!: T;\n readonly __safeEnvOptional!: false;\n\n optional(): OptionalValidator<T, this> {\n this.isOptional = true;\n return this as OptionalValidator<T, this>;\n }\n\n default(value: T): DefaultValidator<T, this> {\n this.defaultValue = value;\n this.hasDefault = true;\n return this as DefaultValidator<T, this>;\n }\n\n protected resolveUndefined(key: string): T | undefined {\n if (this.hasDefault) {\n return this.defaultValue;\n }\n\n if (this.isOptional) {\n return undefined;\n }\n\n throw new Error(`[safe-env] Missing required environment variable: ${key}`);\n }\n\n abstract parse(value: string | undefined, key: string): T | undefined;\n}\n\nexport type OptionalValidator<T, V extends BaseValidator<T>> = V & {\n readonly __safeEnvOptional: true;\n};\n\nexport type DefaultValidator<T, V extends BaseValidator<T>> = V & {\n readonly __safeEnvDefault: true;\n};\n","import { BaseValidator } from \"./base\";\nimport { SafeEnvError } from \"../errors\";\n\nexport class BooleanValidator extends BaseValidator<boolean> {\n parse(value: string | undefined, key: string): boolean | undefined {\n if (value === undefined) {\n return this.resolveUndefined(key);\n }\n\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n\n throw new SafeEnvError(\n key,\n `must be \"true\" or \"false\", received ${JSON.stringify(value)}`,\n );\n }\n}\n","import { BaseValidator } from \"./base\";\nimport { SafeEnvError } from \"../errors\";\n\nexport class EnumValidator<T extends readonly string[]> extends BaseValidator<T[number]> {\n constructor(private readonly values: T) {\n super();\n }\n\n parse(value: string | undefined, key: string): T[number] | undefined {\n if (value === undefined) {\n return this.resolveUndefined(key);\n }\n\n if (this.values.includes(value)) {\n return value as T[number];\n }\n\n throw new SafeEnvError(\n key,\n `must be one of ${this.values.map((item) => JSON.stringify(item)).join(\", \")}, received ${JSON.stringify(value)}`,\n );\n }\n}\n","import { BaseValidator } from \"./base\";\nimport { SafeEnvError } from \"../errors\";\n\nexport class NumberValidator extends BaseValidator<number> {\n parse(value: string | undefined, key: string): number | undefined {\n if (value === undefined) {\n return this.resolveUndefined(key);\n }\n\n const parsed = Number(value);\n\n if (!Number.isFinite(parsed)) {\n throw new SafeEnvError(key, `must be a valid finite number, received ${JSON.stringify(value)}`);\n }\n\n return parsed;\n }\n}\n","import { BaseValidator } from \"./base\";\nimport { SafeEnvError } from \"../errors\";\n\nexport class StringValidator extends BaseValidator<string> {\n private minLength?: number;\n private maxLength?: number;\n\n min(length: number): this {\n this.minLength = length;\n return this;\n }\n\n max(length: number): this {\n this.maxLength = length;\n return this;\n }\n\n parse(value: string | undefined, key: string): string | undefined {\n if (value === undefined) {\n return this.resolveUndefined(key);\n }\n\n if (this.minLength !== undefined && value.length < this.minLength) {\n throw new SafeEnvError(\n key,\n `must be at least ${this.minLength} characters long`,\n );\n }\n\n if (this.maxLength !== undefined && value.length > this.maxLength) {\n throw new SafeEnvError(\n key,\n `must be at most ${this.maxLength} characters long`,\n );\n }\n\n return value;\n }\n}\n","import { createEnv } from \"./createEnv\";\nimport { BooleanValidator } from \"./validators/boolean\";\nimport { EnumValidator } from \"./validators/enum\";\nimport { NumberValidator } from \"./validators/number\";\nimport { StringValidator } from \"./validators/string\";\nimport type { AnyValidator, InferEnv, InferValidator } from \"./types\";\n\nexport { createEnv } from \"./createEnv\";\nexport { SafeEnvError } from \"./errors\";\nexport type { AnyValidator, InferEnv, InferValidator } from \"./types\";\n\nexport const z = {\n string: () => new StringValidator(),\n number: () => new NumberValidator(),\n boolean: () => new BooleanValidator(),\n enum: <const T extends readonly string[]>(values: T) => new EnumValidator(values),\n};\n\nexport type EnvSchema = Record<string, AnyValidator>;\nexport type InferSchema<T extends EnvSchema> = InferEnv<T>;\n\nvoid createEnv;\nvoid (null as unknown as InferValidator<AnyValidator>);\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@mrinal1224/safe-env",
3
+ "version": "0.1.0",
4
+ "description": "Type-safe environment variable validation for Node.js and TypeScript.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "sideEffects": false,
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "coverage": "vitest run --coverage",
27
+ "typecheck": "tsc --noEmit",
28
+ "lint": "eslint ."
29
+ },
30
+ "keywords": [
31
+ "env",
32
+ "environment-variables",
33
+ "environment",
34
+ "typescript",
35
+ "validation",
36
+ "configuration",
37
+ "nodejs",
38
+ "config"
39
+ ],
40
+ "author": "Mrinal Bhattacharya",
41
+ "license": "MIT",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/mrinal1224/Safe-Env.git"
45
+ },
46
+ "homepage": "https://github.com/mrinal1224/Safe-Env#readme",
47
+ "bugs": {
48
+ "url": "https://github.com/mrinal1224/Safe-Env/issues"
49
+ },
50
+ "engines": {
51
+ "node": ">=20"
52
+ },
53
+ "publishConfig": {
54
+ "access": "public"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^22.0.0",
58
+ "@vitest/coverage-v8": "^2.1.0",
59
+ "eslint": "^9.0.0",
60
+ "tsup": "^8.0.0",
61
+ "typescript": "^5.0.0",
62
+ "vitest": "^2.1.0"
63
+ }
64
+ }