Austenite
Declarative environment variables for TypeScript
Install / Use
/learn @ezzatron/AusteniteREADME
Austenite
Declarative environment variables for TypeScript.
Usage
// env.ts - declares everything needed from the environment
import { boolean, url } from "austenite";
export const cdnUrl = url("CDN_URL", "CDN to use when serving static assets");
export const isDebug = boolean(
"DEBUG",
"enable or disable debugging features",
{ default: false },
);
// run.ts - starts the service/app, uses declarations from above
import { initialize } from "austenite/node";
import { cdnUrl, isDebug } from "./env.ts";
// validates the environment, option defaults shown here
await initialize({
// set to "none" to disable Markdown pretty-printing
markdownPrettyPrint: "prettier",
});
// cdnUrl.value() is a URL
console.log(`CDN URL hostname is ${cdnUrl.value().hostname}`);
// isDebug.value() is a boolean
console.log(`Debug mode is ${isDebug.value() ? "enabled" : "disabled"}`);
Validation summaries
If the environment is invalid, calling initialize() will terminate the process
with a non-zero exit code, and output a table that describes what went wrong:
Environment Variables:
❯ CDN_URL CDN to use when serving static assets <URL> ✗ set to host.example.org, must be a URL
❯ DEBUG enable or disable debugging features [ true | false ] = false ✗ set to yes, expected true or false
❯ EARTH_ATOM_COUNT number of atoms on earth [ <big integer> ] ✗ set to 5.9722e24, must be a big integer
❯ GRPC_TIMEOUT gRPC request timeout [ <ISO 8601 duration> ] ✗ set to PT30S, must be <= PT10S
❯ LOG_LEVEL the minimum log level to record [ debug | info | warn | error | fatal ] = info ✗ set to silly, expected debug, info, warn, error, or fatal
❯ PORT listen port for the HTTP server [ <port number> ] = 8080 ✗ set to 65536, must be between 1 and 65535
❯ READ_DSN database connection string for read-models <string> ✗ set to host=localhost, must have a minimum length of 30, but has a length of 14
❯ REDIS_PRIMARY_SERVICE_HOST kubernetes `redis-primary` service host <hostname> ✗ set to .redis.example.org, must not begin or end with a dot
❯ REDIS_PRIMARY_SERVICE_PORT kubernetes `redis-primary` service port <port number> ✗ set to 65536, must be between 1 and 65535
❯ SAMPLE_RATIO ratio of requests to sample [ <number> ] ✗ set to 1/100, must be numeric
❯ SESSION_KEY session token signing key <base64> ✗ set to <sensitive value>, must be base64 encoded
❯ WEIGHT weighting for this node <integer> ✗ set to 0, must be >= 1
Generated usage documentation
If the environment variable AUSTENITE_MODE is set to usage/markdown, calling
initialize() will terminate the process with a zero exit code, and output a
Markdown document containing usage documentation for the environment variables
consumed by each declaration.
<!-- prettier-ignore-end --> <!-- prettier-ignore-start -->[!IMPORTANT] See ENVIRONMENT.md for example output.
<!-- prettier-ignore-end -->[!TIP] If you have the
prettierNPM package installed, Austenite will pretty-print Markdown output according to your Prettier config for a file at./ENVIRONMENT.md.If you have Prettier installed, but don't have a config file for
./ENVIRONMENT.md, Austenite will use its own default Prettier config.If you don't have Prettier installed, or if you set the
markdownPrettyPrintoption to"none", Austenite won't pretty-print Markdown output.
Declarations
bigInteger
import { bigInteger } from "austenite";
// required
export const earthAtomCount = bigInteger(
"EARTH_ATOM_COUNT",
"number of atoms on earth",
);
// optional
export const earthAtomCount = bigInteger(
"EARTH_ATOM_COUNT",
"number of atoms on earth",
{ default: undefined },
);
// default
export const earthAtomCount = bigInteger(
"EARTH_ATOM_COUNT",
"number of atoms on earth",
{ default: 5_972_200_000_000_000_000_000_000n },
);
// min/max
export const earthAtomCount = bigInteger(
"EARTH_ATOM_COUNT",
"number of atoms on earth",
{
min: 5_000_000_000_000_000_000_000_000n,
max: 6_000_000_000_000_000_000_000_000n,
},
);
// example values
export const earthAtomCount = bigInteger(
"EARTH_ATOM_COUNT",
"number of atoms on earth",
{
examples: [
{ value: 5_000_000_000_000_000_000_000_000n, label: "5 septillion" },
{
value: 6_000_000_000_000_000_000_000_000n,
as: "0x4f68ca6d8cd91c6000000",
label: "6 septillion",
},
],
},
);
// constraints
export const earthAtomCount = bigInteger(
"EARTH_ATOM_COUNT",
"number of atoms on earth",
{
constraints: [
{
description: "must be a multiple of 1000",
constrain: (v) => v % 1_000n === 0n || "must be a multiple of 1000",
},
],
examples: [
{ value: 5_972_200_000_000_000_000_000_000n, label: "5.9722 septillion" },
],
},
);
binary
import { binary } from "austenite";
// required
export const sessionKey = binary("SESSION_KEY", "session token signing key");
// sensitive
export const sessionKey = binary("SESSION_KEY", "session token signing key", {
isSensitive: true,
});
// optional
export const sessionKey = binary("SESSION_KEY", "session token signing key", {
default: undefined,
});
// default
export const sessionKey = binary("SESSION_KEY", "session token signing key", {
default: Buffer.from("SUPER_SECRET_256_BIT_SIGNING_KEY", "utf-8"),
});
// base64url
export const sessionKey = binary("SESSION_KEY", "session token signing key", {
encoding: "base64url",
});
// hex
export const sessionKey = binary("SESSION_KEY", "session token signing key", {
encoding: "hex",
});
// exact length
export const sessionKey = binary("SESSION_KEY", "session token signing key", {
length: 32,
});
// min/max length
export const sessionKey = binary("SESSION_KEY", "session token signing key", {
length: { min: 32, max: 64 },
});
// example values
export const sessionKey = binary("SESSION_KEY", "session token signing key", {
examples: [
{
value: Buffer.from("128_BIT_SIGN_KEY", "utf-8"),
label: "128-bit key",
},
{
value: Buffer.from("SUPER_SECRET_256_BIT_SIGNING_KEY", "utf-8"),
as: "U1VQRVJfU0VDUkVUXzI1Nl9CSVRfU0lHTklOR19LRVk",
label: "256-bit key",
},
],
});
// constraints
export const sessionKey = binary("SESSION_KEY", "session token signing key", {
constraints: [
{
description: "must be 128 or 256 bits",
constrain: (v) =>
[16, 32].includes(v.length) || "decoded length must be 16 or 32",
},
],
examples: [
{
value: Buffer.from("SUPER_SECRET_256_BIT_SIGNING_KEY", "utf-8"),
label: "256-bit key",
},
],
});
boolean
import { boolean } from "austenite";
// required
export const isDebug = boolean("DEBUG", "enable or disable debugging features");
// optional
export const isDebug = boolean(
"DEBUG",
"enable or disable debugging features",
{ default: undefined },
);
// default
export const isDebug = boolean(
"DEBUG",
"enable or disable debugging features",
{ default: false },
);
// custom literals
export const isDebug = boolean(
"DEBUG",
"enable or disable debugging features",
{ literals: { y: true, yes: true, n: false, no: false } },
);
// example values
export const isDebug = boolean(
"DEBUG",
"enable or disable debugging features",
{
literals: { y: true, yes: true, n: false, no: false },
examples: [
{ value: true, label: "enabled" },
{ value: false, as: "no", label: "disabled" },
],
},
);
// constraints
export const isDebug = boolean(
"DEBUG",
"enable or disable debugging features",
{
constraints: [
{
description: "must not be enabled on Windows",
constrain: (v) =>
!v ||
process.platform !== "win32" ||
"must not be enabled on Windows",
},
],
examples: [{ value: false, label: "disabled" }],
},
);
duration
import { Temporal } from "@js-temporal/polyfill";
import { duration } from "austenite";
// required
export const grpcTimeout = duration("GRPC_TIMEOUT", "gRPC request timeout");
// optional
export const grpcTimeout = duration("GRPC_TIMEOUT", "gRPC request timeout", {
default: undefined,
});
// default
export const grpcTimeout = duration("GRPC_TIMEOUT", "gRPC request timeout", {
default: Temporal.Duration.from("PT10S"),
});
// min/max
export const grpcTimeout = duration("GRPC_TIMEOU
