@lowerdeck/env 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+
2
+ $ microbundle
3
+ Build "@lowerdeck/env" to dist:
4
+ 218 B: index.cjs.gz
5
+ 164 B: index.cjs.br
6
+ 212 B: index.modern.js.gz
7
+ 170 B: index.modern.js.br
8
+ 225 B: index.module.js.gz
9
+ 175 B: index.module.js.br
10
+ 304 B: index.umd.js.gz
11
+ 267 B: index.umd.js.br
@@ -0,0 +1,28 @@
1
+
2
+ $ vitest run --passWithNoTests
3
+ [?25l
4
+  RUN  v3.2.4 /Users/tobias/code/metorial/metorial-enterprise/oss/src/packages/backend/env
5
+
6
+ [?2026h
7
+  ❯ src/env.test.ts [queued]
8
+
9
+  Test Files 0 passed (1)
10
+  Tests 0 passed (0)
11
+  Start at 10:23:43
12
+  Duration 102ms
13
+ [?2026l[?2026h
14
+  ❯ src/env.test.ts 0/1
15
+
16
+  Test Files 0 passed (1)
17
+  Tests 0 passed (1)
18
+  Start at 10:23:43
19
+  Duration 303ms
20
+ [?2026l ✓ src/env.test.ts (1 test) 2ms
21
+ ✓ createValidatedEnv > validates env 1ms
22
+
23
+  Test Files  1 passed (1)
24
+  Tests  1 passed (1)
25
+  Start at  10:23:43
26
+  Duration  335ms (transform 97ms, setup 0ms, collect 128ms, tests 2ms, environment 0ms, prepare 37ms)
27
+
28
+ [?25h
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # `@lowerdeck/env`
2
+
3
+ Type-safe environment variable validation. Ensure required environment variables exist and have proper types at application startup.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @lowerdeck/env
9
+ yarn add @lowerdeck/env
10
+ bun add @lowerdeck/env
11
+ pnpm add @lowerdeck/env
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```typescript
17
+ import { createValidatedEnv } from '@lowerdeck/env';
18
+ import { string, number, object } from '@lowerdeck/validation';
19
+
20
+ // Define environment schema
21
+ const env = createValidatedEnv(
22
+ object({
23
+ NODE_ENV: string().oneOf(['development', 'production', 'test']),
24
+ PORT: number().min(1).max(65535),
25
+ DATABASE_URL: string().url(),
26
+ API_KEY: string().min(32),
27
+ DEBUG: string().optional()
28
+ })
29
+ );
30
+
31
+ // Use validated environment variables
32
+ console.log(env.PORT); // number type
33
+ console.log(env.NODE_ENV); // 'development' | 'production' | 'test'
34
+ console.log(env.DATABASE_URL); // validated URL string
35
+
36
+ // Throws error if validation fails
37
+ // Error: Environment variable PORT is required
38
+ // Error: Environment variable DATABASE_URL must be a valid URL
39
+ ```
40
+
41
+ ### With Default Values
42
+
43
+ ```typescript
44
+ import { createValidatedEnv } from '@lowerdeck/env';
45
+ import { string, number, object, optional } from '@lowerdeck/validation';
46
+
47
+ const env = createValidatedEnv(
48
+ object({
49
+ PORT: optional(number().min(1)).default(3000),
50
+ HOST: optional(string()).default('localhost'),
51
+ LOG_LEVEL: optional(string().oneOf(['debug', 'info', 'warn', 'error'])).default('info')
52
+ })
53
+ );
54
+
55
+ console.log(env.PORT); // 3000 if not set
56
+ ```
57
+
58
+ ## License
59
+
60
+ This project is licensed under the Apache License 2.0.
61
+
62
+ <div align="center">
63
+ <sub>Built with ❤️ by <a href="https://metorial.com">Metorial</a></sub>
64
+ </div>
package/dist/env.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { ValidationType, ValidationTypeValue } from '@lowerdeck/validation';
2
+ export declare let createValidatedEnv: <Env extends Record<string, Record<string, ValidationType<any>>>>(env: Env) => { [K in keyof Env]: { [P in keyof Env[K]]: ValidationTypeValue<Env[K][P]>; }; };
3
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5E,eAAO,IAAI,kBAAkB,GAC3B,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAE/D,KAAK,GAAG,KACP,GACA,CAAC,IAAI,MAAM,GAAG,GAAG,GACf,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACpD,GAgBF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=env.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.test.d.ts","sourceRoot":"","sources":["../src/env.test.ts"],"names":[],"mappings":""}
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ exports.createValidatedEnv=function(e){return Object.fromEntries(Object.entries(e).map(function(e){return[e[0],Object.fromEntries(Object.entries(e[1]).map(function(e){var r=e[0],t=e[1].validate(process.env[r]);if(!t.success)throw new Error("ENV VALIDATION: "+r+" - "+t.errors[0].message);return[r,t.value]}))]}))};
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/env.ts"],"sourcesContent":["import { ValidationType, ValidationTypeValue } from '@lowerdeck/validation';\n\nexport let createValidatedEnv = <\n Env extends Record<string, Record<string, ValidationType<any>>>\n>(\n env: Env\n): {\n [K in keyof Env]: {\n [P in keyof Env[K]]: ValidationTypeValue<Env[K][P]>;\n };\n} => {\n return Object.fromEntries(\n Object.entries(env).map(([key, value]) => [\n key,\n Object.fromEntries(\n Object.entries(value).map(([key, value]) => {\n let res = value.validate(process.env[key]);\n if (!res.success)\n throw new Error(`ENV VALIDATION: ${key} - ${res.errors[0].message}`);\n\n return [key, res.value];\n })\n )\n ])\n ) as any;\n};\n"],"names":["env","Object","fromEntries","entries","map","_ref","_ref2","key","res","validate","process","success","Error","errors","message","value"],"mappings":"2BAEgC,SAG9BA,GAMA,OAAOC,OAAOC,YACZD,OAAOE,QAAQH,GAAKI,IAAI,SAAAC,GAAY,MAAM,CAAbA,EAAA,GAE3BJ,OAAOC,YACLD,OAAOE,QAHyBE,EAAA,IAGVD,IAAI,SAAAE,GAAiB,IAAfC,EAAGD,EAAA,GACzBE,EADgCF,EAAA,GACpBG,SAASC,QAAQV,IAAIO,IACrC,IAAKC,EAAIG,QACP,MAAM,IAAIC,MAAK,mBAAoBL,EAAG,MAAMC,EAAIK,OAAO,GAAGC,SAE5D,MAAO,CAACP,EAAKC,EAAIO,MACnB,IAEH,GAEL"}
@@ -0,0 +1,2 @@
1
+ export * from './env';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC"}
@@ -0,0 +1,2 @@
1
+ let e=e=>Object.fromEntries(Object.entries(e).map(([e,r])=>[e,Object.fromEntries(Object.entries(r).map(([e,r])=>{let t=r.validate(process.env[e]);if(!t.success)throw new Error(`ENV VALIDATION: ${e} - ${t.errors[0].message}`);return[e,t.value]}))]));export{e as createValidatedEnv};
2
+ //# sourceMappingURL=index.modern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.modern.js","sources":["../src/env.ts"],"sourcesContent":["import { ValidationType, ValidationTypeValue } from '@lowerdeck/validation';\n\nexport let createValidatedEnv = <\n Env extends Record<string, Record<string, ValidationType<any>>>\n>(\n env: Env\n): {\n [K in keyof Env]: {\n [P in keyof Env[K]]: ValidationTypeValue<Env[K][P]>;\n };\n} => {\n return Object.fromEntries(\n Object.entries(env).map(([key, value]) => [\n key,\n Object.fromEntries(\n Object.entries(value).map(([key, value]) => {\n let res = value.validate(process.env[key]);\n if (!res.success)\n throw new Error(`ENV VALIDATION: ${key} - ${res.errors[0].message}`);\n\n return [key, res.value];\n })\n )\n ])\n ) as any;\n};\n"],"names":["createValidatedEnv","env","Object","fromEntries","entries","map","key","value","res","validate","process","success","Error","errors","message"],"mappings":"AAEW,IAAAA,EAGTC,GAMOC,OAAOC,YACZD,OAAOE,QAAQH,GAAKI,IAAI,EAAEC,EAAKC,KAAW,CACxCD,EACAJ,OAAOC,YACLD,OAAOE,QAAQG,GAAOF,IAAI,EAAEC,EAAKC,MAC/B,IAAIC,EAAMD,EAAME,SAASC,QAAQT,IAAIK,IACrC,IAAKE,EAAIG,QACP,MAAU,IAAAC,MAAM,mBAAmBN,OAASE,EAAIK,OAAO,GAAGC,WAE5D,MAAO,CAACR,EAAKE,EAAID"}
@@ -0,0 +1,2 @@
1
+ var e=function(e){return Object.fromEntries(Object.entries(e).map(function(e){return[e[0],Object.fromEntries(Object.entries(e[1]).map(function(e){var r=e[0],t=e[1].validate(process.env[r]);if(!t.success)throw new Error("ENV VALIDATION: "+r+" - "+t.errors[0].message);return[r,t.value]}))]}))};export{e as createValidatedEnv};
2
+ //# sourceMappingURL=index.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.module.js","sources":["../src/env.ts"],"sourcesContent":["import { ValidationType, ValidationTypeValue } from '@lowerdeck/validation';\n\nexport let createValidatedEnv = <\n Env extends Record<string, Record<string, ValidationType<any>>>\n>(\n env: Env\n): {\n [K in keyof Env]: {\n [P in keyof Env[K]]: ValidationTypeValue<Env[K][P]>;\n };\n} => {\n return Object.fromEntries(\n Object.entries(env).map(([key, value]) => [\n key,\n Object.fromEntries(\n Object.entries(value).map(([key, value]) => {\n let res = value.validate(process.env[key]);\n if (!res.success)\n throw new Error(`ENV VALIDATION: ${key} - ${res.errors[0].message}`);\n\n return [key, res.value];\n })\n )\n ])\n ) as any;\n};\n"],"names":["createValidatedEnv","env","Object","fromEntries","entries","map","_ref","_ref2","key","res","validate","process","success","Error","errors","message","value"],"mappings":"AAEW,IAAAA,EAAqB,SAG9BC,GAMA,OAAOC,OAAOC,YACZD,OAAOE,QAAQH,GAAKI,IAAI,SAAAC,GAAY,MAAM,CAAbA,EAAA,GAE3BJ,OAAOC,YACLD,OAAOE,QAHyBE,EAAA,IAGVD,IAAI,SAAAE,GAAiB,IAAfC,EAAGD,EAAA,GACzBE,EADgCF,EAAA,GACpBG,SAASC,QAAQV,IAAIO,IACrC,IAAKC,EAAIG,QACP,MAAM,IAAIC,MAAK,mBAAoBL,EAAG,MAAMC,EAAIK,OAAO,GAAGC,SAE5D,MAAO,CAACP,EAAKC,EAAIO,MACnB,IAEH,GAEL"}
@@ -0,0 +1,2 @@
1
+ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e||self).env={})}(this,function(e){e.createValidatedEnv=function(e){return Object.fromEntries(Object.entries(e).map(function(e){return[e[0],Object.fromEntries(Object.entries(e[1]).map(function(e){var n=e[0],t=e[1].validate(process.env[n]);if(!t.success)throw new Error("ENV VALIDATION: "+n+" - "+t.errors[0].message);return[n,t.value]}))]}))}});
2
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/env.ts"],"sourcesContent":["import { ValidationType, ValidationTypeValue } from '@lowerdeck/validation';\n\nexport let createValidatedEnv = <\n Env extends Record<string, Record<string, ValidationType<any>>>\n>(\n env: Env\n): {\n [K in keyof Env]: {\n [P in keyof Env[K]]: ValidationTypeValue<Env[K][P]>;\n };\n} => {\n return Object.fromEntries(\n Object.entries(env).map(([key, value]) => [\n key,\n Object.fromEntries(\n Object.entries(value).map(([key, value]) => {\n let res = value.validate(process.env[key]);\n if (!res.success)\n throw new Error(`ENV VALIDATION: ${key} - ${res.errors[0].message}`);\n\n return [key, res.value];\n })\n )\n ])\n ) as any;\n};\n"],"names":["env","Object","fromEntries","entries","map","_ref","_ref2","key","res","validate","process","success","Error","errors","message","value"],"mappings":"kPAEgC,SAG9BA,GAMA,OAAOC,OAAOC,YACZD,OAAOE,QAAQH,GAAKI,IAAI,SAAAC,GAAY,MAAM,CAAbA,EAAA,GAE3BJ,OAAOC,YACLD,OAAOE,QAHyBE,EAAA,IAGVD,IAAI,SAAAE,GAAiB,IAAfC,EAAGD,EAAA,GACzBE,EADgCF,EAAA,GACpBG,SAASC,QAAQV,IAAIO,IACrC,IAAKC,EAAIG,QACP,MAAM,IAAIC,MAAK,mBAAoBL,EAAG,MAAMC,EAAIK,OAAO,GAAGC,SAE5D,MAAO,CAACP,EAAKC,EAAIO,MACnB,IAEH,GAEL"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@lowerdeck/env",
3
+ "version": "1.0.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "author": "Tobias Herber",
8
+ "license": "Apache 2",
9
+ "type": "module",
10
+ "source": "src/index.ts",
11
+ "exports": {
12
+ "require": "./dist/index.cjs",
13
+ "default": "./dist/index.modern.js"
14
+ },
15
+ "main": "./dist/index.cjs",
16
+ "module": "./dist/index.module.js",
17
+ "types": "dist/index.d.ts",
18
+ "unpkg": "./dist/index.umd.js",
19
+ "scripts": {
20
+ "test": "vitest run --passWithNoTests",
21
+ "lint": "prettier src/**/*.ts --check",
22
+ "build": "microbundle"
23
+ },
24
+ "dependencies": {
25
+ "@lowerdeck/validation": "^1.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "microbundle": "^0.15.1",
29
+ "@lowerdeck/tsconfig": "^1.0.0",
30
+ "typescript": "5.8.2",
31
+ "vitest": "^3.1.2"
32
+ }
33
+ }
@@ -0,0 +1,38 @@
1
+ import { v } from '@lowerdeck/validation';
2
+ import { describe, expect, test } from 'vitest';
3
+ import { createValidatedEnv } from './env';
4
+
5
+ describe('createValidatedEnv', () => {
6
+ test('validates env', () => {
7
+ process.env.PORT = '3000';
8
+ process.env.TEST = 'true';
9
+ process.env.TEST2 = 'false';
10
+ process.env.HELLO = 'world';
11
+
12
+ let env = createValidatedEnv({
13
+ test: {
14
+ PORT: v.string(),
15
+ TEST: v.boolean()
16
+ },
17
+ test2: {
18
+ TEST2: v.boolean()
19
+ },
20
+ hello: {
21
+ HELLO: v.string()
22
+ }
23
+ });
24
+
25
+ expect(env).toEqual({
26
+ test: {
27
+ PORT: '3000',
28
+ TEST: true
29
+ },
30
+ test2: {
31
+ TEST2: false
32
+ },
33
+ hello: {
34
+ HELLO: 'world'
35
+ }
36
+ });
37
+ });
38
+ });
package/src/env.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { ValidationType, ValidationTypeValue } from '@lowerdeck/validation';
2
+
3
+ export let createValidatedEnv = <
4
+ Env extends Record<string, Record<string, ValidationType<any>>>
5
+ >(
6
+ env: Env
7
+ ): {
8
+ [K in keyof Env]: {
9
+ [P in keyof Env[K]]: ValidationTypeValue<Env[K][P]>;
10
+ };
11
+ } => {
12
+ return Object.fromEntries(
13
+ Object.entries(env).map(([key, value]) => [
14
+ key,
15
+ Object.fromEntries(
16
+ Object.entries(value).map(([key, value]) => {
17
+ let res = value.validate(process.env[key]);
18
+ if (!res.success)
19
+ throw new Error(`ENV VALIDATION: ${key} - ${res.errors[0].message}`);
20
+
21
+ return [key, res.value];
22
+ })
23
+ )
24
+ ])
25
+ ) as any;
26
+ };
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './env';
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "@lowerdeck/tsconfig/base.json",
4
+ "exclude": ["dist"],
5
+ "include": ["src"],
6
+ "compilerOptions": {
7
+ "outDir": "dist",
8
+ "lib": ["es2021"],
9
+ "target": "ES2019"
10
+ }
11
+ }