Comparing version 0.3.2 to 0.4.0
@@ -1,34 +0,6 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.deprecate = exports.port = void 0; | ||
const z = __importStar(require("zod")); | ||
const port = () => z.number().int().nonnegative().lte(65535); | ||
exports.port = port; | ||
const deprecate = () => z | ||
import * as z from "zod"; | ||
export const port = () => z.number().int().nonnegative().lte(65535); | ||
export const deprecate = () => z | ||
.undefined({ invalid_type_error: "This var is deprecated." }) | ||
.transform(() => undefined); | ||
exports.deprecate = deprecate; | ||
//# sourceMappingURL=extra-schemas.js.map |
export { z } from "zod"; | ||
export * from "./parse-env"; | ||
export * from "./preprocessors"; | ||
export * from "./extra-schemas"; | ||
export * from "./parse-env.js"; | ||
export * from "./preprocessors.js"; | ||
export * from "./extra-schemas.js"; |
@@ -1,23 +0,5 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.z = void 0; | ||
var zod_1 = require("zod"); | ||
Object.defineProperty(exports, "z", { enumerable: true, get: function () { return zod_1.z; } }); | ||
__exportStar(require("./parse-env"), exports); | ||
__exportStar(require("./preprocessors"), exports); | ||
__exportStar(require("./extra-schemas"), exports); | ||
export { z } from "zod"; | ||
export * from "./parse-env.js"; | ||
export * from "./preprocessors.js"; | ||
export * from "./extra-schemas.js"; | ||
//# sourceMappingURL=index.js.map |
import * as z from "zod"; | ||
import type { DeepReadonlyObject } from "./util"; | ||
export declare type SimpleSchema<TOut = any, TIn = any> = z.ZodType<TOut, z.ZodTypeDef, TIn>; | ||
export declare type DetailedSpec<TSchema extends SimpleSchema = SimpleSchema<unknown, unknown>> = TSchema extends SimpleSchema<any, infer TIn> ? { | ||
import type { DeepReadonlyObject } from "./util.js"; | ||
export type SimpleSchema<TOut = any, TIn = any> = z.ZodType<TOut, z.ZodTypeDef, TIn>; | ||
export type DetailedSpec<TSchema extends SimpleSchema = SimpleSchema<unknown, unknown>> = TSchema extends SimpleSchema<any, infer TIn> ? { | ||
/** | ||
@@ -30,8 +30,8 @@ * The Zod schema that will be used to parse the passed environment value | ||
} : never; | ||
export declare type Schemas = Record<string, SimpleSchema | DetailedSpec>; | ||
declare type DetailedSpecKeys = keyof DetailedSpec; | ||
export declare type RestrictSchemas<T extends Schemas> = { | ||
export type Schemas = Record<string, SimpleSchema | DetailedSpec>; | ||
type DetailedSpecKeys = keyof DetailedSpec; | ||
export type RestrictSchemas<T extends Schemas> = { | ||
[K in keyof T]: T[K] extends SimpleSchema ? SimpleSchema : T[K] extends DetailedSpec ? DetailedSpec<T[K]["schema"]> & Omit<Record<keyof T[K], never>, DetailedSpecKeys> : never; | ||
}; | ||
export declare type ParsedSchema<T extends Schemas> = T extends any ? { | ||
export type ParsedSchema<T extends Schemas> = T extends any ? { | ||
[K in keyof T]: T[K] extends SimpleSchema<infer TOut> ? TOut : T[K] extends DetailedSpec ? T[K]["schema"] extends SimpleSchema<infer TOut> ? TOut : never : never; | ||
@@ -38,0 +38,0 @@ } : never; |
@@ -1,30 +0,4 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.parseEnv = exports.inferSchemas = exports.resolveDefaultValueForSpec = void 0; | ||
const z = __importStar(require("zod")); | ||
const preprocessors_1 = require("./preprocessors"); | ||
const reporter_1 = require("./reporter"); | ||
import * as z from "zod"; | ||
import { getSchemaWithPreprocessor } from "./preprocessors.js"; | ||
import { reportErrors, errorMap } from "./reporter.js"; | ||
/** | ||
@@ -34,3 +8,3 @@ * Since there might be a provided default value of `null` or `undefined`, we | ||
*/ | ||
function resolveDefaultValueForSpec(defaults, nodeEnv) { | ||
export function resolveDefaultValueForSpec(defaults, nodeEnv) { | ||
if (defaults) { | ||
@@ -46,3 +20,2 @@ if (nodeEnv != null && | ||
} | ||
exports.resolveDefaultValueForSpec = resolveDefaultValueForSpec; | ||
/** | ||
@@ -52,4 +25,3 @@ * Mostly an internal convenience function for testing. Returns the input | ||
*/ | ||
const inferSchemas = (schemas) => schemas; | ||
exports.inferSchemas = inferSchemas; | ||
export const inferSchemas = (schemas) => schemas; | ||
/** | ||
@@ -59,3 +31,3 @@ * Parses the passed environment object using the provided map of Zod schemas | ||
*/ | ||
function parseEnv(env, schemas) { | ||
export function parseEnv(env, schemas) { | ||
const parsed = {}; | ||
@@ -80,6 +52,6 @@ const errors = []; | ||
// we'd report a default value that _should_ have passed.) | ||
parsed[key] = schemaOrSpec.parse(defaultValue, { errorMap: reporter_1.errorMap }); | ||
parsed[key] = schemaOrSpec.parse(defaultValue, { errorMap }); | ||
} | ||
else { | ||
parsed[key] = (0, preprocessors_1.getSchemaWithPreprocessor)(schemaOrSpec).parse(envValue, { errorMap: reporter_1.errorMap }); | ||
parsed[key] = getSchemaWithPreprocessor(schemaOrSpec).parse(envValue, { errorMap }); | ||
} | ||
@@ -90,3 +62,3 @@ } | ||
if (defaultUsed) { | ||
parsed[key] = schemaOrSpec.schema.parse(defaultValue, { errorMap: reporter_1.errorMap }); | ||
parsed[key] = schemaOrSpec.schema.parse(defaultValue, { errorMap }); | ||
} | ||
@@ -98,7 +70,7 @@ else { | ||
// `null` for us). | ||
parsed[key] = (0, preprocessors_1.getSchemaWithPreprocessor)(schemaOrSpec.schema).parse(envValue, { errorMap: reporter_1.errorMap }); | ||
parsed[key] = getSchemaWithPreprocessor(schemaOrSpec.schema).parse(envValue, { errorMap }); | ||
} | ||
} | ||
else { | ||
parsed[key] = (0, preprocessors_1.getSchemaWithPreprocessor)(schemaOrSpec.schema).parse(envValue, { errorMap: reporter_1.errorMap }); | ||
parsed[key] = getSchemaWithPreprocessor(schemaOrSpec.schema).parse(envValue, { errorMap }); | ||
} | ||
@@ -117,7 +89,6 @@ } | ||
if (errors.length > 0) { | ||
throw new Error((0, reporter_1.reportErrors)(errors, schemas)); | ||
throw new Error(reportErrors(errors, schemas)); | ||
} | ||
return parsed; | ||
} | ||
exports.parseEnv = parseEnv; | ||
//# sourceMappingURL=parse-env.js.map |
@@ -1,29 +0,3 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getSchemaWithPreprocessor = exports.getPreprocessorByZodType = void 0; | ||
const z = __importStar(require("zod")); | ||
const util_1 = require("./util"); | ||
import * as z from "zod"; | ||
import { assertNever } from "./util.js"; | ||
const { ZodFirstPartyTypeKind: TypeName } = z; | ||
@@ -34,3 +8,3 @@ /** | ||
*/ | ||
function getPreprocessorByZodType(schema) { | ||
export function getPreprocessorByZodType(schema) { | ||
const def = schema._def; | ||
@@ -188,9 +162,9 @@ const { typeName } = def; | ||
case TypeName.ZodSet: | ||
case TypeName.ZodNaN: | ||
throw new Error(`Zod type not supported: ${typeName}`); | ||
default: { | ||
(0, util_1.assertNever)(typeName); | ||
assertNever(typeName); | ||
} | ||
} | ||
} | ||
exports.getPreprocessorByZodType = getPreprocessorByZodType; | ||
/** | ||
@@ -200,6 +174,5 @@ * Given a Zod schema, return the schema wrapped in a preprocessor that tries to | ||
*/ | ||
function getSchemaWithPreprocessor(schema) { | ||
export function getSchemaWithPreprocessor(schema) { | ||
return z.preprocess(getPreprocessorByZodType(schema), schema); | ||
} | ||
exports.getSchemaWithPreprocessor = getSchemaWithPreprocessor; | ||
//# sourceMappingURL=preprocessors.js.map |
import { ZodErrorMap } from "zod"; | ||
import { Schemas } from "./parse-env"; | ||
import { Schemas } from "./parse-env.js"; | ||
export declare const errorMap: ZodErrorMap; | ||
@@ -4,0 +4,0 @@ export interface ErrorWithContext { |
@@ -1,6 +0,3 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.reportErrors = exports.errorMap = void 0; | ||
const zod_1 = require("zod"); | ||
const colorette_1 = require("colorette"); | ||
import { ZodError, ZodIssueCode } from "zod"; | ||
import { yellow, red, cyan, green } from "colorette"; | ||
// Even though we also have our own formatter, we pass a custom error map to | ||
@@ -11,4 +8,4 @@ // Zod's `.parse()` for two reasons: | ||
// - to return slightly friendly error messages in some common scenarios. | ||
const errorMap = (issue, ctx) => { | ||
if (issue.code === zod_1.ZodIssueCode.invalid_type && | ||
export const errorMap = (issue, ctx) => { | ||
if (issue.code === ZodIssueCode.invalid_type && | ||
issue.received === "undefined") { | ||
@@ -19,8 +16,7 @@ return { message: "This field is required." }; | ||
}; | ||
exports.errorMap = errorMap; | ||
const indent = (str, amt) => `${" ".repeat(amt)}${str}`; | ||
function reportErrors(errors, schemas) { | ||
export function reportErrors(errors, schemas) { | ||
const formattedErrors = errors.map(({ key, receivedValue, error, defaultUsed, defaultValue }) => { | ||
const message = [`[${(0, colorette_1.yellow)(key)}]:`]; | ||
if (error instanceof zod_1.ZodError) { | ||
const message = [`[${yellow(key)}]:`]; | ||
if (error instanceof ZodError) { | ||
const { formErrors, fieldErrors } = error.flatten(); | ||
@@ -33,3 +29,3 @@ for (const fe of formErrors) | ||
for (const [objKey, keyErrors] of fieldErrorEntries) { | ||
message.push(indent(`[${(0, colorette_1.green)(objKey)}]:`, 4)); | ||
message.push(indent(`[${green(objKey)}]:`, 4)); | ||
for (const fe of keyErrors) | ||
@@ -48,7 +44,7 @@ message.push(indent(fe, 6)); | ||
} | ||
message.push(indent(`(received ${(0, colorette_1.cyan)(receivedValue === undefined | ||
message.push(indent(`(received ${cyan(receivedValue === undefined | ||
? "undefined" | ||
: JSON.stringify(receivedValue))})`, 2)); | ||
if (defaultUsed) { | ||
message.push(indent(`(used default of ${(0, colorette_1.cyan)(defaultValue === undefined | ||
message.push(indent(`(used default of ${cyan(defaultValue === undefined | ||
? "undefined" | ||
@@ -60,9 +56,8 @@ : JSON.stringify(defaultValue))})`, 2)); | ||
message.push(""); | ||
message.push(`Description of [${(0, colorette_1.yellow)(key)}]: ${schemas[key].description}`); | ||
message.push(`Description of [${yellow(key)}]: ${schemas[key].description}`); | ||
} | ||
return message.map((l) => indent(l, 2)).join("\n"); | ||
}); | ||
return `${(0, colorette_1.red)("Errors found while parsing environment:")}\n${formattedErrors.join("\n\n")}\n`; | ||
return `${red("Errors found while parsing environment:")}\n${formattedErrors.join("\n\n")}\n`; | ||
} | ||
exports.reportErrors = reportErrors; | ||
//# sourceMappingURL=reporter.js.map |
export declare function assertNever(value: never): never; | ||
declare type primitive = string | number | boolean | undefined | null; | ||
export declare type DeepReadonlyArray<T> = ReadonlyArray<DeepReadonly<T>>; | ||
export declare type DeepReadonlyObject<T> = { | ||
type primitive = string | number | boolean | undefined | null; | ||
export type DeepReadonlyArray<T> = ReadonlyArray<DeepReadonly<T>>; | ||
export type DeepReadonlyObject<T> = { | ||
readonly [P in keyof T]: DeepReadonly<T[P]>; | ||
}; | ||
export declare type DeepReadonly<T> = T extends primitive ? T : T extends Array<infer U> ? DeepReadonlyArray<U> : DeepReadonlyObject<T>; | ||
export type DeepReadonly<T> = T extends primitive ? T : T extends Array<infer U> ? DeepReadonlyArray<U> : DeepReadonlyObject<T>; | ||
export {}; |
@@ -1,8 +0,4 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.assertNever = void 0; | ||
function assertNever(value) { | ||
export function assertNever(value) { | ||
throw new Error(`Unhandled type: ${JSON.stringify(value)}`); | ||
} | ||
exports.assertNever = assertNever; | ||
//# sourceMappingURL=util.js.map |
{ | ||
"name": "znv", | ||
"version": "0.3.2", | ||
"version": "0.4.0", | ||
"description": "Parse your environment with Zod schemas", | ||
"type": "module", | ||
"keywords": [ | ||
@@ -11,4 +12,5 @@ "env", | ||
], | ||
"main": "dist/index.js", | ||
"main": "dist-cjs/index.js", | ||
"types": "dist/index.d.ts", | ||
"module": "dist/index.js", | ||
"author": "s <https://github.com/lostfictions>", | ||
@@ -24,8 +26,24 @@ "homepage": "https://github.com/lostfictions/znv", | ||
"files": [ | ||
"!dist/**/*.test.*", | ||
"dist/" | ||
"dist/", | ||
"dist-cjs/" | ||
], | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist-cjs/index.d.ts", | ||
"default": "./dist-cjs/index.js" | ||
} | ||
} | ||
}, | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "rm -rf dist/ && tsc", | ||
"build": "run-s -l build:*", | ||
"build:clean": "rm -rf dist/ dist-cjs/", | ||
"build:mjs": "tsc --project tsconfig.build.json", | ||
"build:cjs": "tsc --project tsconfig.cjs.build.json", | ||
"build:copy": "cp package.cjs.json dist-cjs/package.json", | ||
"test": "run-p -cl test:*", | ||
@@ -44,19 +62,25 @@ "test:ts": "tsc --noEmit", | ||
"peerDependencies": { | ||
"zod": "^3.11.6" | ||
"zod": "^3.13.2" | ||
}, | ||
"devDependencies": { | ||
"@types/jest": "^29.2.4", | ||
"@types/node": "^16.18.8", | ||
"eslint": "^8.29.0", | ||
"eslint-config-lostfictions": "^5.0.0", | ||
"jest": "^29.3.1", | ||
"@types/jest": "^29.5.4", | ||
"@types/node": "^16.18.24", | ||
"eslint": "^8.48.0", | ||
"eslint-config-lostfictions": "^6.0.0", | ||
"jest": "^29.6.4", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^2.8.1", | ||
"ts-jest": "^29.0.3", | ||
"prettier": "^3.0.3", | ||
"ts-jest": "^29.1.1", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^4.7.4", | ||
"zod": "^3.11.6" | ||
"typescript": "^4.9.5", | ||
"zod": "~3.13.2" | ||
}, | ||
"jest": { | ||
"preset": "ts-jest", | ||
"preset": "ts-jest/presets/default-esm", | ||
"moduleNameMapper": { | ||
"^(\\.{1,2}/.*)\\.js$": "$1" | ||
}, | ||
"extensionsToTreatAsEsm": [ | ||
".ts" | ||
], | ||
"rootDir": "src", | ||
@@ -67,3 +91,4 @@ "transform": { | ||
{ | ||
"isolatedModules": true | ||
"isolatedModules": true, | ||
"useESM": true | ||
} | ||
@@ -70,0 +95,0 @@ ] |
@@ -41,21 +41,2 @@ # znv | ||
/////////// notes | ||
- Parsing and validation of embedded JSON makes it convenient to define a bundle | ||
of related (non-orthogonal) config values, arrays of values, etc. Also eases | ||
the transition to/from config files. | ||
- Robust defaults management | ||
todo: | ||
- allow passing getter function to defaults keys | ||
- allow passing function to defaults | ||
- recipe: merging multiple configurations (actually hard if it's not all stringly-typed) | ||
- recipe: use with next.js | ||
- antipattern: complex dependencies/defaults | ||
## Quickstart | ||
@@ -187,4 +168,2 @@ | ||
https://danluu.com/postmortem-lessons/ | ||
Env vars represent one of the _boundaries_ of your application, just like file | ||
@@ -427,32 +406,2 @@ I/O or a server request. In TypeScript, as in many other typed languages, these | ||
===================== | ||
comparisons | ||
===================== | ||
config comparison | ||
https://github.com/lorenwest/node-config | ||
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/config/index.d.ts | ||
mostly not for env but supports it. totally untyped and untypeable, needlessly | ||
complex, "validation" is throwing on undefined and that's it, mostly goes | ||
against 12 factor | ||
convict comparison | ||
https://github.com/mozilla/node-convict/tree/master/packages/convict | ||
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/convict/index.d.ts | ||
not just for env -- handles command-line args, loads from file, merges. | ||
interesting best-effort typings but the library itself allows too much | ||
looseness. validation is limited and not composeable, uses validate method that | ||
you can forget to call (violates "parse, don't validate") | ||
nconf comparison | ||
https://github.com/indexzero/nconf | ||
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/nconf/index.d.ts | ||
untyped. does too much (encryption! storage engines!) but no validation | ||
cosmiconfig | ||
https://github.com/davidtheclark/cosmiconfig | ||
not for env | ||
========================== | ||
## Complementary tooling | ||
@@ -459,0 +408,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83780
40
948
Yes
419
1