@clipboard-health/config v0.14.2
@clipboard-health/config
Type-safe static configuration management: a pure function to resolve, validate against a Zod schema, and freeze configuration values.
Configuration values resolve in order from highest precedence to lowest:
- Environment variables
- Resolved converting configuration path from camelCase to UPPER_SNAKE. For example, the
{ myApi: { port: 3000 } }
configuration resolves toMY_API_PORT
.
- Resolved converting configuration path from camelCase to UPPER_SNAKE. For example, the
- Environment-specific overrides, {@link ConfigValue.overrides}
- Default values, {@link ConfigValue.defaultValue}
Supported configuration value types:
- bigint
- boolean
- date
- number
- string
- arrays and nested objects using the above types
To override arrays with environment variables, use stringified JSON arrays, e.g. ["a","b"]
.
IMPORTANT: To avoid runtime errors:
- Environment variables are strings, so use
z.coerce
Zod types for those you plan to override. Note thatz.coerce.boolean()
coerces any truthy value totrue
. To restrict to"true" | "false"
, use thebooleanString
schema from@clipboard-health/contract-core
. - The resulting configuration is deeply frozen and will throw a runtime error if you attempt to
modify it. The actual return type is
ReadonlyDeep<SchemaT>
, but the library returns aReadonly<SchemaT>
because the former prevents clients from passing configuration values to functions that don't explicitly acceptreadonly
types.
Table of contents
Install
npm install @clipboard-health/config
Usage
Type-safe configuration
import { ok } from "node:assert/strict";
import { createConfig } from "@clipboard-health/config";
import { z } from "zod";
const allowed = ["local", "development", "production"] as const;
type Allowed = (typeof allowed)[number];
function createEnvironmentConfig(current: Allowed) {
return createConfig({
config: {
baseUrl: {
defaultValue: "http://localhost:3000",
description: "Base URL for API requests",
overrides: {
development: "https://dev.example.com",
production: "https://api.example.com",
},
},
database: {
port: {
defaultValue: 5432,
description: "Database port",
},
},
},
environment: { allowed, current },
schema: z.object({
baseUrl: z.string().url(),
database: z.object({
// Use `z.coerce` to override with environment variables.
port: z.coerce.number().min(1024).max(65_535),
}),
}),
});
}
{
// Uses default values.
const config = createEnvironmentConfig("local");
ok(config.baseUrl === "http://localhost:3000");
ok(config.database.port === 5432);
}
{
// Uses baseUrl environment override.
const config = createEnvironmentConfig("development");
ok(config.baseUrl === "https://dev.example.com");
ok(config.database.port === 5432);
}
// Uses environment variable overrides.
const original = { ...process.env };
try {
process.env["BASE_URL"] = "https://staging.example.com";
process.env["DATABASE_PORT"] = "54320";
const config = createEnvironmentConfig("local");
ok(config.baseUrl === "https://staging.example.com");
ok(config.database.port === 54_320);
} finally {
process.env = { ...original };
}
Local development commands
See package.json
scripts
for a list of commands.
6 months ago
6 months ago
8 months ago
7 months ago
4 months ago
7 months ago
7 months ago
7 months ago
8 months ago
7 months ago
8 months ago
6 months ago
6 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
8 months ago
11 months ago
6 months ago
11 months ago
6 months ago
10 months ago
4 months ago
6 months ago
9 months ago
4 months ago
4 months ago
9 months ago
4 months ago
4 months ago
9 months ago
9 months ago
8 months ago
6 months ago
11 months ago
11 months ago
11 months ago
6 months ago
6 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago