Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

znv

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

znv - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

dist/reporter.d.ts

51

dist/parse-env.js

@@ -24,4 +24,4 @@ "use strict";

const z = __importStar(require("zod"));
const colorette_1 = require("colorette");
const preprocessors_1 = require("./preprocessors");
const reporter_1 = require("./reporter");
/**

@@ -58,10 +58,27 @@ * Since there might be a provided default value of `null` or `undefined`, we

const envValue = env[key];
let defaultUsed = false;
let defaultValue;
try {
if (schemaOrSpec instanceof z.ZodType) {
parsed[key] = (0, preprocessors_1.getSchemaWithPreprocessor)(schemaOrSpec).parse(envValue);
if (envValue == null && schemaOrSpec instanceof z.ZodDefault) {
defaultUsed = true;
defaultValue = schemaOrSpec._def.defaultValue();
// we "unwrap" the default value ourselves and pass it to the schema.
// in the very unlikely case that the value isn't stable AND
// validation fails, this ensures the default value we report is the
// one that was actually used.
// (consider `z.number().gte(0.5).default(() => Math.random())` -- if
// we invoked the default getter and got 0.7, and then ran the parser
// against a missing env var and it generated another default of 0.4,
// we'd report a default value that _should_ have passed.)
parsed[key] = schemaOrSpec.parse(defaultValue, { errorMap: reporter_1.errorMap });
}
else {
parsed[key] = (0, preprocessors_1.getSchemaWithPreprocessor)(schemaOrSpec).parse(envValue, { errorMap: reporter_1.errorMap });
}
}
else if (envValue == null) {
const [hasDefault, defaultValue] = resolveDefaultValueForSpec(schemaOrSpec.defaults, env["NODE_ENV"]);
if (hasDefault) {
parsed[key] = schemaOrSpec.schema.parse(defaultValue);
[defaultUsed, defaultValue] = resolveDefaultValueForSpec(schemaOrSpec.defaults, env["NODE_ENV"]);
if (defaultUsed) {
parsed[key] = schemaOrSpec.schema.parse(defaultValue, { errorMap: reporter_1.errorMap });
}

@@ -73,15 +90,21 @@ else {

// `null` for us).
parsed[key] = (0, preprocessors_1.getSchemaWithPreprocessor)(schemaOrSpec.schema).parse(envValue);
parsed[key] = (0, preprocessors_1.getSchemaWithPreprocessor)(schemaOrSpec.schema).parse(envValue, { errorMap: reporter_1.errorMap });
}
}
else {
parsed[key] = (0, preprocessors_1.getSchemaWithPreprocessor)(schemaOrSpec.schema).parse(envValue);
parsed[key] = (0, preprocessors_1.getSchemaWithPreprocessor)(schemaOrSpec.schema).parse(envValue, { errorMap: reporter_1.errorMap });
}
}
catch (e) {
errors.push([key, envValue, e]);
errors.push({
key,
receivedValue: envValue,
error: e,
defaultUsed,
defaultValue,
});
}
}
if (errors.length > 0) {
throw new Error(reportErrors(errors, schemas));
throw new Error((0, reporter_1.reportErrors)(errors, schemas));
}

@@ -91,12 +114,2 @@ return parsed;

exports.parseEnv = parseEnv;
const indent = (msg) => msg
.split("\n")
.map((line) => ` ${line}`)
.join("\n");
function reportErrors(errors, schemas) {
const errorMap = errors.map(([k, v, e]) => ` [${(0, colorette_1.yellow)(k)}]:\n${indent(e instanceof Error ? e.message : JSON.stringify(e))}\n (received ${typeof v === "undefined" ? (0, colorette_1.cyan)("undefined") : `\`${(0, colorette_1.cyan)(v)}\``})${schemas[k]?.description
? `\n\n Description of [${(0, colorette_1.yellow)(k)}]: ${schemas[k].description}`
: ""}`);
return `${(0, colorette_1.red)("Errors found!")}\n${errorMap.join("\n\n")}\n`;
}
//# sourceMappingURL=parse-env.js.map
{
"name": "znv",
"version": "0.2.0",
"version": "0.3.0",
"description": "Parse your environment with Zod schemas",

@@ -5,0 +5,0 @@ "keywords": [

# znv
<p align="center">
<img src="logo.svg" height="90">
</p>
<p align="center">
<a href="https://www.npmjs.com/package/znv">
<img src="https://img.shields.io/npm/v/znv.svg?logo=npm" alt="NPM version" />
</a>
</p>

@@ -15,2 +21,12 @@ Parse your environment with [Zod](https://github.com/colinhacks/zod).

- [Quickstart](#quickstart)
- [Motivation](#motivation)
- [Usage](#usage)
- [`parseEnv`](#parseenvenvironment-schemas)
- [Extra schemas](#extra-schemas)
- [Coercion rules](#coercion-rules)
- [Comparison to other libraries](#comparison-to-other-libraries)
- [Complementary tooling](#complementary-tooling)
- [How do I pronounce znv?](#how-do-i-pronounce-znv)
## Quickstart

@@ -36,5 +52,5 @@

In the above example, the exported values `API_SERVER`, `LLAMA_COUNT`, and
`COLOR` are all guaranteed to be defined and will be typed as `string`,
`number`, and `'red' | 'blue'`, respectively.
In the above example, the exported values `LLAMA_COUNT` and `COLOR` are
guaranteed to be defined and will be typed as `number` and `'red' | 'blue'`
respectively.

@@ -66,3 +82,3 @@ A more elaborate example:

production: "my-cool-llama.website",
staging: "cool-llama-staging.cloud-provider.zone",
test: "cool-llama-staging.cloud-provider.zone",

@@ -116,10 +132,11 @@ // "_" is a special token that can be used in `defaults`. its value will

certain code path is hit. A good way to avoid this is to **declare and validate
environment variables in one place** and to export the validated result, so that
environment variables in one place** and export the validated result, so that
other parts of your code can make their dependencies on these vars explicit.
Additionally, env vars represent one of the _boundaries_ of your application,
similar to an FFI call or a server request. In TypeScript, as in many other
typed languages, these boundaries present a challenge to maintaining a
well-typed app. [Zod](https://github.com/colinhacks/zod) does an excellent job
at parsing and validating poorly-typed data into clean, well-typed values.
Env vars represent one of the _boundaries_ of your application, just like file
I/O or a server request. In TypeScript, as in many other typed languages, these
boundaries present a challenge to maintaining a well-typed app.
[Zod](https://github.com/colinhacks/zod) does an excellent job at parsing and
validating poorly-typed data at boundaries into clean, well-typed values. znv
facilitates its use for environment validation.

@@ -141,2 +158,7 @@ ### What does znv actually do?

znv also makes it easy to define defaults for env vars based on your
environment. Zod allows you to define schema defaults, but making a given
default vary by environment or only act as a fallback in certain environments is
not straightforward.
## Usage

@@ -155,6 +177,9 @@

You usually want to pass in `process.env` as the first argument. **It is not
recommended** to use znv for general-purpose schema validation — just use Zod
for that.
You usually want to pass in `process.env` as the first argument.
> **It is not recommended** to use znv for general-purpose schema validation —
> just use Zod (with
> [preprocessors](https://github.com/colinhacks/zod#preprocess) to handle
> coercion, if necessary).
#### `schemas: Record<string, ZodType | DetailedSpec>`

@@ -210,15 +235,15 @@

Note that it is **not recommended** to use `staging` as a possible value for
`NODE_ENV`. Your staging environment should be as similar to your production
environment as possible, and `NODE_ENV=production` has special meaning for
several tools and libraries. For example,
[`npm install`](https://docs.npmjs.com/cli/v8/commands/npm-install) and
[`yarn install`](https://classic.yarnpkg.com/en/docs/cli/install#toc-yarn-install-production-true-false)
won't install `devDependencies` if `NODE_ENV=production`;
[Express](https://expressjs.com/en/advanced/best-practice-performance.html#set-node_env-to-production)
and [React](https://reactjs.org/docs/optimizing-performance.html) will also
behave differently depending on whether `NODE_ENV` is `production` or not.
Instead, your staging environment should also set `NODE_ENV=production`, and
you should define your own env var(s) for any special configuration that's
necessary for your staging environment.
> (As an aside, it is **not recommended** to use `staging` as a possible value
> for `NODE_ENV`. Your staging environment should be as similar to your
> production environment as possible, and `NODE_ENV=production` has special
> meaning for several tools and libraries. For example,
> [`npm install`](https://docs.npmjs.com/cli/v8/commands/npm-install) and
> [`yarn install`](https://classic.yarnpkg.com/en/docs/cli/install#toc-yarn-install-production-true-false)
> by default won't install `devDependencies` if `NODE_ENV=production`;
> [Express](https://expressjs.com/en/advanced/best-practice-performance.html#set-node_env-to-production)
> and [React](https://reactjs.org/docs/optimizing-performance.html) will also
> behave differently depending on whether `NODE_ENV` is `production` or not.
> Instead, your staging environment should also set `NODE_ENV=production`, and
> you should define your own env var(s) for any special configuration that's
> necessary for your staging environment.)

@@ -232,3 +257,3 @@ However, `_` still lets you express a few interesting scenarios:

// default for all environments, but require the var to be defined in prod.
// default for all environments, but require the var to be passed in in prod.
{ production: undefined, _: "dev default" }

@@ -244,10 +269,11 @@

`parseEnv` doesn't restrict or validate `NODE_ENV`, but you can add it to your
schemas like any other env var. For example, you could use
`parseEnv` doesn't restrict or validate `NODE_ENV` to any particular values,
but you can add `NODE_ENV` to your schemas like any other env var. For
example, you could use
`NODE_ENV: z.enum(["production", "development", "test", "ci"])` to enforce
that `NODE_ENV` is always defined and is one of the expected values.
that `NODE_ENV` is always defined and is one of those four expected values.
### Extra schemas
znv exports a very small number of extra schema for common env var types.
znv exports a very small number of extra schemas for common env var types.

@@ -260,9 +286,6 @@ #### `port()`

`deprecate()` is an alias for `z.undefined().transform(() => undefined as never)`.
This will do two things:
`deprecate()` is an alias for
`z.undefined().transform(() => undefined as never)`. `parseEnv` will throw if a
var using the `deprecate()` schema is passed in from the environment.
- throw if the var is defined in the environment
- yield a TypeScript error if the value returned from `parseEnv` is used
anywhere in your code.
## Coercion rules

@@ -287,9 +310,8 @@

- If your schema's input is a Date, znv will call `new Date()` with the input
value. This has a number of pitfalls, and `Date()` constructor is excessively
forgiving. The value is passed in as a string, which means trying to pass a
Unix epoch will yield unexpected results. (Epochs need to be passed in as
`number`; `new Date()` with an epoch as a string might give you an
`invalid date` or might equally give you a well-formed but utterly incorrect
date.) _You should only pass in ISO 8601 date strings_, such as those returned
by `Date.prototype.toISOString()`.
value. This has a number of pitfalls, since the `Date()` constructor is
excessively forgiving. The value is passed in as a string, which means trying
to pass a Unix epoch will yield unexpected results. (Epochs need to be passed
in as `number`: `new Date()` with an epoch as a string will either give you
`invalid date` or a completely nonsensical date.) _You should only pass in ISO
8601 date strings_, such as those returned by `Date.prototype.toISOString()`.
- Zod defines "nullable" as distinct from "optional". If your schema is

@@ -303,9 +325,8 @@ nullable, znv will coerce `undefined` to `null`. Generally it's preferred to

Envalid is a nice little library, and znv's design was inspired by it. Envalid
has a similar API and is written in TypeScript. It performs some inference of
the return value based on the validator schema you pass in, but won't do things
like narrow enumerated types (`str({ choices: ['a', 'b'] })`) to a union of
literals. Expressing defaults is more limited (you can't have different defaults
for `test` and `development` environments, for example). Defaults are not passed
through validators.
Envalid is a nice library that inspired znv's API design. Envalid is written in
TypeScript and performs some inference of the return value based on the
validator schema you pass in, but won't do things like narrow enumerated types
(`str({ choices: ['a', 'b'] })`) to a union of literals. Expressing defaults is
more limited (you can't have different defaults for `test` and `development`
environments, for example). Defaults are not passed through validators.

@@ -322,5 +343,6 @@ Envalid's validators are built-in and express a handful of types with limited

Joi is the "classic" schema validation library. Joi is written in JavaScript,
and its type definitions support a very limited form of inference when they work
at all.
Joi is the Cadillac of schema validation libraries. Its default of coercing
strings to the target type makes it easy to adopt for environment validation.
Unfortunately, Joi is written in JavaScript and its type definitions support a
very limited form of inference when they work at all.

@@ -335,1 +357,8 @@ ## Complementary tooling

znv also works great with [dotenv](https://github.com/motdotla/dotenv).
## How do I pronounce znv?
If you usually pronounce "z" as "zed," then you could say "zenv." If you usually
pronounce "z" as "zee," you could say "zee en vee."
Or do your own thing. I'm not the boss of you.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc