node-safe-env 0.1.1 → 0.1.2

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 CHANGED
@@ -1,10 +1,25 @@
1
1
  # node-safe-env
2
2
 
3
- Schema-based environment loading and validation for Node.js.
3
+ Schema-based environment validation for Node.js and TypeScript.
4
4
 
5
- `node-safe-env` helps you fail fast at startup by validating environment variables
6
- with a typed schema, parsing values into runtime types, and reporting all validation
7
- issues in one error.
5
+ `node-safe-env` helps you fail fast at startup: validate env variables, parse them into typed runtime values, and get all validation issues in one clear error report.
6
+
7
+ ## Why node-safe-env?
8
+
9
+ - Fail-fast startup validation: catch config mistakes before your app starts serving traffic.
10
+ - Typed parsing: parse strings from `.env` and `process.env` into `number`, `boolean`, `Date`, arrays, and more.
11
+ - Aggregated errors: see all invalid/missing values at once.
12
+ - CLI validation: validate your env setup from scripts and CI.
13
+ - `.env.example` validation: keep examples aligned with your schema.
14
+ - Debug tracing: inspect where each value came from and how it was parsed.
15
+
16
+ ## Try It Now
17
+
18
+ ```bash
19
+ npx node-safe-env --help
20
+ npx node-safe-env validate --schema ./env.schema.ts
21
+ npx node-safe-env validate-example --schema ./env.schema.ts
22
+ ```
8
23
 
9
24
  ## Install
10
25
 
@@ -14,6 +29,8 @@ npm install node-safe-env
14
29
 
15
30
  ## Quick Start
16
31
 
32
+ Define a schema:
33
+
17
34
  ```ts
18
35
  import { createEnv, defineEnv } from "node-safe-env";
19
36
 
@@ -27,7 +44,11 @@ const schema = defineEnv({
27
44
  default: "development",
28
45
  },
29
46
  } as const);
47
+ ```
30
48
 
49
+ Use it at runtime:
50
+
51
+ ```ts
31
52
  const env = createEnv(schema);
32
53
 
33
54
  env.APP_NAME; // string
@@ -36,9 +57,25 @@ env.DEBUG; // boolean
36
57
  env.NODE_ENV; // "development" | "test" | "production"
37
58
  ```
38
59
 
39
- ## `defineEnv()`
60
+ What this gives you:
40
61
 
41
- `defineEnv()` locks schema literal types with a single top-level `as const`. Use it when you want to export or reuse a schema across modules.
62
+ - `required: true` means the value must exist.
63
+ - `default` is used when a value is missing.
64
+ - `type` controls parsing and validation.
65
+ - returned `env` is strongly typed from your schema.
66
+
67
+ ## What Is a Schema in node-safe-env?
68
+
69
+ A schema is an object where each key maps to a rule object.
70
+
71
+ Each rule describes:
72
+
73
+ - what type the value should be (`type`)
74
+ - whether it must be present (`required`)
75
+ - what to use if missing (`default`)
76
+ - optional rule-specific settings (for example enum values, array options, custom parser)
77
+
78
+ Use `defineEnv()` when you want better literal type inference and reusable exported schema modules.
42
79
 
43
80
  ```ts
44
81
  // env.schema.ts
@@ -50,50 +87,72 @@ export const schema = defineEnv({
50
87
  } as const);
51
88
  ```
52
89
 
53
- ```ts
54
- // main.ts
55
- import { createEnv } from "node-safe-env";
56
- import { schema } from "./env.schema.js";
90
+ ## CLI
57
91
 
58
- const env = createEnv(schema);
92
+ `node-safe-env` includes:
93
+
94
+ - `validate`: validate current environment values against your schema
95
+ - `validate-example`: validate `.env.example` coverage against your schema
96
+
97
+ ```bash
98
+ node-safe-env validate --schema ./env.schema.ts
99
+ node-safe-env validate-example --schema ./env.schema.ts
100
+ node-safe-env validate --schema ./dist/env.schema.js --strict
59
101
  ```
60
102
 
61
- ## Nested Schemas
103
+ ### CLI schema files
104
+
105
+ The `--schema` module supports both JavaScript and TypeScript files:
106
+
107
+ - JavaScript: `.js`, `.mjs`, `.cjs`
108
+ - TypeScript: `.ts`, `.mts`, `.cts`
109
+
110
+ Accepted export shapes:
62
111
 
63
- Schemas can be nested. Input env keys are flattened using uppercase segments joined by `_`.
112
+ - default export
113
+ - named export `schema`
114
+
115
+ ## `.env.example` Validation
116
+
117
+ Validate a real file:
64
118
 
65
119
  ```ts
66
- const env = createEnv({
67
- server: {
68
- port: { type: "port", default: 3000 },
69
- },
70
- database: {
71
- url: { type: "string", required: true },
72
- },
120
+ import { validateExampleEnvFile } from "node-safe-env";
121
+
122
+ const issues = validateExampleEnvFile(schema, {
123
+ cwd: process.cwd(),
124
+ exampleFile: ".env.example",
73
125
  });
74
126
  ```
75
127
 
76
- ```env
77
- SERVER_PORT=4000
78
- DATABASE_URL=postgres://localhost:5432/app
79
- ```
128
+ Validate an in-memory object:
80
129
 
81
130
  ```ts
82
- env.server.port; // number
83
- env.database.url; // string
131
+ import { validateExampleEnv } from "node-safe-env";
132
+
133
+ const issues = validateExampleEnv(schema, {
134
+ PORT: "",
135
+ });
84
136
  ```
85
137
 
86
- ## Loading Order
138
+ ## Common Use Cases
87
139
 
88
- When `options.source` is not provided, values are loaded and merged in this order (last one wins):
140
+ - App startup validation: load and validate env once during bootstrap.
141
+ - CI checks for `.env.example`: fail PRs when required keys are missing or stale.
142
+ - Debugging source issues: use debug/tracing output to understand where values were loaded from.
89
143
 
90
- 1. `.env`
91
- 2. `.env.local`
92
- 3. `.env.<NODE_ENV>`
93
- 4. custom file from `options.envFile`
94
- 5. `process.env`
144
+ ## Value at a Glance
95
145
 
96
- ## Supported Rule Types
146
+ `node-safe-env` is a schema-based env validator with:
147
+
148
+ - TypeScript-friendly schema inference
149
+ - CLI commands for runtime and `.env.example` validation
150
+ - structured, aggregated validation errors
151
+ - source tracing and debug visibility
152
+
153
+ ## Rule Types
154
+
155
+ Supported `type` values:
97
156
 
98
157
  - `string`
99
158
  - `number`
@@ -109,87 +168,38 @@ When `options.source` is not provided, values are loaded and merged in this orde
109
168
  - `date`
110
169
  - `custom`
111
170
 
112
- ## Email Rule
113
-
114
- ```ts
115
- const env = createEnv({
116
- ADMIN_EMAIL: { type: "email", required: true },
117
- });
118
- ```
119
-
120
- ## Date Rule
121
-
122
- `date` parses ISO-compatible values into `Date`.
123
-
124
- ```ts
125
- const env = createEnv({
126
- START_DATE: { type: "date", required: true },
127
- });
128
-
129
- env.START_DATE; // Date
130
- ```
131
-
132
- ## Custom Rule
171
+ ## Nested Schemas
133
172
 
134
- Supply a `parse` function that returns the typed value or throws for invalid input.
173
+ Schemas can be nested. Env keys are flattened with `_` between segments.
135
174
 
136
175
  ```ts
137
176
  const env = createEnv({
138
- RETRY_DELAY_MS: {
139
- type: "custom",
140
- parse: (raw) => {
141
- const n = Number(raw);
142
- if (!Number.isInteger(n) || n < 0)
143
- throw new Error("Must be a non-negative integer.");
144
- return n;
145
- },
177
+ server: {
178
+ port: { type: "port", default: 3000 },
146
179
  },
147
- });
148
-
149
- env.RETRY_DELAY_MS; // number
150
- ```
151
-
152
- If `parse` throws, `createEnv` records an `invalid_custom` validation issue with the thrown message.
153
-
154
- ## Array Rule Options
155
-
156
- Array parsing supports separator and item controls.
157
-
158
- ```ts
159
- const env = createEnv({
160
- ALLOWED_HOSTS: {
161
- type: "array",
162
- separator: "|", // default: ","
163
- trimItems: false, // default: true
164
- allowEmptyItems: true, // default: false
180
+ database: {
181
+ url: { type: "string", required: true },
165
182
  },
166
183
  });
167
184
  ```
168
185
 
169
- Defaults:
170
-
171
- - `separator`: `","`
172
- - `trimItems`: `true`
173
- - `allowEmptyItems`: `false`
174
-
175
- ## Defaults (Static and Functional)
186
+ ```env
187
+ SERVER_PORT=4000
188
+ DATABASE_URL=postgres://localhost:5432/app
189
+ ```
176
190
 
177
- Defaults go through the same parse/validation pipeline as environment input.
191
+ ## Loading Order
178
192
 
179
- ```ts
180
- const env = createEnv({
181
- PORT: { type: "port", default: 3000 },
182
- START_DATE: { type: "date", default: () => "2026-01-01" },
183
- ADMIN_EMAIL: { type: "email", default: () => "admin@example.com" },
184
- });
185
- ```
193
+ When `options.source` is not provided, values are merged in this order (last wins):
186
194
 
187
- If a functional default throws, `createEnv` returns a structured `invalid_default` validation issue.
195
+ 1. `.env`
196
+ 2. `.env.local`
197
+ 3. `.env.<NODE_ENV>`
198
+ 4. custom file from `options.envFile`
199
+ 5. `process.env`
188
200
 
189
201
  ## Debug Mode
190
202
 
191
- Enable debug reporting during `createEnv` execution.
192
-
193
203
  ```ts
194
204
  import { createEnv, type EnvDebugReport } from "node-safe-env";
195
205
 
@@ -202,118 +212,19 @@ createEnv(schema, {
202
212
  });
203
213
  ```
204
214
 
205
- Also supported:
215
+ Or:
206
216
 
207
217
  ```ts
208
- createEnv(schema, { debug: true }); // emits one report via console.info
218
+ createEnv(schema, { debug: true });
209
219
  ```
210
220
 
211
- Debug reports include:
212
-
213
- - loaded file metadata (`loadedFiles`)
214
- - per-key entries (`keys`) with source, status, default usage, and issue details
215
-
216
- Sensitive rules (`sensitive: true`) are masked as `"***"` in debug `raw` and `parsed` fields.
217
-
218
221
  ## Strict Mode
219
222
 
220
223
  ```ts
221
224
  createEnv(schema, { strict: true });
222
225
  ```
223
226
 
224
- Strict mode reports unknown environment keys as validation issues.
225
-
226
- ## Masking Sensitive Values
227
-
228
- Use `maskEnv()` to sanitize parsed env output for logs.
229
-
230
- ```ts
231
- import { createEnv, maskEnv } from "node-safe-env";
232
-
233
- const schema = {
234
- API_TOKEN: { type: "string", required: true, sensitive: true },
235
- PORT: { type: "port", default: 3000 },
236
- } as const;
237
-
238
- const env = createEnv(schema);
239
- const safeEnv = maskEnv(schema, env);
240
- ```
241
-
242
- ## Source Tracing
243
-
244
- Use `traceEnv()` when you have a source map of raw values and origin labels.
245
-
246
- ```ts
247
- import { traceEnv } from "node-safe-env";
248
-
249
- const trace = traceEnv(
250
- {
251
- PORT: { type: "port" },
252
- },
253
- {
254
- PORT: { source: "process.env", raw: "3000" },
255
- },
256
- {
257
- PORT: 3000,
258
- },
259
- );
260
- ```
261
-
262
- ## `.env.example` Validation
263
-
264
- Validate an example file against your schema:
265
-
266
- ```ts
267
- import { validateExampleEnvFile } from "node-safe-env";
268
-
269
- const issues = validateExampleEnvFile(schema, {
270
- cwd: process.cwd(),
271
- exampleFile: ".env.example",
272
- });
273
- ```
274
-
275
- Or validate an in-memory object:
276
-
277
- ```ts
278
- import { validateExampleEnv } from "node-safe-env";
279
-
280
- const issues = validateExampleEnv(schema, {
281
- PORT: "",
282
- });
283
- ```
284
-
285
- ## CLI
286
-
287
- `node-safe-env` includes a CLI with two commands.
288
-
289
- ```bash
290
- # installed locally (package.json scripts or npx)
291
- node-safe-env validate --schema ./dist/env.schema.js
292
- node-safe-env validate-example --schema ./dist/env.schema.js
293
-
294
- # one-off with npx
295
- npx node-safe-env validate --schema ./dist/env.schema.js
296
- ```
297
-
298
- `validate` options:
299
-
300
- - `--schema <path>` (required)
301
- - `--cwd <path>`
302
- - `--env-file <path>`
303
- - `--node-env <value>`
304
- - `--strict`
305
-
306
- `validate-example` options:
307
-
308
- - `--schema <path>` (required)
309
- - `--cwd <path>`
310
- - `--example-file <path>`
311
-
312
- CLI schema loading note:
313
-
314
- - the `--schema` target must be an executable JavaScript module
315
- - accepted export shapes: default export or named export `schema`
316
- - use built `.js`, `.mjs`, or `.cjs` files for CLI usage
227
+ Strict mode reports unknown environment keys as issues.
317
228
 
318
229
  ## Error Handling
319
230
 
@@ -346,7 +257,7 @@ Exports:
346
257
  - `readEnvFileSource`
347
258
  - `resolveExampleEnvPath`
348
259
 
349
- `createEnv(schema, options?)` options:
260
+ `createEnv(schema, options?)`:
350
261
 
351
262
  ```ts
352
263
  {
@@ -365,7 +276,7 @@ Exports:
365
276
  - ESM and CommonJS builds
366
277
  - TypeScript declarations included
367
278
 
368
- ## Development Scripts
279
+ ## Development
369
280
 
370
281
  ```bash
371
282
  npm run lint
@@ -378,4 +289,4 @@ npm run check
378
289
 
379
290
  ## License
380
291
 
381
- MIT
292
+ MIT
package/dist/cli.js CHANGED
@@ -793,16 +793,90 @@ function formatIssues(issues) {
793
793
  return issues.map((issue) => `- ${issue.key}: ${issue.message}`).join("\n");
794
794
  }
795
795
 
796
+ // src/cli/utils/formatCliError.ts
797
+ function formatCliError(error) {
798
+ const message = error instanceof Error ? error.message : "Unknown CLI error";
799
+ return `CLI error: ${message}`;
800
+ }
801
+
796
802
  // src/cli/utils/loadSchemaModule.ts
797
803
  import path3 from "path";
804
+ import fs2 from "fs";
798
805
  import { pathToFileURL } from "url";
806
+ var SUPPORTED_SCHEMA_EXTENSIONS = [
807
+ ".js",
808
+ ".mjs",
809
+ ".cjs",
810
+ ".ts",
811
+ ".mts",
812
+ ".cts"
813
+ ];
799
814
  function isObject(value) {
800
815
  return typeof value === "object" && value !== null;
801
816
  }
817
+ function isTypeScriptFile(filePath) {
818
+ const ext = path3.extname(filePath).toLowerCase();
819
+ return ext === ".ts" || ext === ".mts" || ext === ".cts";
820
+ }
821
+ function isSupportedSchemaFile(filePath) {
822
+ const ext = path3.extname(filePath).toLowerCase();
823
+ return SUPPORTED_SCHEMA_EXTENSIONS.includes(
824
+ ext
825
+ );
826
+ }
827
+ function assertSchemaPathIsUsable(absolutePath, schemaPath) {
828
+ if (!isSupportedSchemaFile(absolutePath)) {
829
+ throw new Error(
830
+ `Unsupported schema file type for "${schemaPath}". Supported extensions: ${SUPPORTED_SCHEMA_EXTENSIONS.join(", ")}.`
831
+ );
832
+ }
833
+ if (!fs2.existsSync(absolutePath)) {
834
+ throw new Error(
835
+ `Schema file not found: "${schemaPath}" (resolved to "${absolutePath}").`
836
+ );
837
+ }
838
+ }
839
+ async function importTypeScriptModule(absolutePath, schemaPath) {
840
+ try {
841
+ const { register } = await import("tsx/esm/api");
842
+ const api = register({
843
+ namespace: `node-safe-env:${Date.now()}:${Math.random().toString(36).slice(2)}`
844
+ });
845
+ const loaded = await (async () => {
846
+ try {
847
+ return await api.import(
848
+ pathToFileURL(absolutePath).href,
849
+ import.meta.url
850
+ );
851
+ } finally {
852
+ api.unregister();
853
+ }
854
+ })();
855
+ if (isObject(loaded)) {
856
+ return loaded;
857
+ }
858
+ return { default: loaded };
859
+ } catch (error) {
860
+ const message = error instanceof Error ? error.message : "Unknown error";
861
+ throw new Error(
862
+ `Failed to load TypeScript schema module "${schemaPath}" using tsx runtime: ${message}`
863
+ );
864
+ }
865
+ }
802
866
  async function loadSchemaModule(schemaPath) {
803
867
  const absolutePath = path3.resolve(schemaPath);
804
868
  const moduleUrl = pathToFileURL(absolutePath).href;
805
- const mod = await import(moduleUrl);
869
+ assertSchemaPathIsUsable(absolutePath, schemaPath);
870
+ const mod = isTypeScriptFile(absolutePath) ? await importTypeScriptModule(absolutePath, schemaPath) : await (async () => {
871
+ try {
872
+ return await import(moduleUrl);
873
+ } catch (error) {
874
+ const message = error instanceof Error ? error.message : "Unknown error";
875
+ throw new Error(
876
+ `Failed to import schema module "${schemaPath}": ${message}`
877
+ );
878
+ }
879
+ })();
806
880
  const schemaCandidate = mod.default ?? mod.schema;
807
881
  if (!isObject(schemaCandidate)) {
808
882
  throw new Error(
@@ -830,8 +904,7 @@ async function runValidateCommand(options) {
830
904
  console.error(formatIssues(error.issues));
831
905
  return 1;
832
906
  }
833
- const message = error instanceof Error ? error.message : "Unknown CLI error";
834
- console.error(`CLI error: ${message}`);
907
+ console.error(formatCliError(error));
835
908
  return 1;
836
909
  }
837
910
  }
@@ -927,8 +1000,7 @@ async function runValidateExampleCommand(options) {
927
1000
  console.log("\u2713 .env.example validation passed.");
928
1001
  return 0;
929
1002
  } catch (error) {
930
- const message = error instanceof Error ? error.message : "Unknown CLI error";
931
- console.error(`CLI error: ${message}`);
1003
+ console.error(formatCliError(error));
932
1004
  return 1;
933
1005
  }
934
1006
  }
@@ -946,13 +1018,22 @@ Commands:
946
1018
  validate-example Validate a .env.example file against a schema
947
1019
 
948
1020
  Options:
949
- --schema <path> Path to schema module
1021
+ --schema <path> Path to schema module (.js, .mjs, .cjs, .ts, .mts, .cts)
950
1022
  --cwd <path> Working directory for env file loading
951
1023
  --env-file <path> Custom env file path for validate
952
1024
  --node-env <value> NODE_ENV override for validate
953
1025
  --strict Enable strict mode for unknown keys
954
1026
  --example-file <path> Custom example file path for validate-example
955
1027
  --help Show this help
1028
+
1029
+ Schema module exports:
1030
+ - default export
1031
+ - named export: schema
1032
+
1033
+ Examples:
1034
+ node-safe-env validate --schema ./env.schema.ts
1035
+ node-safe-env validate-example --schema ./env.schema.ts
1036
+ node-safe-env validate --schema ./dist/env.schema.js --strict
956
1037
  `);
957
1038
  }
958
1039
  function getStringFlag(flags, name) {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/utils/parseArgs.ts","../src/errors/EnvValidationError.ts","../src/createEnv.ts","../src/flattenSchema.ts","../src/findUnknownEnvKeys.ts","../src/loadEnvFiles.ts","../src/mergeSources.ts","../src/applyTransform.ts","../src/validators/boolean.ts","../src/validators/enum.ts","../src/validators/json.ts","../src/validators/number.ts","../src/validators/port.ts","../src/validators/string.ts","../src/validators/url.ts","../src/validators/int.ts","../src/validators/float.ts","../src/validators/array.ts","../src/validators/custom.ts","../src/validators/email.ts","../src/validators/date.ts","../src/validators/index.ts","../src/parseValue.ts","../src/setNestedValue.ts","../src/cli/utils/formatIssues.ts","../src/cli/utils/loadSchemaModule.ts","../src/cli/commands/validate.ts","../src/readEnvFileSource.ts","../src/validateExampleEnv.ts","../src/validateExampleEnvFile.ts","../src/cli/commands/validateExample.ts","../src/cli/index.ts"],"sourcesContent":["export type ParsedCliArgs = {\r\n command?: string;\r\n flags: Record<string, string | boolean>;\r\n positionals: string[];\r\n};\r\n\r\nexport function parseArgs(argv: string[]): ParsedCliArgs {\r\n const [command, ...rest] = argv;\r\n\r\n const flags: Record<string, string | boolean> = {};\r\n const positionals: string[] = [];\r\n\r\n for (let index = 0; index < rest.length; index += 1) {\r\n const token = rest[index];\r\n\r\n if (!token.startsWith(\"--\")) {\r\n positionals.push(token);\r\n continue;\r\n }\r\n\r\n const flagName = token.slice(2);\r\n const next = rest[index + 1];\r\n\r\n if (!next || next.startsWith(\"--\")) {\r\n flags[flagName] = true;\r\n continue;\r\n }\r\n\r\n flags[flagName] = next;\r\n index += 1;\r\n }\r\n\r\n return {\r\n command,\r\n flags,\r\n positionals,\r\n };\r\n}\r\n","import type { EnvValidationIssue } from \"../types/schema\";\n\nexport class EnvValidationError extends Error {\n public readonly issues: EnvValidationIssue[];\n\n constructor(issues: EnvValidationIssue[]) {\n super(\n [\n \"Environment validation failed:\",\n ...issues.map((issue) => `- [${issue.code}] ${issue.message}`),\n ].join(\"\\n\"),\n );\n\n this.name = \"EnvValidationError\";\n this.issues = issues;\n }\n}\n","import { EnvValidationError } from \"./errors/EnvValidationError\";\nimport path from \"node:path\";\nimport { findUnknownEnvKeys } from \"./findUnknownEnvKeys\";\nimport { flattenSchema } from \"./flattenSchema\";\nimport { loadEnvFiles } from \"./loadEnvFiles\";\nimport { mergeSources } from \"./mergeSources\";\nimport { parseValue } from \"./parseValue\";\nimport { setNestedValue } from \"./setNestedValue\";\nimport type {\n CreateEnvOptions,\n EnvDebugDefaultKind,\n EnvDebugKeyEntry,\n EnvDebugLoadedFile,\n EnvDebugReport,\n EnvDebugSource,\n EnvRule,\n EnvSchema,\n EnvValidationIssue,\n EnvValueSource,\n LoadedEnvFiles,\n ParsedEnv,\n} from \"./types/schema\";\n\nfunction isEmptyString(value: string): boolean {\n return value.trim() === \"\";\n}\n\nfunction defaultToRawValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n return JSON.stringify(value);\n}\n\nfunction resolveDefaultValue(value: unknown): unknown {\n return typeof value === \"function\" ? (value as () => unknown)() : value;\n}\n\nfunction parseDefaultValue(\n envKey: string,\n rule: EnvRule,\n): ReturnType<typeof parseValue> & {\n defaultKind: EnvDebugDefaultKind;\n rawDefault?: string;\n} {\n const defaultKind: EnvDebugDefaultKind =\n typeof rule.default === \"function\" ? \"function\" : \"static\";\n let resolvedDefault: unknown;\n\n try {\n resolvedDefault = resolveDefaultValue(rule.default);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n issue: {\n key: envKey,\n code: \"invalid_default\",\n message: `Default function for \"${envKey}\" threw an error: ${message}`,\n },\n defaultKind,\n };\n }\n\n const rawDefault = defaultToRawValue(resolvedDefault);\n\n return {\n ...parseValue(envKey, rawDefault, rule),\n defaultKind,\n rawDefault,\n };\n}\n\ntype SourceTrace = Record<string, { source: EnvValueSource; raw: string }>;\n\nfunction countKeys(source: Record<string, string | undefined>): number {\n return Object.values(source).filter((value) => typeof value === \"string\")\n .length;\n}\n\nfunction buildLoadedFileReport(\n loadedFiles: LoadedEnvFiles,\n cwd: string,\n nodeEnv: string,\n envFile?: string,\n): EnvDebugLoadedFile[] {\n return [\n {\n source: \".env\",\n path: path.join(cwd, \".env\"),\n keyCount: countKeys(loadedFiles.base),\n },\n {\n source: \".env.local\",\n path: path.join(cwd, \".env.local\"),\n keyCount: countKeys(loadedFiles.local),\n },\n {\n source: \".env.environment\",\n path: path.join(cwd, `.env.${nodeEnv}`),\n keyCount: countKeys(loadedFiles.environment),\n },\n {\n source: \"custom\",\n path: envFile ? path.resolve(cwd, envFile) : undefined,\n keyCount: countKeys(loadedFiles.custom),\n },\n ];\n}\n\nfunction buildSourceTrace(\n loadedFiles: LoadedEnvFiles,\n runtimeValues: Record<string, string | undefined>,\n): SourceTrace {\n const trace: SourceTrace = Object.create(null) as SourceTrace;\n\n const applySource = (\n source: Record<string, string | undefined>,\n label: EnvValueSource,\n ): void => {\n for (const [key, raw] of Object.entries(source)) {\n if (typeof raw === \"string\") {\n trace[key] = { source: label, raw };\n }\n }\n };\n\n applySource(loadedFiles.base, \".env\");\n applySource(loadedFiles.local, \".env.local\");\n applySource(loadedFiles.environment, \".env.environment\");\n applySource(loadedFiles.custom, \"custom\");\n applySource(runtimeValues, \"process.env\");\n\n return trace;\n}\n\nfunction maskDebugValue(value: unknown, sensitive: boolean): unknown {\n if (value === undefined) {\n return undefined;\n }\n\n return sensitive ? \"***\" : value;\n}\n\nfunction resolveDebugLogger(\n debug: CreateEnvOptions[\"debug\"],\n): ((report: EnvDebugReport) => void) | undefined {\n if (debug === true) {\n return (report: EnvDebugReport): void => {\n console.info(report);\n };\n }\n\n if (debug && typeof debug === \"object\" && debug.logger) {\n return debug.logger;\n }\n\n return undefined;\n}\n\nexport function createEnv<S extends EnvSchema>(\n schema: S,\n options: CreateEnvOptions = {},\n): ParsedEnv<S> {\n const debugEnabled = options.debug !== undefined && options.debug !== false;\n const debugLogger = debugEnabled\n ? resolveDebugLogger(options.debug)\n : undefined;\n const debugKeys: EnvDebugKeyEntry[] = [];\n\n let source: Record<string, string | undefined>;\n let loadedFileReport: EnvDebugLoadedFile[] = [];\n let sourceTrace: SourceTrace = Object.create(null) as SourceTrace;\n\n if (options.source) {\n source = options.source;\n\n if (debugEnabled) {\n for (const [key, raw] of Object.entries(source)) {\n if (typeof raw === \"string\") {\n sourceTrace[key] = { source: \"process.env\", raw };\n }\n }\n }\n } else {\n const loadedFiles = loadEnvFiles({\n cwd: options.cwd,\n nodeEnv: options.nodeEnv,\n envFile: options.envFile,\n });\n source = mergeSources(loadedFiles, process.env);\n\n if (debugEnabled) {\n const cwd = options.cwd ?? process.cwd();\n const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV ?? \"development\";\n loadedFileReport = buildLoadedFileReport(\n loadedFiles,\n cwd,\n nodeEnv,\n options.envFile,\n );\n sourceTrace = buildSourceTrace(loadedFiles, process.env);\n }\n }\n\n const issues: EnvValidationIssue[] = [];\n const result: Record<string, unknown> = {};\n const flattenedSchema = flattenSchema(schema as Record<string, unknown>);\n\n if (options.strict) {\n issues.push(\n ...findUnknownEnvKeys(schema as Record<string, unknown>, source),\n );\n }\n\n for (const entry of flattenedSchema) {\n const { path, envKey, rule } = entry;\n const currentValue = source[envKey];\n const sourceInfo = sourceTrace[envKey];\n const sensitive = rule.sensitive === true;\n const defaultKind: EnvDebugDefaultKind | undefined =\n rule.default === undefined\n ? undefined\n : typeof rule.default === \"function\"\n ? \"function\"\n : \"static\";\n\n const pushDebugEntry = (\n status: EnvDebugKeyEntry[\"status\"],\n values: {\n source: EnvDebugSource;\n usedDefault: boolean;\n raw?: string;\n parsed?: unknown;\n issue?: EnvValidationIssue;\n defaultKind?: EnvDebugDefaultKind;\n },\n ): void => {\n if (!debugEnabled) {\n return;\n }\n\n debugKeys.push({\n key: envKey,\n ruleType: rule.type,\n source: values.source,\n usedDefault: values.usedDefault,\n defaultKind: values.defaultKind,\n raw: maskDebugValue(values.raw, sensitive) as string | undefined,\n parsed: maskDebugValue(values.parsed, sensitive),\n status,\n issue: values.issue,\n });\n };\n\n if (typeof currentValue !== \"string\") {\n if (rule.default !== undefined) {\n const parsedDefault = parseDefaultValue(envKey, rule);\n\n if (parsedDefault.issue) {\n issues.push(parsedDefault.issue);\n pushDebugEntry(\"issue\", {\n source: \"default\",\n usedDefault: true,\n defaultKind: parsedDefault.defaultKind,\n raw: parsedDefault.rawDefault,\n issue: parsedDefault.issue,\n });\n continue;\n }\n\n pushDebugEntry(\"defaulted\", {\n source: \"default\",\n usedDefault: true,\n defaultKind: parsedDefault.defaultKind,\n raw: parsedDefault.rawDefault,\n parsed: parsedDefault.value,\n });\n setNestedValue(result, path, parsedDefault.value);\n continue;\n }\n\n if (rule.required) {\n const issue = {\n key: envKey,\n code: \"missing\",\n message: `Missing required environment variable \"${envKey}\".`,\n } as const;\n\n issues.push(issue);\n pushDebugEntry(\"missing\", {\n source: \"missing\",\n usedDefault: false,\n defaultKind,\n issue,\n });\n } else {\n pushDebugEntry(\"missing\", {\n source: \"missing\",\n usedDefault: false,\n defaultKind,\n });\n }\n\n continue;\n }\n\n const rawValue = currentValue;\n\n if (!rule.allowEmpty && isEmptyString(rawValue)) {\n if (rule.default !== undefined) {\n const parsedDefault = parseDefaultValue(envKey, rule);\n\n if (parsedDefault.issue) {\n issues.push(parsedDefault.issue);\n pushDebugEntry(\"issue\", {\n source: \"default\",\n usedDefault: true,\n defaultKind: parsedDefault.defaultKind,\n raw: parsedDefault.rawDefault,\n issue: parsedDefault.issue,\n });\n continue;\n }\n\n pushDebugEntry(\"defaulted\", {\n source: \"default\",\n usedDefault: true,\n defaultKind: parsedDefault.defaultKind,\n raw: parsedDefault.rawDefault,\n parsed: parsedDefault.value,\n });\n setNestedValue(result, path, parsedDefault.value);\n continue;\n }\n\n const issue = {\n key: envKey,\n code: \"empty\",\n message: `Environment variable \"${envKey}\" cannot be empty.`,\n } as const;\n\n issues.push(issue);\n pushDebugEntry(\"empty\", {\n source: sourceInfo?.source ?? \"process.env\",\n usedDefault: false,\n defaultKind,\n raw: rawValue,\n issue,\n });\n continue;\n }\n\n const parsed = parseValue(envKey, rawValue, rule);\n\n if (parsed.issue) {\n issues.push(parsed.issue);\n pushDebugEntry(\"issue\", {\n source: sourceInfo?.source ?? \"process.env\",\n usedDefault: false,\n defaultKind,\n raw: rawValue,\n issue: parsed.issue,\n });\n continue;\n }\n\n pushDebugEntry(\"parsed\", {\n source: sourceInfo?.source ?? \"process.env\",\n usedDefault: false,\n defaultKind,\n raw: rawValue,\n parsed: parsed.value,\n });\n setNestedValue(result, path, parsed.value);\n }\n\n if (debugLogger) {\n debugLogger({\n loadedFiles: loadedFileReport,\n keys: debugKeys,\n });\n }\n\n if (issues.length > 0) {\n throw new EnvValidationError(issues);\n }\n\n return result as unknown as ParsedEnv<S>;\n}\n","import type { EnvRule } from \"./types/schema\";\r\n\r\nexport type FlattenedSchemaEntry = {\r\n path: string[];\r\n envKey: string;\r\n rule: EnvRule;\r\n};\r\n\r\nfunction isEnvRule(value: unknown): value is EnvRule {\r\n return (\r\n typeof value === \"object\" &&\r\n value !== null &&\r\n \"type\" in value &&\r\n typeof (value as { type?: unknown }).type === \"string\"\r\n );\r\n}\r\n\r\nfunction toEnvKey(path: string[]): string {\r\n return path.map((segment) => segment.toUpperCase()).join(\"_\");\r\n}\r\n\r\nexport function flattenSchema(\r\n schema: Record<string, unknown>,\r\n parentPath: string[] = [],\r\n): FlattenedSchemaEntry[] {\r\n const entries: FlattenedSchemaEntry[] = [];\r\n\r\n for (const [key, value] of Object.entries(schema)) {\r\n const currentPath = [...parentPath, key];\r\n\r\n if (isEnvRule(value)) {\r\n entries.push({\r\n path: currentPath,\r\n envKey: toEnvKey(currentPath),\r\n rule: value,\r\n });\r\n\r\n continue;\r\n }\r\n\r\n if (typeof value === \"object\" && value !== null) {\r\n entries.push(\r\n ...flattenSchema(value as Record<string, unknown>, currentPath),\r\n );\r\n }\r\n }\r\n\r\n return entries;\r\n}\r\n","import { flattenSchema } from \"./flattenSchema\";\r\nimport type { EnvSource, EnvValidationIssue } from \"./types/schema\";\r\n\r\nexport function findUnknownEnvKeys(\r\n schema: Record<string, unknown>,\r\n source: EnvSource,\r\n): EnvValidationIssue[] {\r\n const knownKeys = new Set(flattenSchema(schema).map((entry) => entry.envKey));\r\n const issues: EnvValidationIssue[] = [];\r\n\r\n for (const key of Object.keys(source)) {\r\n if (source[key] === undefined) {\r\n continue;\r\n }\r\n\r\n if (knownKeys.has(key)) {\r\n continue;\r\n }\r\n\r\n issues.push({\r\n key,\r\n code: \"unknown_key\",\r\n message: `Environment variable \"${key}\" is not defined in the schema.`,\r\n });\r\n }\r\n\r\n return issues;\r\n}\r\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {\n LoadEnvFilesOptions,\n EnvSource,\n LoadedEnvFiles,\n} from \"./types/schema\";\n\nconst ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nfunction stripInlineComment(input: string): string {\n let inSingleQuote = false;\n let inDoubleQuote = false;\n let isEscaped = false;\n\n for (let index = 0; index < input.length; index += 1) {\n const char = input[index];\n\n if (isEscaped) {\n isEscaped = false;\n continue;\n }\n\n if (char === \"\\\\\") {\n isEscaped = true;\n continue;\n }\n\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (\n char === \"#\" &&\n !inSingleQuote &&\n !inDoubleQuote &&\n (index === 0 || /\\s/.test(input[index - 1] ?? \"\"))\n ) {\n return input.slice(0, index).trimEnd();\n }\n }\n\n return input.trimEnd();\n}\n\nfunction parseEnvFile(filePath: string): EnvSource {\n if (!fs.existsSync(filePath)) {\n return Object.create(null) as EnvSource;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const result = Object.create(null) as EnvSource;\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n let line = rawLine.trim();\n\n if (!line || line.startsWith(\"#\")) {\n continue;\n }\n\n if (line.startsWith(\"export \")) {\n line = line.slice(\"export \".length).trim();\n\n if (!line) {\n continue;\n }\n }\n\n const equalIndex = line.indexOf(\"=\");\n\n if (equalIndex <= 0) {\n continue;\n }\n\n const key = line.slice(0, equalIndex).trim();\n\n if (!ENV_KEY_PATTERN.test(key)) {\n continue;\n }\n\n let value = stripInlineComment(line.slice(equalIndex + 1)).trim();\n\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n result[key] = value;\n }\n\n return result;\n}\n\nexport function loadEnvFiles(\n options: LoadEnvFilesOptions = {},\n): LoadedEnvFiles {\n const cwd = options.cwd ?? process.cwd();\n const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV ?? \"development\";\n\n const base = parseEnvFile(path.join(cwd, \".env\"));\n const local = parseEnvFile(path.join(cwd, \".env.local\"));\n const environment = parseEnvFile(path.join(cwd, `.env.${nodeEnv}`));\n const custom = options.envFile\n ? parseEnvFile(path.resolve(cwd, options.envFile))\n : (Object.create(null) as EnvSource);\n\n return {\n base,\n local,\n environment,\n custom,\n };\n}\n","import type { EnvSource, LoadedEnvFiles } from \"./types/schema\";\n\nexport function mergeSources(\n files: LoadedEnvFiles,\n runtimeValues: EnvSource = process.env,\n): EnvSource {\n return Object.assign(\n Object.create(null),\n files.base,\n files.local,\n files.environment,\n files.custom,\n runtimeValues,\n ) as EnvSource;\n}\n","import type { EnvRule, EnvValidationIssue } from \"./types/schema\";\r\nimport type { ParseResult } from \"./validators\";\r\n\r\nexport function applyTransform(\r\n key: string,\r\n rule: EnvRule,\r\n result: ParseResult,\r\n): ParseResult {\r\n if (result.issue || result.value === undefined || !rule.transform) {\r\n return result;\r\n }\r\n\r\n try {\r\n return {\r\n value: rule.transform(result.value as never),\r\n };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error && error.message\r\n ? error.message\r\n : `Environment variable \"${key}\" failed transform.`;\r\n\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_custom\",\r\n message,\r\n } satisfies EnvValidationIssue,\r\n };\r\n }\r\n}\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nconst TRUE_VALUES = new Set([\"true\", \"1\", \"yes\", \"on\"]);\r\nconst FALSE_VALUES = new Set([\"false\", \"0\", \"no\", \"off\"]);\r\n\r\nexport const validateBoolean: EnvValidator = ({ key, rawValue }) => {\r\n const normalized = rawValue.trim().toLowerCase();\r\n\r\n if (TRUE_VALUES.has(normalized)) {\r\n return { value: true };\r\n }\r\n\r\n if (FALSE_VALUES.has(normalized)) {\r\n return { value: false };\r\n }\r\n\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_boolean\",\r\n message: `Environment variable \"${key}\" must be a valid boolean.`,\r\n },\r\n };\r\n};\r\n","import type { EnumRule } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nexport const validateEnum: EnvValidator = ({ key, rawValue, rule }) => {\r\n const enumRule = rule as EnumRule;\r\n\r\n if (!enumRule.values.includes(rawValue)) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_enum\",\r\n message: `Environment variable \"${key}\" must be one of: ${enumRule.values.join(\", \")}.`,\r\n },\r\n };\r\n }\r\n\r\n return { value: rawValue };\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateJson: EnvValidator = ({ key, rawValue }) => {\r\n try {\r\n const parsed = JSON.parse(rawValue);\r\n\r\n return { value: parsed };\r\n } catch {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_json\",\r\n message: `Environment variable \"${key}\" must contain valid JSON.`,\r\n },\r\n };\r\n }\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateNumber: EnvValidator = ({ key, rawValue }) => {\r\n const parsed = Number(rawValue);\r\n\r\n if (!Number.isFinite(parsed)) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_number\",\r\n message: `Environment variable \"${key}\" must be a valid number.`,\r\n },\r\n };\r\n }\r\n\r\n return { value: parsed };\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validatePort: EnvValidator = ({ key, rawValue }) => {\r\n const num = Number(rawValue);\r\n\r\n if (!Number.isInteger(num) || num < 1 || num > 65535) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_port\",\r\n message: `Environment variable \"${key}\" must be a valid port (1–65535).`,\r\n },\r\n };\r\n }\r\n\r\n return { value: num };\r\n};","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateString: EnvValidator = ({ rawValue }) => {\r\n return { value: rawValue };\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateUrl: EnvValidator = ({ key, rawValue }) => {\r\n try {\r\n new URL(rawValue);\r\n\r\n return { value: rawValue };\r\n } catch {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_url\",\r\n message: `Environment variable \"${key}\" must be a valid URL.`,\r\n },\r\n };\r\n }\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateInt: EnvValidator = ({ key, rawValue }) => {\r\n const parsed = Number(rawValue);\r\n\r\n if (!Number.isInteger(parsed)) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_number\",\r\n message: `Environment variable \"${key}\" must be a valid integer.`,\r\n },\r\n };\r\n }\r\n\r\n return { value: parsed };\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateFloat: EnvValidator = ({ key, rawValue }) => {\r\n const parsed = Number(rawValue);\r\n\r\n if (!Number.isFinite(parsed)) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_number\",\r\n message: `Environment variable \"${key}\" must be a valid float.`,\r\n },\r\n };\r\n }\r\n\r\n return { value: parsed };\r\n};\r\n","import type { ArrayRule, EnvValidationIssue } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nexport const validateArray: EnvValidator = ({ key, rawValue, rule }) => {\r\n const arrayRule = rule as ArrayRule;\r\n const separator = arrayRule.separator ?? \",\";\r\n const trimItems = arrayRule.trimItems ?? true;\r\n const allowEmptyItems = arrayRule.allowEmptyItems ?? false;\r\n const splitValues = rawValue.split(separator);\r\n\r\n const parsed = trimItems\r\n ? splitValues.map((item) => item.trim())\r\n : splitValues;\r\n\r\n if (!allowEmptyItems && parsed.some((item) => item === \"\")) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_array\",\r\n message: `Environment variable \"${key}\" cannot contain empty array items`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n return { value: parsed };\r\n};\r\n","import type { CustomRule } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nexport const validateCustom: EnvValidator = ({ key, rawValue, rule }) => {\r\n const customRule = rule as CustomRule;\r\n\r\n try {\r\n const parsed = customRule.parse(rawValue);\r\n\r\n return { value: parsed };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error && error.message\r\n ? error.message\r\n : `Environment variable \"${key}\" failed custom validation.`;\r\n\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_custom\",\r\n message,\r\n },\r\n };\r\n }\r\n};\r\n","import type { EmailRule, EnvValidationIssue } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nexport const validateEmail: EnvValidator = ({ key, rawValue, rule }) => {\r\n const emailRule = rule as EmailRule;\r\n void emailRule;\r\n\r\n const value = rawValue.trim();\r\n\r\n if (!value) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_email\",\r\n message: `Environment variable \"${key}\" must be a valid email address`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n if (/\\s/.test(value)) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_email\",\r\n message: `Environment variable \"${key}\" must be a valid email address`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n\r\n if (!emailRegex.test(value)) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_email\",\r\n message: `Environment variable \"${key}\" must be a valid email address`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n return {\r\n value,\r\n };\r\n};","import type { DateRule, EnvValidationIssue } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nfunction isValidDate(date: Date): boolean {\r\n return !Number.isNaN(date.getTime());\r\n}\r\n\r\nexport const validateDate: EnvValidator = ({ key, rawValue, rule }) => {\r\n const dateRule = rule as DateRule;\r\n void dateRule;\r\n\r\n const value = rawValue.trim();\r\n\r\n if (!value) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_date\",\r\n message: `Environment variable \"${key}\" must be a valid ISO date`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\r\n const isoDateTimeRegex =\r\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,3})?)?(Z|[+-]\\d{2}:\\d{2})$/;\r\n\r\n if (!isoDateRegex.test(value) && !isoDateTimeRegex.test(value)) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_date\",\r\n message: `Environment variable \"${key}\" must be a valid ISO date string`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n const parsed = new Date(value);\r\n\r\n if (!isValidDate(parsed)) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_date\",\r\n message: `Environment variable \"${key}\" must be a valid date`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n if (isoDateRegex.test(value)) {\r\n const [year, month, day] = value.split(\"-\").map(Number);\r\n\r\n if (\r\n parsed.getUTCFullYear() !== year ||\r\n parsed.getUTCMonth() + 1 !== month ||\r\n parsed.getUTCDate() !== day\r\n ) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_date\",\r\n message: `Environment variable \"${key}\" must be a real calendar date`,\r\n };\r\n\r\n return { issue };\r\n }\r\n }\r\n\r\n return {\r\n value: parsed,\r\n };\r\n};\r\n","import { validateBoolean } from \"./boolean\";\r\nimport { validateEnum } from \"./enum\";\r\nimport { validateJson } from \"./json\";\r\nimport { validateNumber } from \"./number\";\r\nimport { validatePort } from \"./port\";\r\nimport { validateString } from \"./string\";\r\nimport { validateUrl } from \"./url\";\r\nimport type { EnvValidator } from \"./types\";\r\nimport { validateInt } from \"./int\";\r\nimport { validateFloat } from \"./float\";\r\nimport { validateArray } from \"./array\";\r\nimport { validateCustom } from \"./custom\";\r\nimport { validateEmail } from \"./email\";\r\nimport { validateDate } from \"./date\";\r\n\r\nexport const validators = {\r\n string: validateString,\r\n number: validateNumber,\r\n boolean: validateBoolean,\r\n enum: validateEnum,\r\n url: validateUrl,\r\n port: validatePort,\r\n json: validateJson,\r\n int: validateInt,\r\n float: validateFloat,\r\n array: validateArray,\r\n custom: validateCustom,\r\n email: validateEmail,\r\n date: validateDate,\r\n} as const satisfies {\r\n string: EnvValidator;\r\n number: EnvValidator;\r\n boolean: EnvValidator;\r\n enum: EnvValidator;\r\n url: EnvValidator;\r\n port: EnvValidator;\r\n json: EnvValidator;\r\n int: EnvValidator;\r\n float: EnvValidator;\r\n array: EnvValidator;\r\n custom: EnvValidator;\r\n email: EnvValidator;\r\n date: EnvValidator;\r\n};\r\n\r\nexport type { ParseResult, EnvValidator } from \"./types\";\r\n","import { applyTransform } from \"./applyTransform\";\nimport type { EnvRule } from \"./types/schema\";\nimport { validators } from \"./validators\";\nimport type { ParseResult } from \"./validators\";\n\nexport function parseValue(\n key: string,\n rawValue: string,\n rule: EnvRule,\n): ParseResult {\n const validator = validators[rule.type];\n\n const result = validator({\n key,\n rawValue,\n rule,\n });\n\n return applyTransform(key, rule, result);\n}\n","export function setNestedValue(\r\n target: Record<string, unknown>,\r\n path: string[],\r\n value: unknown,\r\n): void {\r\n let current: Record<string, unknown> = target;\r\n\r\n for (let index = 0; index < path.length - 1; index += 1) {\r\n const segment = path[index];\r\n const existing = current[segment];\r\n\r\n if (\r\n typeof existing !== \"object\" ||\r\n existing === null ||\r\n Array.isArray(existing)\r\n ) {\r\n current[segment] = {};\r\n }\r\n\r\n current = current[segment] as Record<string, unknown>;\r\n }\r\n\r\n current[path[path.length - 1]] = value;\r\n}\r\n","import type { EnvValidationIssue } from \"../../types/schema\";\r\n\r\nexport function formatIssues(issues: EnvValidationIssue[]): string {\r\n return issues.map((issue) => `- ${issue.key}: ${issue.message}`).join(\"\\n\");\r\n}\r\n","import path from \"node:path\";\r\nimport { pathToFileURL } from \"node:url\";\r\nimport type { EnvSchema } from \"../../types/schema\";\r\n\r\ntype SchemaModule = {\r\n default?: unknown;\r\n schema?: unknown;\r\n};\r\n\r\nfunction isObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null;\r\n}\r\n\r\nexport async function loadSchemaModule(schemaPath: string): Promise<EnvSchema> {\r\n const absolutePath = path.resolve(schemaPath);\r\n const moduleUrl = pathToFileURL(absolutePath).href;\r\n\r\n const mod = (await import(moduleUrl)) as SchemaModule;\r\n\r\n const schemaCandidate = mod.default ?? mod.schema;\r\n\r\n if (!isObject(schemaCandidate)) {\r\n throw new Error(\r\n `Schema module \"${schemaPath}\" must export a schema as default export or named export \"schema\".`,\r\n );\r\n }\r\n\r\n return schemaCandidate as EnvSchema;\r\n}\r\n","import { createEnv } from \"../../createEnv\";\r\nimport { EnvValidationError } from \"../../errors/EnvValidationError\";\r\nimport { formatIssues } from \"../utils/formatIssues\";\r\nimport { loadSchemaModule } from \"../utils/loadSchemaModule\";\r\n\r\nexport type ValidateCommandOptions = {\r\n schemaPath: string;\r\n cwd?: string;\r\n envFile?: string;\r\n nodeEnv?: string;\r\n strict?: boolean;\r\n};\r\n\r\nexport async function runValidateCommand(\r\n options: ValidateCommandOptions,\r\n): Promise<number> {\r\n try {\r\n const schema = await loadSchemaModule(options.schemaPath);\r\n\r\n createEnv(schema, {\r\n cwd: options.cwd,\r\n envFile: options.envFile,\r\n nodeEnv: options.nodeEnv,\r\n strict: options.strict,\r\n });\r\n\r\n console.log(\"✓ Environment validation passed.\");\r\n return 0;\r\n } catch (error) {\r\n if (error instanceof EnvValidationError) {\r\n console.error(\"Environment validation failed:\\n\");\r\n console.error(formatIssues(error.issues));\r\n return 1;\r\n }\r\n\r\n const message =\r\n error instanceof Error ? error.message : \"Unknown CLI error\";\r\n console.error(`CLI error: ${message}`);\r\n return 1;\r\n }\r\n}","import { existsSync, readFileSync } from \"node:fs\";\r\nimport { resolve } from \"node:path\";\r\nimport type { EnvSource } from \"./types/schema\";\r\n\r\nfunction stripQuotes(value: string): string {\r\n if (\r\n (value.startsWith('\"') && value.endsWith('\"')) ||\r\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\r\n ) {\r\n return value.slice(1, -1);\r\n }\r\n\r\n return value;\r\n}\r\n\r\nexport function readEnvFileSource(filePath: string): EnvSource {\r\n if (!existsSync(filePath)) {\r\n return {};\r\n }\r\n\r\n const content = readFileSync(filePath, \"utf8\");\r\n const source: EnvSource = {};\r\n\r\n for (const line of content.split(/\\r?\\n/)) {\r\n const trimmed = line.trim();\r\n\r\n if (!trimmed || trimmed.startsWith(\"#\")) {\r\n continue;\r\n }\r\n\r\n const equalsIndex = trimmed.indexOf(\"=\");\r\n\r\n if (equalsIndex === -1) {\r\n continue;\r\n }\r\n\r\n const key = trimmed.slice(0, equalsIndex).trim();\r\n const rawValue = trimmed.slice(equalsIndex + 1).trim();\r\n\r\n if (!key) {\r\n continue;\r\n }\r\n\r\n source[key] = stripQuotes(rawValue);\r\n }\r\n\r\n return source;\r\n}\r\n\r\nexport function resolveExampleEnvPath(\r\n cwd: string = process.cwd(),\r\n exampleFile: string = \".env.example\",\r\n): string {\r\n return resolve(cwd, exampleFile);\r\n}\r\n","import { flattenSchema } from \"./flattenSchema\";\r\nimport type { EnvSchema, EnvSource, EnvValidationIssue } from \"./types/schema\";\r\n\r\nexport function validateExampleEnv(\r\n schema: EnvSchema,\r\n exampleSource: EnvSource,\r\n): EnvValidationIssue[] {\r\n const issues: EnvValidationIssue[] = [];\r\n const flattenedSchema = flattenSchema(schema);\r\n const expectedKeys = new Set(flattenedSchema.map((entry) => entry.envKey));\r\n\r\n for (const entry of flattenedSchema) {\r\n const { envKey } = entry;\r\n\r\n if (!(envKey in exampleSource)) {\r\n issues.push({\r\n key: envKey,\r\n code: \"missing_example_key\",\r\n message: `Environment variable \"${envKey}\" is missing from .env.example.`,\r\n });\r\n }\r\n }\r\n\r\n for (const key of Object.keys(exampleSource)) {\r\n if (exampleSource[key] === undefined) {\r\n continue;\r\n }\r\n\r\n if (expectedKeys.has(key)) {\r\n continue;\r\n }\r\n\r\n issues.push({\r\n key,\r\n code: \"unknown_example_key\",\r\n message: `Environment variable \"${key}\" in .env.example is not defined in the schema.`,\r\n });\r\n }\r\n\r\n return issues;\r\n}\r\n","import { readEnvFileSource, resolveExampleEnvPath } from \"./readEnvFileSource\";\r\nimport { validateExampleEnv } from \"./validateExampleEnv\";\r\nimport type {\r\n EnvSchema,\r\n EnvValidationIssue,\r\n ValidateExampleEnvFileOptions,\r\n} from \"./types/schema\";\r\n\r\nexport function validateExampleEnvFile(\r\n schema: EnvSchema,\r\n options: ValidateExampleEnvFileOptions = {},\r\n): EnvValidationIssue[] {\r\n const filePath = resolveExampleEnvPath(options.cwd, options.exampleFile);\r\n const exampleSource = readEnvFileSource(filePath);\r\n\r\n return validateExampleEnv(schema, exampleSource);\r\n}\r\n","import { formatIssues } from \"../utils/formatIssues\";\r\nimport { loadSchemaModule } from \"../utils/loadSchemaModule\";\r\nimport { validateExampleEnvFile } from \"../../validateExampleEnvFile\";\r\n\r\nexport type ValidateExampleCommandOptions = {\r\n schemaPath: string;\r\n cwd?: string;\r\n exampleFile?: string;\r\n};\r\n\r\nexport async function runValidateExampleCommand(\r\n options: ValidateExampleCommandOptions,\r\n): Promise<number> {\r\n try {\r\n const schema = await loadSchemaModule(options.schemaPath);\r\n\r\n const issues = validateExampleEnvFile(schema, {\r\n cwd: options.cwd,\r\n exampleFile: options.exampleFile,\r\n });\r\n\r\n if (issues.length > 0) {\r\n console.error(\".env.example validation failed:\\n\");\r\n console.error(formatIssues(issues));\r\n return 1;\r\n }\r\n\r\n console.log(\"✓ .env.example validation passed.\");\r\n return 0;\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : \"Unknown CLI error\";\r\n console.error(`CLI error: ${message}`);\r\n return 1;\r\n }\r\n}\r\n","#!/usr/bin/env node\r\n\r\nimport { parseArgs } from \"./utils/parseArgs\";\r\nimport { runValidateCommand } from \"./commands/validate\";\r\nimport { runValidateExampleCommand } from \"./commands/validateExample\";\r\n\r\ntype CliIO = {\r\n log: (message: string) => void;\r\n error: (message: string) => void;\r\n};\r\n\r\nfunction printHelp(io: CliIO): void {\r\n io.log(`node-safe-env CLI\r\n\r\nUsage:\r\n node-safe-env validate --schema <path> [--cwd <path>] [--env-file <path>] [--node-env <value>] [--strict]\r\n node-safe-env validate-example --schema <path> [--cwd <path>] [--example-file <path>]\r\n\r\nCommands:\r\n validate Validate environment variables using a schema\r\n validate-example Validate a .env.example file against a schema\r\n\r\nOptions:\r\n --schema <path> Path to schema module\r\n --cwd <path> Working directory for env file loading\r\n --env-file <path> Custom env file path for validate\r\n --node-env <value> NODE_ENV override for validate\r\n --strict Enable strict mode for unknown keys\r\n --example-file <path> Custom example file path for validate-example\r\n --help Show this help\r\n`);\r\n}\r\n\r\nfunction getStringFlag(\r\n flags: Record<string, string | boolean>,\r\n name: string,\r\n): string | undefined {\r\n const value = flags[name];\r\n return typeof value === \"string\" ? value : undefined;\r\n}\r\n\r\nexport async function runCli(\r\n argv: string[],\r\n io: CliIO = {\r\n log: console.log,\r\n error: console.error,\r\n },\r\n): Promise<number> {\r\n const parsed = parseArgs(argv);\r\n\r\n if (\r\n !parsed.command ||\r\n parsed.flags.help ||\r\n parsed.command === \"help\" ||\r\n parsed.command === \"--help\"\r\n ) {\r\n printHelp(io);\r\n return 0;\r\n }\r\n\r\n const schemaPath = getStringFlag(parsed.flags, \"schema\");\r\n\r\n if (!schemaPath) {\r\n io.error('Missing required flag \"--schema\".\\n');\r\n printHelp(io);\r\n return 1;\r\n }\r\n\r\n if (parsed.command === \"validate\") {\r\n return runValidateCommand({\r\n schemaPath,\r\n cwd: getStringFlag(parsed.flags, \"cwd\"),\r\n envFile: getStringFlag(parsed.flags, \"env-file\"),\r\n nodeEnv: getStringFlag(parsed.flags, \"node-env\"),\r\n strict: parsed.flags.strict === true,\r\n });\r\n }\r\n\r\n if (parsed.command === \"validate-example\") {\r\n return runValidateExampleCommand({\r\n schemaPath,\r\n cwd: getStringFlag(parsed.flags, \"cwd\"),\r\n exampleFile: getStringFlag(parsed.flags, \"example-file\"),\r\n });\r\n }\r\n\r\n io.error(`Unknown command \"${parsed.command}\".\\n`);\r\n printHelp(io);\r\n return 1;\r\n}\r\n\r\nasync function main(): Promise<void> {\r\n const exitCode = await runCli(process.argv.slice(2));\r\n process.exitCode = exitCode;\r\n}\r\n\r\nvoid main();\r\n"],"mappings":"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","names":["path","path","path","path","path"]}
1
+ {"version":3,"sources":["../src/cli/utils/parseArgs.ts","../src/errors/EnvValidationError.ts","../src/createEnv.ts","../src/flattenSchema.ts","../src/findUnknownEnvKeys.ts","../src/loadEnvFiles.ts","../src/mergeSources.ts","../src/applyTransform.ts","../src/validators/boolean.ts","../src/validators/enum.ts","../src/validators/json.ts","../src/validators/number.ts","../src/validators/port.ts","../src/validators/string.ts","../src/validators/url.ts","../src/validators/int.ts","../src/validators/float.ts","../src/validators/array.ts","../src/validators/custom.ts","../src/validators/email.ts","../src/validators/date.ts","../src/validators/index.ts","../src/parseValue.ts","../src/setNestedValue.ts","../src/cli/utils/formatIssues.ts","../src/cli/utils/formatCliError.ts","../src/cli/utils/loadSchemaModule.ts","../src/cli/commands/validate.ts","../src/readEnvFileSource.ts","../src/validateExampleEnv.ts","../src/validateExampleEnvFile.ts","../src/cli/commands/validateExample.ts","../src/cli/index.ts"],"sourcesContent":["export type ParsedCliArgs = {\r\n command?: string;\r\n flags: Record<string, string | boolean>;\r\n positionals: string[];\r\n};\r\n\r\nexport function parseArgs(argv: string[]): ParsedCliArgs {\r\n const [command, ...rest] = argv;\r\n\r\n const flags: Record<string, string | boolean> = {};\r\n const positionals: string[] = [];\r\n\r\n for (let index = 0; index < rest.length; index += 1) {\r\n const token = rest[index];\r\n\r\n if (!token.startsWith(\"--\")) {\r\n positionals.push(token);\r\n continue;\r\n }\r\n\r\n const flagName = token.slice(2);\r\n const next = rest[index + 1];\r\n\r\n if (!next || next.startsWith(\"--\")) {\r\n flags[flagName] = true;\r\n continue;\r\n }\r\n\r\n flags[flagName] = next;\r\n index += 1;\r\n }\r\n\r\n return {\r\n command,\r\n flags,\r\n positionals,\r\n };\r\n}\r\n","import type { EnvValidationIssue } from \"../types/schema\";\n\nexport class EnvValidationError extends Error {\n public readonly issues: EnvValidationIssue[];\n\n constructor(issues: EnvValidationIssue[]) {\n super(\n [\n \"Environment validation failed:\",\n ...issues.map((issue) => `- [${issue.code}] ${issue.message}`),\n ].join(\"\\n\"),\n );\n\n this.name = \"EnvValidationError\";\n this.issues = issues;\n }\n}\n","import { EnvValidationError } from \"./errors/EnvValidationError\";\nimport path from \"node:path\";\nimport { findUnknownEnvKeys } from \"./findUnknownEnvKeys\";\nimport { flattenSchema } from \"./flattenSchema\";\nimport { loadEnvFiles } from \"./loadEnvFiles\";\nimport { mergeSources } from \"./mergeSources\";\nimport { parseValue } from \"./parseValue\";\nimport { setNestedValue } from \"./setNestedValue\";\nimport type {\n CreateEnvOptions,\n EnvDebugDefaultKind,\n EnvDebugKeyEntry,\n EnvDebugLoadedFile,\n EnvDebugReport,\n EnvDebugSource,\n EnvRule,\n EnvSchema,\n EnvValidationIssue,\n EnvValueSource,\n LoadedEnvFiles,\n ParsedEnv,\n} from \"./types/schema\";\n\nfunction isEmptyString(value: string): boolean {\n return value.trim() === \"\";\n}\n\nfunction defaultToRawValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n return JSON.stringify(value);\n}\n\nfunction resolveDefaultValue(value: unknown): unknown {\n return typeof value === \"function\" ? (value as () => unknown)() : value;\n}\n\nfunction parseDefaultValue(\n envKey: string,\n rule: EnvRule,\n): ReturnType<typeof parseValue> & {\n defaultKind: EnvDebugDefaultKind;\n rawDefault?: string;\n} {\n const defaultKind: EnvDebugDefaultKind =\n typeof rule.default === \"function\" ? \"function\" : \"static\";\n let resolvedDefault: unknown;\n\n try {\n resolvedDefault = resolveDefaultValue(rule.default);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n issue: {\n key: envKey,\n code: \"invalid_default\",\n message: `Default function for \"${envKey}\" threw an error: ${message}`,\n },\n defaultKind,\n };\n }\n\n const rawDefault = defaultToRawValue(resolvedDefault);\n\n return {\n ...parseValue(envKey, rawDefault, rule),\n defaultKind,\n rawDefault,\n };\n}\n\ntype SourceTrace = Record<string, { source: EnvValueSource; raw: string }>;\n\nfunction countKeys(source: Record<string, string | undefined>): number {\n return Object.values(source).filter((value) => typeof value === \"string\")\n .length;\n}\n\nfunction buildLoadedFileReport(\n loadedFiles: LoadedEnvFiles,\n cwd: string,\n nodeEnv: string,\n envFile?: string,\n): EnvDebugLoadedFile[] {\n return [\n {\n source: \".env\",\n path: path.join(cwd, \".env\"),\n keyCount: countKeys(loadedFiles.base),\n },\n {\n source: \".env.local\",\n path: path.join(cwd, \".env.local\"),\n keyCount: countKeys(loadedFiles.local),\n },\n {\n source: \".env.environment\",\n path: path.join(cwd, `.env.${nodeEnv}`),\n keyCount: countKeys(loadedFiles.environment),\n },\n {\n source: \"custom\",\n path: envFile ? path.resolve(cwd, envFile) : undefined,\n keyCount: countKeys(loadedFiles.custom),\n },\n ];\n}\n\nfunction buildSourceTrace(\n loadedFiles: LoadedEnvFiles,\n runtimeValues: Record<string, string | undefined>,\n): SourceTrace {\n const trace: SourceTrace = Object.create(null) as SourceTrace;\n\n const applySource = (\n source: Record<string, string | undefined>,\n label: EnvValueSource,\n ): void => {\n for (const [key, raw] of Object.entries(source)) {\n if (typeof raw === \"string\") {\n trace[key] = { source: label, raw };\n }\n }\n };\n\n applySource(loadedFiles.base, \".env\");\n applySource(loadedFiles.local, \".env.local\");\n applySource(loadedFiles.environment, \".env.environment\");\n applySource(loadedFiles.custom, \"custom\");\n applySource(runtimeValues, \"process.env\");\n\n return trace;\n}\n\nfunction maskDebugValue(value: unknown, sensitive: boolean): unknown {\n if (value === undefined) {\n return undefined;\n }\n\n return sensitive ? \"***\" : value;\n}\n\nfunction resolveDebugLogger(\n debug: CreateEnvOptions[\"debug\"],\n): ((report: EnvDebugReport) => void) | undefined {\n if (debug === true) {\n return (report: EnvDebugReport): void => {\n console.info(report);\n };\n }\n\n if (debug && typeof debug === \"object\" && debug.logger) {\n return debug.logger;\n }\n\n return undefined;\n}\n\nexport function createEnv<S extends EnvSchema>(\n schema: S,\n options: CreateEnvOptions = {},\n): ParsedEnv<S> {\n const debugEnabled = options.debug !== undefined && options.debug !== false;\n const debugLogger = debugEnabled\n ? resolveDebugLogger(options.debug)\n : undefined;\n const debugKeys: EnvDebugKeyEntry[] = [];\n\n let source: Record<string, string | undefined>;\n let loadedFileReport: EnvDebugLoadedFile[] = [];\n let sourceTrace: SourceTrace = Object.create(null) as SourceTrace;\n\n if (options.source) {\n source = options.source;\n\n if (debugEnabled) {\n for (const [key, raw] of Object.entries(source)) {\n if (typeof raw === \"string\") {\n sourceTrace[key] = { source: \"process.env\", raw };\n }\n }\n }\n } else {\n const loadedFiles = loadEnvFiles({\n cwd: options.cwd,\n nodeEnv: options.nodeEnv,\n envFile: options.envFile,\n });\n source = mergeSources(loadedFiles, process.env);\n\n if (debugEnabled) {\n const cwd = options.cwd ?? process.cwd();\n const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV ?? \"development\";\n loadedFileReport = buildLoadedFileReport(\n loadedFiles,\n cwd,\n nodeEnv,\n options.envFile,\n );\n sourceTrace = buildSourceTrace(loadedFiles, process.env);\n }\n }\n\n const issues: EnvValidationIssue[] = [];\n const result: Record<string, unknown> = {};\n const flattenedSchema = flattenSchema(schema as Record<string, unknown>);\n\n if (options.strict) {\n issues.push(\n ...findUnknownEnvKeys(schema as Record<string, unknown>, source),\n );\n }\n\n for (const entry of flattenedSchema) {\n const { path, envKey, rule } = entry;\n const currentValue = source[envKey];\n const sourceInfo = sourceTrace[envKey];\n const sensitive = rule.sensitive === true;\n const defaultKind: EnvDebugDefaultKind | undefined =\n rule.default === undefined\n ? undefined\n : typeof rule.default === \"function\"\n ? \"function\"\n : \"static\";\n\n const pushDebugEntry = (\n status: EnvDebugKeyEntry[\"status\"],\n values: {\n source: EnvDebugSource;\n usedDefault: boolean;\n raw?: string;\n parsed?: unknown;\n issue?: EnvValidationIssue;\n defaultKind?: EnvDebugDefaultKind;\n },\n ): void => {\n if (!debugEnabled) {\n return;\n }\n\n debugKeys.push({\n key: envKey,\n ruleType: rule.type,\n source: values.source,\n usedDefault: values.usedDefault,\n defaultKind: values.defaultKind,\n raw: maskDebugValue(values.raw, sensitive) as string | undefined,\n parsed: maskDebugValue(values.parsed, sensitive),\n status,\n issue: values.issue,\n });\n };\n\n if (typeof currentValue !== \"string\") {\n if (rule.default !== undefined) {\n const parsedDefault = parseDefaultValue(envKey, rule);\n\n if (parsedDefault.issue) {\n issues.push(parsedDefault.issue);\n pushDebugEntry(\"issue\", {\n source: \"default\",\n usedDefault: true,\n defaultKind: parsedDefault.defaultKind,\n raw: parsedDefault.rawDefault,\n issue: parsedDefault.issue,\n });\n continue;\n }\n\n pushDebugEntry(\"defaulted\", {\n source: \"default\",\n usedDefault: true,\n defaultKind: parsedDefault.defaultKind,\n raw: parsedDefault.rawDefault,\n parsed: parsedDefault.value,\n });\n setNestedValue(result, path, parsedDefault.value);\n continue;\n }\n\n if (rule.required) {\n const issue = {\n key: envKey,\n code: \"missing\",\n message: `Missing required environment variable \"${envKey}\".`,\n } as const;\n\n issues.push(issue);\n pushDebugEntry(\"missing\", {\n source: \"missing\",\n usedDefault: false,\n defaultKind,\n issue,\n });\n } else {\n pushDebugEntry(\"missing\", {\n source: \"missing\",\n usedDefault: false,\n defaultKind,\n });\n }\n\n continue;\n }\n\n const rawValue = currentValue;\n\n if (!rule.allowEmpty && isEmptyString(rawValue)) {\n if (rule.default !== undefined) {\n const parsedDefault = parseDefaultValue(envKey, rule);\n\n if (parsedDefault.issue) {\n issues.push(parsedDefault.issue);\n pushDebugEntry(\"issue\", {\n source: \"default\",\n usedDefault: true,\n defaultKind: parsedDefault.defaultKind,\n raw: parsedDefault.rawDefault,\n issue: parsedDefault.issue,\n });\n continue;\n }\n\n pushDebugEntry(\"defaulted\", {\n source: \"default\",\n usedDefault: true,\n defaultKind: parsedDefault.defaultKind,\n raw: parsedDefault.rawDefault,\n parsed: parsedDefault.value,\n });\n setNestedValue(result, path, parsedDefault.value);\n continue;\n }\n\n const issue = {\n key: envKey,\n code: \"empty\",\n message: `Environment variable \"${envKey}\" cannot be empty.`,\n } as const;\n\n issues.push(issue);\n pushDebugEntry(\"empty\", {\n source: sourceInfo?.source ?? \"process.env\",\n usedDefault: false,\n defaultKind,\n raw: rawValue,\n issue,\n });\n continue;\n }\n\n const parsed = parseValue(envKey, rawValue, rule);\n\n if (parsed.issue) {\n issues.push(parsed.issue);\n pushDebugEntry(\"issue\", {\n source: sourceInfo?.source ?? \"process.env\",\n usedDefault: false,\n defaultKind,\n raw: rawValue,\n issue: parsed.issue,\n });\n continue;\n }\n\n pushDebugEntry(\"parsed\", {\n source: sourceInfo?.source ?? \"process.env\",\n usedDefault: false,\n defaultKind,\n raw: rawValue,\n parsed: parsed.value,\n });\n setNestedValue(result, path, parsed.value);\n }\n\n if (debugLogger) {\n debugLogger({\n loadedFiles: loadedFileReport,\n keys: debugKeys,\n });\n }\n\n if (issues.length > 0) {\n throw new EnvValidationError(issues);\n }\n\n return result as unknown as ParsedEnv<S>;\n}\n","import type { EnvRule } from \"./types/schema\";\r\n\r\nexport type FlattenedSchemaEntry = {\r\n path: string[];\r\n envKey: string;\r\n rule: EnvRule;\r\n};\r\n\r\nfunction isEnvRule(value: unknown): value is EnvRule {\r\n return (\r\n typeof value === \"object\" &&\r\n value !== null &&\r\n \"type\" in value &&\r\n typeof (value as { type?: unknown }).type === \"string\"\r\n );\r\n}\r\n\r\nfunction toEnvKey(path: string[]): string {\r\n return path.map((segment) => segment.toUpperCase()).join(\"_\");\r\n}\r\n\r\nexport function flattenSchema(\r\n schema: Record<string, unknown>,\r\n parentPath: string[] = [],\r\n): FlattenedSchemaEntry[] {\r\n const entries: FlattenedSchemaEntry[] = [];\r\n\r\n for (const [key, value] of Object.entries(schema)) {\r\n const currentPath = [...parentPath, key];\r\n\r\n if (isEnvRule(value)) {\r\n entries.push({\r\n path: currentPath,\r\n envKey: toEnvKey(currentPath),\r\n rule: value,\r\n });\r\n\r\n continue;\r\n }\r\n\r\n if (typeof value === \"object\" && value !== null) {\r\n entries.push(\r\n ...flattenSchema(value as Record<string, unknown>, currentPath),\r\n );\r\n }\r\n }\r\n\r\n return entries;\r\n}\r\n","import { flattenSchema } from \"./flattenSchema\";\r\nimport type { EnvSource, EnvValidationIssue } from \"./types/schema\";\r\n\r\nexport function findUnknownEnvKeys(\r\n schema: Record<string, unknown>,\r\n source: EnvSource,\r\n): EnvValidationIssue[] {\r\n const knownKeys = new Set(flattenSchema(schema).map((entry) => entry.envKey));\r\n const issues: EnvValidationIssue[] = [];\r\n\r\n for (const key of Object.keys(source)) {\r\n if (source[key] === undefined) {\r\n continue;\r\n }\r\n\r\n if (knownKeys.has(key)) {\r\n continue;\r\n }\r\n\r\n issues.push({\r\n key,\r\n code: \"unknown_key\",\r\n message: `Environment variable \"${key}\" is not defined in the schema.`,\r\n });\r\n }\r\n\r\n return issues;\r\n}\r\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {\n LoadEnvFilesOptions,\n EnvSource,\n LoadedEnvFiles,\n} from \"./types/schema\";\n\nconst ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nfunction stripInlineComment(input: string): string {\n let inSingleQuote = false;\n let inDoubleQuote = false;\n let isEscaped = false;\n\n for (let index = 0; index < input.length; index += 1) {\n const char = input[index];\n\n if (isEscaped) {\n isEscaped = false;\n continue;\n }\n\n if (char === \"\\\\\") {\n isEscaped = true;\n continue;\n }\n\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (\n char === \"#\" &&\n !inSingleQuote &&\n !inDoubleQuote &&\n (index === 0 || /\\s/.test(input[index - 1] ?? \"\"))\n ) {\n return input.slice(0, index).trimEnd();\n }\n }\n\n return input.trimEnd();\n}\n\nfunction parseEnvFile(filePath: string): EnvSource {\n if (!fs.existsSync(filePath)) {\n return Object.create(null) as EnvSource;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const result = Object.create(null) as EnvSource;\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n let line = rawLine.trim();\n\n if (!line || line.startsWith(\"#\")) {\n continue;\n }\n\n if (line.startsWith(\"export \")) {\n line = line.slice(\"export \".length).trim();\n\n if (!line) {\n continue;\n }\n }\n\n const equalIndex = line.indexOf(\"=\");\n\n if (equalIndex <= 0) {\n continue;\n }\n\n const key = line.slice(0, equalIndex).trim();\n\n if (!ENV_KEY_PATTERN.test(key)) {\n continue;\n }\n\n let value = stripInlineComment(line.slice(equalIndex + 1)).trim();\n\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n result[key] = value;\n }\n\n return result;\n}\n\nexport function loadEnvFiles(\n options: LoadEnvFilesOptions = {},\n): LoadedEnvFiles {\n const cwd = options.cwd ?? process.cwd();\n const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV ?? \"development\";\n\n const base = parseEnvFile(path.join(cwd, \".env\"));\n const local = parseEnvFile(path.join(cwd, \".env.local\"));\n const environment = parseEnvFile(path.join(cwd, `.env.${nodeEnv}`));\n const custom = options.envFile\n ? parseEnvFile(path.resolve(cwd, options.envFile))\n : (Object.create(null) as EnvSource);\n\n return {\n base,\n local,\n environment,\n custom,\n };\n}\n","import type { EnvSource, LoadedEnvFiles } from \"./types/schema\";\n\nexport function mergeSources(\n files: LoadedEnvFiles,\n runtimeValues: EnvSource = process.env,\n): EnvSource {\n return Object.assign(\n Object.create(null),\n files.base,\n files.local,\n files.environment,\n files.custom,\n runtimeValues,\n ) as EnvSource;\n}\n","import type { EnvRule, EnvValidationIssue } from \"./types/schema\";\r\nimport type { ParseResult } from \"./validators\";\r\n\r\nexport function applyTransform(\r\n key: string,\r\n rule: EnvRule,\r\n result: ParseResult,\r\n): ParseResult {\r\n if (result.issue || result.value === undefined || !rule.transform) {\r\n return result;\r\n }\r\n\r\n try {\r\n return {\r\n value: rule.transform(result.value as never),\r\n };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error && error.message\r\n ? error.message\r\n : `Environment variable \"${key}\" failed transform.`;\r\n\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_custom\",\r\n message,\r\n } satisfies EnvValidationIssue,\r\n };\r\n }\r\n}\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nconst TRUE_VALUES = new Set([\"true\", \"1\", \"yes\", \"on\"]);\r\nconst FALSE_VALUES = new Set([\"false\", \"0\", \"no\", \"off\"]);\r\n\r\nexport const validateBoolean: EnvValidator = ({ key, rawValue }) => {\r\n const normalized = rawValue.trim().toLowerCase();\r\n\r\n if (TRUE_VALUES.has(normalized)) {\r\n return { value: true };\r\n }\r\n\r\n if (FALSE_VALUES.has(normalized)) {\r\n return { value: false };\r\n }\r\n\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_boolean\",\r\n message: `Environment variable \"${key}\" must be a valid boolean.`,\r\n },\r\n };\r\n};\r\n","import type { EnumRule } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nexport const validateEnum: EnvValidator = ({ key, rawValue, rule }) => {\r\n const enumRule = rule as EnumRule;\r\n\r\n if (!enumRule.values.includes(rawValue)) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_enum\",\r\n message: `Environment variable \"${key}\" must be one of: ${enumRule.values.join(\", \")}.`,\r\n },\r\n };\r\n }\r\n\r\n return { value: rawValue };\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateJson: EnvValidator = ({ key, rawValue }) => {\r\n try {\r\n const parsed = JSON.parse(rawValue);\r\n\r\n return { value: parsed };\r\n } catch {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_json\",\r\n message: `Environment variable \"${key}\" must contain valid JSON.`,\r\n },\r\n };\r\n }\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateNumber: EnvValidator = ({ key, rawValue }) => {\r\n const parsed = Number(rawValue);\r\n\r\n if (!Number.isFinite(parsed)) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_number\",\r\n message: `Environment variable \"${key}\" must be a valid number.`,\r\n },\r\n };\r\n }\r\n\r\n return { value: parsed };\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validatePort: EnvValidator = ({ key, rawValue }) => {\r\n const num = Number(rawValue);\r\n\r\n if (!Number.isInteger(num) || num < 1 || num > 65535) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_port\",\r\n message: `Environment variable \"${key}\" must be a valid port (1–65535).`,\r\n },\r\n };\r\n }\r\n\r\n return { value: num };\r\n};","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateString: EnvValidator = ({ rawValue }) => {\r\n return { value: rawValue };\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateUrl: EnvValidator = ({ key, rawValue }) => {\r\n try {\r\n new URL(rawValue);\r\n\r\n return { value: rawValue };\r\n } catch {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_url\",\r\n message: `Environment variable \"${key}\" must be a valid URL.`,\r\n },\r\n };\r\n }\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateInt: EnvValidator = ({ key, rawValue }) => {\r\n const parsed = Number(rawValue);\r\n\r\n if (!Number.isInteger(parsed)) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_number\",\r\n message: `Environment variable \"${key}\" must be a valid integer.`,\r\n },\r\n };\r\n }\r\n\r\n return { value: parsed };\r\n};\r\n","import type { EnvValidator } from \"./types\";\r\n\r\nexport const validateFloat: EnvValidator = ({ key, rawValue }) => {\r\n const parsed = Number(rawValue);\r\n\r\n if (!Number.isFinite(parsed)) {\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_number\",\r\n message: `Environment variable \"${key}\" must be a valid float.`,\r\n },\r\n };\r\n }\r\n\r\n return { value: parsed };\r\n};\r\n","import type { ArrayRule, EnvValidationIssue } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nexport const validateArray: EnvValidator = ({ key, rawValue, rule }) => {\r\n const arrayRule = rule as ArrayRule;\r\n const separator = arrayRule.separator ?? \",\";\r\n const trimItems = arrayRule.trimItems ?? true;\r\n const allowEmptyItems = arrayRule.allowEmptyItems ?? false;\r\n const splitValues = rawValue.split(separator);\r\n\r\n const parsed = trimItems\r\n ? splitValues.map((item) => item.trim())\r\n : splitValues;\r\n\r\n if (!allowEmptyItems && parsed.some((item) => item === \"\")) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_array\",\r\n message: `Environment variable \"${key}\" cannot contain empty array items`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n return { value: parsed };\r\n};\r\n","import type { CustomRule } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nexport const validateCustom: EnvValidator = ({ key, rawValue, rule }) => {\r\n const customRule = rule as CustomRule;\r\n\r\n try {\r\n const parsed = customRule.parse(rawValue);\r\n\r\n return { value: parsed };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error && error.message\r\n ? error.message\r\n : `Environment variable \"${key}\" failed custom validation.`;\r\n\r\n return {\r\n issue: {\r\n key,\r\n code: \"invalid_custom\",\r\n message,\r\n },\r\n };\r\n }\r\n};\r\n","import type { EmailRule, EnvValidationIssue } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nexport const validateEmail: EnvValidator = ({ key, rawValue, rule }) => {\r\n const emailRule = rule as EmailRule;\r\n void emailRule;\r\n\r\n const value = rawValue.trim();\r\n\r\n if (!value) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_email\",\r\n message: `Environment variable \"${key}\" must be a valid email address`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n if (/\\s/.test(value)) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_email\",\r\n message: `Environment variable \"${key}\" must be a valid email address`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n\r\n if (!emailRegex.test(value)) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_email\",\r\n message: `Environment variable \"${key}\" must be a valid email address`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n return {\r\n value,\r\n };\r\n};","import type { DateRule, EnvValidationIssue } from \"../types/schema\";\r\nimport type { EnvValidator } from \"./types\";\r\n\r\nfunction isValidDate(date: Date): boolean {\r\n return !Number.isNaN(date.getTime());\r\n}\r\n\r\nexport const validateDate: EnvValidator = ({ key, rawValue, rule }) => {\r\n const dateRule = rule as DateRule;\r\n void dateRule;\r\n\r\n const value = rawValue.trim();\r\n\r\n if (!value) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_date\",\r\n message: `Environment variable \"${key}\" must be a valid ISO date`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\r\n const isoDateTimeRegex =\r\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,3})?)?(Z|[+-]\\d{2}:\\d{2})$/;\r\n\r\n if (!isoDateRegex.test(value) && !isoDateTimeRegex.test(value)) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_date\",\r\n message: `Environment variable \"${key}\" must be a valid ISO date string`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n const parsed = new Date(value);\r\n\r\n if (!isValidDate(parsed)) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_date\",\r\n message: `Environment variable \"${key}\" must be a valid date`,\r\n };\r\n\r\n return { issue };\r\n }\r\n\r\n if (isoDateRegex.test(value)) {\r\n const [year, month, day] = value.split(\"-\").map(Number);\r\n\r\n if (\r\n parsed.getUTCFullYear() !== year ||\r\n parsed.getUTCMonth() + 1 !== month ||\r\n parsed.getUTCDate() !== day\r\n ) {\r\n const issue: EnvValidationIssue = {\r\n key,\r\n code: \"invalid_date\",\r\n message: `Environment variable \"${key}\" must be a real calendar date`,\r\n };\r\n\r\n return { issue };\r\n }\r\n }\r\n\r\n return {\r\n value: parsed,\r\n };\r\n};\r\n","import { validateBoolean } from \"./boolean\";\r\nimport { validateEnum } from \"./enum\";\r\nimport { validateJson } from \"./json\";\r\nimport { validateNumber } from \"./number\";\r\nimport { validatePort } from \"./port\";\r\nimport { validateString } from \"./string\";\r\nimport { validateUrl } from \"./url\";\r\nimport type { EnvValidator } from \"./types\";\r\nimport { validateInt } from \"./int\";\r\nimport { validateFloat } from \"./float\";\r\nimport { validateArray } from \"./array\";\r\nimport { validateCustom } from \"./custom\";\r\nimport { validateEmail } from \"./email\";\r\nimport { validateDate } from \"./date\";\r\n\r\nexport const validators = {\r\n string: validateString,\r\n number: validateNumber,\r\n boolean: validateBoolean,\r\n enum: validateEnum,\r\n url: validateUrl,\r\n port: validatePort,\r\n json: validateJson,\r\n int: validateInt,\r\n float: validateFloat,\r\n array: validateArray,\r\n custom: validateCustom,\r\n email: validateEmail,\r\n date: validateDate,\r\n} as const satisfies {\r\n string: EnvValidator;\r\n number: EnvValidator;\r\n boolean: EnvValidator;\r\n enum: EnvValidator;\r\n url: EnvValidator;\r\n port: EnvValidator;\r\n json: EnvValidator;\r\n int: EnvValidator;\r\n float: EnvValidator;\r\n array: EnvValidator;\r\n custom: EnvValidator;\r\n email: EnvValidator;\r\n date: EnvValidator;\r\n};\r\n\r\nexport type { ParseResult, EnvValidator } from \"./types\";\r\n","import { applyTransform } from \"./applyTransform\";\nimport type { EnvRule } from \"./types/schema\";\nimport { validators } from \"./validators\";\nimport type { ParseResult } from \"./validators\";\n\nexport function parseValue(\n key: string,\n rawValue: string,\n rule: EnvRule,\n): ParseResult {\n const validator = validators[rule.type];\n\n const result = validator({\n key,\n rawValue,\n rule,\n });\n\n return applyTransform(key, rule, result);\n}\n","export function setNestedValue(\r\n target: Record<string, unknown>,\r\n path: string[],\r\n value: unknown,\r\n): void {\r\n let current: Record<string, unknown> = target;\r\n\r\n for (let index = 0; index < path.length - 1; index += 1) {\r\n const segment = path[index];\r\n const existing = current[segment];\r\n\r\n if (\r\n typeof existing !== \"object\" ||\r\n existing === null ||\r\n Array.isArray(existing)\r\n ) {\r\n current[segment] = {};\r\n }\r\n\r\n current = current[segment] as Record<string, unknown>;\r\n }\r\n\r\n current[path[path.length - 1]] = value;\r\n}\r\n","import type { EnvValidationIssue } from \"../../types/schema\";\r\n\r\nexport function formatIssues(issues: EnvValidationIssue[]): string {\r\n return issues.map((issue) => `- ${issue.key}: ${issue.message}`).join(\"\\n\");\r\n}\r\n","export function formatCliError(error: unknown): string {\r\n const message = error instanceof Error ? error.message : \"Unknown CLI error\";\r\n return `CLI error: ${message}`;\r\n}\r\n","import path from \"node:path\";\r\nimport fs from \"node:fs\";\r\nimport { pathToFileURL } from \"node:url\";\r\nimport type { EnvSchema } from \"../../types/schema\";\r\n\r\ntype SchemaModule = {\r\n default?: unknown;\r\n schema?: unknown;\r\n};\r\n\r\nconst SUPPORTED_SCHEMA_EXTENSIONS = [\r\n \".js\",\r\n \".mjs\",\r\n \".cjs\",\r\n \".ts\",\r\n \".mts\",\r\n \".cts\",\r\n] as const;\r\n\r\nfunction isObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null;\r\n}\r\n\r\nfunction isTypeScriptFile(filePath: string): boolean {\r\n const ext = path.extname(filePath).toLowerCase();\r\n return ext === \".ts\" || ext === \".mts\" || ext === \".cts\";\r\n}\r\n\r\nfunction isSupportedSchemaFile(filePath: string): boolean {\r\n const ext = path.extname(filePath).toLowerCase();\r\n return SUPPORTED_SCHEMA_EXTENSIONS.includes(\r\n ext as (typeof SUPPORTED_SCHEMA_EXTENSIONS)[number],\r\n );\r\n}\r\n\r\nfunction assertSchemaPathIsUsable(\r\n absolutePath: string,\r\n schemaPath: string,\r\n): void {\r\n if (!isSupportedSchemaFile(absolutePath)) {\r\n throw new Error(\r\n `Unsupported schema file type for \"${schemaPath}\". Supported extensions: ${SUPPORTED_SCHEMA_EXTENSIONS.join(\", \")}.`,\r\n );\r\n }\r\n\r\n if (!fs.existsSync(absolutePath)) {\r\n throw new Error(\r\n `Schema file not found: \"${schemaPath}\" (resolved to \"${absolutePath}\").`,\r\n );\r\n }\r\n}\r\n\r\nasync function importTypeScriptModule(\r\n absolutePath: string,\r\n schemaPath: string,\r\n): Promise<SchemaModule> {\r\n try {\r\n const { register } = await import(\"tsx/esm/api\");\r\n const api = register({\r\n namespace: `node-safe-env:${Date.now()}:${Math.random().toString(36).slice(2)}`,\r\n });\r\n\r\n const loaded = await (async () => {\r\n try {\r\n return await api.import(\r\n pathToFileURL(absolutePath).href,\r\n import.meta.url,\r\n );\r\n } finally {\r\n api.unregister();\r\n }\r\n })();\r\n\r\n if (isObject(loaded)) {\r\n return loaded as SchemaModule;\r\n }\r\n\r\n return { default: loaded };\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : \"Unknown error\";\r\n throw new Error(\r\n `Failed to load TypeScript schema module \"${schemaPath}\" using tsx runtime: ${message}`,\r\n );\r\n }\r\n}\r\n\r\nexport async function loadSchemaModule(schemaPath: string): Promise<EnvSchema> {\r\n const absolutePath = path.resolve(schemaPath);\r\n const moduleUrl = pathToFileURL(absolutePath).href;\r\n\r\n assertSchemaPathIsUsable(absolutePath, schemaPath);\r\n\r\n const mod = isTypeScriptFile(absolutePath)\r\n ? await importTypeScriptModule(absolutePath, schemaPath)\r\n : await (async (): Promise<SchemaModule> => {\r\n try {\r\n return (await import(moduleUrl)) as SchemaModule;\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : \"Unknown error\";\r\n throw new Error(\r\n `Failed to import schema module \"${schemaPath}\": ${message}`,\r\n );\r\n }\r\n })();\r\n\r\n const schemaCandidate = mod.default ?? mod.schema;\r\n\r\n if (!isObject(schemaCandidate)) {\r\n throw new Error(\r\n `Schema module \"${schemaPath}\" must export a schema as default export or named export \"schema\".`,\r\n );\r\n }\r\n\r\n return schemaCandidate as EnvSchema;\r\n}\r\n","import { createEnv } from \"../../createEnv\";\r\nimport { EnvValidationError } from \"../../errors/EnvValidationError\";\r\nimport { formatIssues } from \"../utils/formatIssues\";\r\nimport { formatCliError } from \"../utils/formatCliError\";\r\nimport { loadSchemaModule } from \"../utils/loadSchemaModule\";\r\n\r\nexport type ValidateCommandOptions = {\r\n schemaPath: string;\r\n cwd?: string;\r\n envFile?: string;\r\n nodeEnv?: string;\r\n strict?: boolean;\r\n};\r\n\r\nexport async function runValidateCommand(\r\n options: ValidateCommandOptions,\r\n): Promise<number> {\r\n try {\r\n const schema = await loadSchemaModule(options.schemaPath);\r\n\r\n createEnv(schema, {\r\n cwd: options.cwd,\r\n envFile: options.envFile,\r\n nodeEnv: options.nodeEnv,\r\n strict: options.strict,\r\n });\r\n\r\n console.log(\"✓ Environment validation passed.\");\r\n return 0;\r\n } catch (error) {\r\n if (error instanceof EnvValidationError) {\r\n console.error(\"Environment validation failed:\\n\");\r\n console.error(formatIssues(error.issues));\r\n return 1;\r\n }\r\n\r\n console.error(formatCliError(error));\r\n return 1;\r\n }\r\n}\r\n","import { existsSync, readFileSync } from \"node:fs\";\r\nimport { resolve } from \"node:path\";\r\nimport type { EnvSource } from \"./types/schema\";\r\n\r\nfunction stripQuotes(value: string): string {\r\n if (\r\n (value.startsWith('\"') && value.endsWith('\"')) ||\r\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\r\n ) {\r\n return value.slice(1, -1);\r\n }\r\n\r\n return value;\r\n}\r\n\r\nexport function readEnvFileSource(filePath: string): EnvSource {\r\n if (!existsSync(filePath)) {\r\n return {};\r\n }\r\n\r\n const content = readFileSync(filePath, \"utf8\");\r\n const source: EnvSource = {};\r\n\r\n for (const line of content.split(/\\r?\\n/)) {\r\n const trimmed = line.trim();\r\n\r\n if (!trimmed || trimmed.startsWith(\"#\")) {\r\n continue;\r\n }\r\n\r\n const equalsIndex = trimmed.indexOf(\"=\");\r\n\r\n if (equalsIndex === -1) {\r\n continue;\r\n }\r\n\r\n const key = trimmed.slice(0, equalsIndex).trim();\r\n const rawValue = trimmed.slice(equalsIndex + 1).trim();\r\n\r\n if (!key) {\r\n continue;\r\n }\r\n\r\n source[key] = stripQuotes(rawValue);\r\n }\r\n\r\n return source;\r\n}\r\n\r\nexport function resolveExampleEnvPath(\r\n cwd: string = process.cwd(),\r\n exampleFile: string = \".env.example\",\r\n): string {\r\n return resolve(cwd, exampleFile);\r\n}\r\n","import { flattenSchema } from \"./flattenSchema\";\r\nimport type { EnvSchema, EnvSource, EnvValidationIssue } from \"./types/schema\";\r\n\r\nexport function validateExampleEnv(\r\n schema: EnvSchema,\r\n exampleSource: EnvSource,\r\n): EnvValidationIssue[] {\r\n const issues: EnvValidationIssue[] = [];\r\n const flattenedSchema = flattenSchema(schema);\r\n const expectedKeys = new Set(flattenedSchema.map((entry) => entry.envKey));\r\n\r\n for (const entry of flattenedSchema) {\r\n const { envKey } = entry;\r\n\r\n if (!(envKey in exampleSource)) {\r\n issues.push({\r\n key: envKey,\r\n code: \"missing_example_key\",\r\n message: `Environment variable \"${envKey}\" is missing from .env.example.`,\r\n });\r\n }\r\n }\r\n\r\n for (const key of Object.keys(exampleSource)) {\r\n if (exampleSource[key] === undefined) {\r\n continue;\r\n }\r\n\r\n if (expectedKeys.has(key)) {\r\n continue;\r\n }\r\n\r\n issues.push({\r\n key,\r\n code: \"unknown_example_key\",\r\n message: `Environment variable \"${key}\" in .env.example is not defined in the schema.`,\r\n });\r\n }\r\n\r\n return issues;\r\n}\r\n","import { readEnvFileSource, resolveExampleEnvPath } from \"./readEnvFileSource\";\r\nimport { validateExampleEnv } from \"./validateExampleEnv\";\r\nimport type {\r\n EnvSchema,\r\n EnvValidationIssue,\r\n ValidateExampleEnvFileOptions,\r\n} from \"./types/schema\";\r\n\r\nexport function validateExampleEnvFile(\r\n schema: EnvSchema,\r\n options: ValidateExampleEnvFileOptions = {},\r\n): EnvValidationIssue[] {\r\n const filePath = resolveExampleEnvPath(options.cwd, options.exampleFile);\r\n const exampleSource = readEnvFileSource(filePath);\r\n\r\n return validateExampleEnv(schema, exampleSource);\r\n}\r\n","import { formatIssues } from \"../utils/formatIssues\";\r\nimport { formatCliError } from \"../utils/formatCliError\";\r\nimport { loadSchemaModule } from \"../utils/loadSchemaModule\";\r\nimport { validateExampleEnvFile } from \"../../validateExampleEnvFile\";\r\n\r\nexport type ValidateExampleCommandOptions = {\r\n schemaPath: string;\r\n cwd?: string;\r\n exampleFile?: string;\r\n};\r\n\r\nexport async function runValidateExampleCommand(\r\n options: ValidateExampleCommandOptions,\r\n): Promise<number> {\r\n try {\r\n const schema = await loadSchemaModule(options.schemaPath);\r\n\r\n const issues = validateExampleEnvFile(schema, {\r\n cwd: options.cwd,\r\n exampleFile: options.exampleFile,\r\n });\r\n\r\n if (issues.length > 0) {\r\n console.error(\".env.example validation failed:\\n\");\r\n console.error(formatIssues(issues));\r\n return 1;\r\n }\r\n\r\n console.log(\"✓ .env.example validation passed.\");\r\n return 0;\r\n } catch (error) {\r\n console.error(formatCliError(error));\r\n return 1;\r\n }\r\n}\r\n","#!/usr/bin/env node\r\n\r\nimport { parseArgs } from \"./utils/parseArgs\";\r\nimport { runValidateCommand } from \"./commands/validate\";\r\nimport { runValidateExampleCommand } from \"./commands/validateExample\";\r\n\r\ntype CliIO = {\r\n log: (message: string) => void;\r\n error: (message: string) => void;\r\n};\r\n\r\nfunction printHelp(io: CliIO): void {\r\n io.log(`node-safe-env CLI\r\n\r\nUsage:\r\n node-safe-env validate --schema <path> [--cwd <path>] [--env-file <path>] [--node-env <value>] [--strict]\r\n node-safe-env validate-example --schema <path> [--cwd <path>] [--example-file <path>]\r\n\r\nCommands:\r\n validate Validate environment variables using a schema\r\n validate-example Validate a .env.example file against a schema\r\n\r\nOptions:\r\n --schema <path> Path to schema module (.js, .mjs, .cjs, .ts, .mts, .cts)\r\n --cwd <path> Working directory for env file loading\r\n --env-file <path> Custom env file path for validate\r\n --node-env <value> NODE_ENV override for validate\r\n --strict Enable strict mode for unknown keys\r\n --example-file <path> Custom example file path for validate-example\r\n --help Show this help\r\n\r\nSchema module exports:\r\n - default export\r\n - named export: schema\r\n\r\nExamples:\r\n node-safe-env validate --schema ./env.schema.ts\r\n node-safe-env validate-example --schema ./env.schema.ts\r\n node-safe-env validate --schema ./dist/env.schema.js --strict\r\n`);\r\n}\r\n\r\nfunction getStringFlag(\r\n flags: Record<string, string | boolean>,\r\n name: string,\r\n): string | undefined {\r\n const value = flags[name];\r\n return typeof value === \"string\" ? value : undefined;\r\n}\r\n\r\nexport async function runCli(\r\n argv: string[],\r\n io: CliIO = {\r\n log: console.log,\r\n error: console.error,\r\n },\r\n): Promise<number> {\r\n const parsed = parseArgs(argv);\r\n\r\n if (\r\n !parsed.command ||\r\n parsed.flags.help ||\r\n parsed.command === \"help\" ||\r\n parsed.command === \"--help\"\r\n ) {\r\n printHelp(io);\r\n return 0;\r\n }\r\n\r\n const schemaPath = getStringFlag(parsed.flags, \"schema\");\r\n\r\n if (!schemaPath) {\r\n io.error('Missing required flag \"--schema\".\\n');\r\n printHelp(io);\r\n return 1;\r\n }\r\n\r\n if (parsed.command === \"validate\") {\r\n return runValidateCommand({\r\n schemaPath,\r\n cwd: getStringFlag(parsed.flags, \"cwd\"),\r\n envFile: getStringFlag(parsed.flags, \"env-file\"),\r\n nodeEnv: getStringFlag(parsed.flags, \"node-env\"),\r\n strict: parsed.flags.strict === true,\r\n });\r\n }\r\n\r\n if (parsed.command === \"validate-example\") {\r\n return runValidateExampleCommand({\r\n schemaPath,\r\n cwd: getStringFlag(parsed.flags, \"cwd\"),\r\n exampleFile: getStringFlag(parsed.flags, \"example-file\"),\r\n });\r\n }\r\n\r\n io.error(`Unknown command \"${parsed.command}\".\\n`);\r\n printHelp(io);\r\n return 1;\r\n}\r\n\r\nasync function main(): Promise<void> {\r\n const exitCode = await runCli(process.argv.slice(2));\r\n process.exitCode = exitCode;\r\n}\r\n\r\nvoid main();\r\n"],"mappings":"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","names":["path","path","path","path","path","fs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-safe-env",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "A tiny schema-based env loader and validator for Node.js.",
5
5
  "keywords": [
6
6
  "env",
@@ -50,6 +50,9 @@
50
50
  "format": "prettier --write .",
51
51
  "check": "npm run lint && npm run build && npm run typecheck && npm run test"
52
52
  },
53
+ "dependencies": {
54
+ "tsx": "^4.21.0"
55
+ },
53
56
  "devDependencies": {
54
57
  "@eslint/js": "9.39.1",
55
58
  "@types/node": "^24.0.0",