@tmrp/env 0.1.1 → 0.1.3
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 +40 -7
- package/dist/effects/create-env-effect.d.ts.map +1 -1
- package/dist/effects/create-env-effect.js +10 -1
- package/dist/effects/create-env-effect.js.map +1 -1
- package/dist/lib/types.d.ts +2 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/runtime/record/create-record-env.d.ts.map +1 -1
- package/dist/runtime/record/create-record-env.js +10 -1
- package/dist/runtime/record/create-record-env.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Type-safe environment variable parsing for TypeScript projects, powered by
|
|
4
4
|
[Zod](https://zod.dev/).
|
|
5
5
|
|
|
6
|
-
`@tmrp/env` reads environment variables from the current runtime or an
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
`@tmrp/env` reads environment variables from the current runtime or an explicit
|
|
7
|
+
env-like object, validates them with Zod schemas, and returns a strongly typed
|
|
8
|
+
object for application code. It supports Node.js, Deno, Bun, Cloudflare Workers,
|
|
9
|
+
Vercel Edge, Netlify, browser-injected config, and `import.meta.env`-based
|
|
10
|
+
toolchains.
|
|
11
11
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
@@ -278,6 +278,36 @@ const env = createImportMetaEnv(
|
|
|
278
278
|
);
|
|
279
279
|
```
|
|
280
280
|
|
|
281
|
+
### Client-exposed Variables (`clientPrefix`)
|
|
282
|
+
|
|
283
|
+
When building applications that run code on both the server and client-side
|
|
284
|
+
(e.g. Next.js, Vite, Nuxt), the bundler statically injects environment variables
|
|
285
|
+
that are prefixed with a specific keyword (like `NEXT_PUBLIC_` or `VITE_`).
|
|
286
|
+
|
|
287
|
+
On the client-side, trying to validate server-only environment variables will
|
|
288
|
+
normally throw errors because those variables are not exposed. To prevent this,
|
|
289
|
+
you can pass the `clientPrefix` option:
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
import { createEnv } from "@tmrp/env";
|
|
293
|
+
import z from "zod";
|
|
294
|
+
|
|
295
|
+
const env = createEnv(
|
|
296
|
+
{
|
|
297
|
+
DATABASE_URL: z.string(), // Server-only
|
|
298
|
+
NEXT_PUBLIC_API_URL: z.url(), // Client-exposed
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
clientPrefix: "NEXT_PUBLIC_",
|
|
302
|
+
}
|
|
303
|
+
);
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
When running in a client environment (determined automatically by checking if
|
|
307
|
+
`"window" in globalThis` is false, or overridden by passing `isServer: false`),
|
|
308
|
+
only keys that start with the `clientPrefix` will be read and validated. All
|
|
309
|
+
other keys will bypass validation and return `undefined` on the client.
|
|
310
|
+
|
|
281
311
|
## Defining Schemas
|
|
282
312
|
|
|
283
313
|
Pass an object whose keys are environment variable names and whose values are
|
|
@@ -366,8 +396,9 @@ env.PORT; // raw string value, or undefined when unavailable
|
|
|
366
396
|
env.SECRET_KEY; // raw string value, or undefined when unavailable
|
|
367
397
|
```
|
|
368
398
|
|
|
369
|
-
This option is intended for non-runtime code paths. Do not use it for
|
|
370
|
-
startup if the returned values will be used as validated
|
|
399
|
+
This option is intended for non-runtime code paths. Do not use it for
|
|
400
|
+
application startup if the returned values will be used as validated
|
|
401
|
+
configuration.
|
|
371
402
|
|
|
372
403
|
## Error Behavior
|
|
373
404
|
|
|
@@ -408,6 +439,8 @@ Reads variables from the detected Bun, Node, or Deno runtime and validates them.
|
|
|
408
439
|
|
|
409
440
|
```ts
|
|
410
441
|
type Options = {
|
|
442
|
+
clientPrefix?: string;
|
|
443
|
+
isServer?: boolean;
|
|
411
444
|
skipValidation?: boolean;
|
|
412
445
|
};
|
|
413
446
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-env-effect.d.ts","sourceRoot":"","sources":["../../src/effects/create-env-effect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAK7D,wBAAgB,eAAe,CAAC,KAAK,CAAC,QAAQ,SAAS,OAAO,EAC5D,OAAO,EAAE,QAAQ,EACjB,aAAa,EAAE,wBAAwB,EACvC,oBAAoB,EAAE,CACpB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,wBAAwB,KAC7B,OAAO,EACZ,OAAO,CAAC,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"create-env-effect.d.ts","sourceRoot":"","sources":["../../src/effects/create-env-effect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAK7D,wBAAgB,eAAe,CAAC,KAAK,CAAC,QAAQ,SAAS,OAAO,EAC5D,OAAO,EAAE,QAAQ,EACjB,aAAa,EAAE,wBAAwB,EACvC,oBAAoB,EAAE,CACpB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,wBAAwB,KAC7B,OAAO,EACZ,OAAO,CAAC,EAAE,OAAO,GA4BH,GAAG,CAAC,QAAQ,CAAC,CAC5B"}
|
|
@@ -2,7 +2,16 @@ import { Effect } from "effect";
|
|
|
2
2
|
import { envParseValueEffect } from "./env-parse-value-effect.js";
|
|
3
3
|
import { envReadValueEffect } from "./env-read-value-effect.js";
|
|
4
4
|
export function createEnvEffect(envKeys, runtimeSchema, runtimeEnvReadEffect, options) {
|
|
5
|
-
const
|
|
5
|
+
const isServer = options?.isServer ?? !("window" in globalThis);
|
|
6
|
+
const clientPrefix = options?.clientPrefix;
|
|
7
|
+
const env = Effect.runSync(Effect.forEach(Object.entries(envKeys), ([key, schema]) => {
|
|
8
|
+
if (!isServer &&
|
|
9
|
+
clientPrefix !== undefined &&
|
|
10
|
+
!key.startsWith(clientPrefix)) {
|
|
11
|
+
return Effect.succeed([key, undefined]);
|
|
12
|
+
}
|
|
13
|
+
return envReadValueEffect(key, (env) => runtimeEnvReadEffect(env, runtimeSchema), options).pipe(Effect.flatMap((value) => envParseValueEffect(key, schema, value, options)), Effect.map((value) => [key, value]));
|
|
14
|
+
}).pipe(Effect.map((entries) => Object.fromEntries(entries))));
|
|
6
15
|
return env;
|
|
7
16
|
}
|
|
8
17
|
//# sourceMappingURL=create-env-effect.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-env-effect.js","sourceRoot":"","sources":["../../src/effects/create-env-effect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,UAAU,eAAe,CAC7B,OAAiB,EACjB,aAAuC,EACvC,oBAGY,EACZ,OAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CACxB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"create-env-effect.js","sourceRoot":"","sources":["../../src/effects/create-env-effect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,UAAU,eAAe,CAC7B,OAAiB,EACjB,aAAuC,EACvC,oBAGY,EACZ,OAAiB;IAEjB,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,UAAU,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,CAAC;IAE3C,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CACxB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE;QACxD,IACE,CAAC,QAAQ;YACT,YAAY,KAAK,SAAS;YAC1B,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,EAC7B,CAAC;YACD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,SAAS,CAAU,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,kBAAkB,CACvB,GAAG,EACH,CAAC,GAAG,EAAE,EAAE,CAAC,oBAAoB,CAAC,GAAG,EAAE,aAAa,CAAC,EACjD,OAAO,CACR,CAAC,IAAI,CACJ,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACvB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CACjD,EACD,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAU,CAAC,CAC7C,CAAC;IACJ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAC9D,CAAC;IAEF,OAAO,GAAoB,CAAC;AAC9B,CAAC"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type Env<TEnvKeys extends EnvKeys> = {
|
|
|
5
5
|
export type EnvKeys = Record<string, ZodType>;
|
|
6
6
|
export type EnvRecord = object;
|
|
7
7
|
export type Options = {
|
|
8
|
+
clientPrefix?: string;
|
|
9
|
+
isServer?: boolean;
|
|
8
10
|
skipValidation?: boolean;
|
|
9
11
|
};
|
|
10
12
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAEtC,MAAM,MAAM,GAAG,CAAC,QAAQ,SAAS,OAAO,IAAI;KACzC,CAAC,IAAI,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9C,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,MAAM,OAAO,GAAG;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAEtC,MAAM,MAAM,GAAG,CAAC,QAAQ,SAAS,OAAO,IAAI;KACzC,CAAC,IAAI,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9C,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,MAAM,OAAO,GAAG;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-record-env.d.ts","sourceRoot":"","sources":["../../../src/runtime/record/create-record-env.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAM3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,KAAK,CAAC,QAAQ,SAAS,OAAO,EAC5D,OAAO,EAAE,QAAQ,EACjB,MAAM,EAAE,SAAS,EACjB,OAAO,CAAC,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"create-record-env.d.ts","sourceRoot":"","sources":["../../../src/runtime/record/create-record-env.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAM3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,KAAK,CAAC,QAAQ,SAAS,OAAO,EAC5D,OAAO,EAAE,QAAQ,EACjB,MAAM,EAAE,SAAS,EACjB,OAAO,CAAC,EAAE,OAAO,GA4BH,GAAG,CAAC,QAAQ,CAAC,CAC5B"}
|
|
@@ -33,7 +33,16 @@ import { readRecordEnv } from "./lib/read-record-env.js";
|
|
|
33
33
|
* `options.skipValidation` is enabled.
|
|
34
34
|
*/
|
|
35
35
|
export function createRecordEnv(envKeys, record, options) {
|
|
36
|
-
const
|
|
36
|
+
const isServer = options?.isServer ?? !("window" in globalThis);
|
|
37
|
+
const clientPrefix = options?.clientPrefix;
|
|
38
|
+
const env = Effect.runSync(Effect.forEach(Object.entries(envKeys), ([key, schema]) => {
|
|
39
|
+
if (!isServer &&
|
|
40
|
+
clientPrefix !== undefined &&
|
|
41
|
+
!key.startsWith(clientPrefix)) {
|
|
42
|
+
return Effect.succeed([key, undefined]);
|
|
43
|
+
}
|
|
44
|
+
return envReadValueEffect(key, (env) => readRecordEnv(env, record), options).pipe(Effect.flatMap((value) => envParseValueEffect(key, schema, value, options)), Effect.map((value) => [key, value]));
|
|
45
|
+
}).pipe(Effect.map((entries) => Object.fromEntries(entries))));
|
|
37
46
|
return env;
|
|
38
47
|
}
|
|
39
48
|
//# sourceMappingURL=create-record-env.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-record-env.js","sourceRoot":"","sources":["../../../src/runtime/record/create-record-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAiB,EACjB,MAAiB,EACjB,OAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CACxB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"create-record-env.js","sourceRoot":"","sources":["../../../src/runtime/record/create-record-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAiB,EACjB,MAAiB,EACjB,OAAiB;IAEjB,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,UAAU,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,CAAC;IAE3C,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CACxB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE;QACxD,IACE,CAAC,QAAQ;YACT,YAAY,KAAK,SAAS;YAC1B,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,EAC7B,CAAC;YACD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,SAAS,CAAU,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,kBAAkB,CACvB,GAAG,EACH,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,EACnC,OAAO,CACR,CAAC,IAAI,CACJ,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACvB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CACjD,EACD,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAU,CAAC,CAC7C,CAAC;IACJ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAC9D,CAAC;IAEF,OAAO,GAAoB,CAAC;AAC9B,CAAC"}
|