Reference / Config API for Bun and Node
Config API for Bun and Node
Every public class, function and type of the Config engine in @tinyshed/tinystore, generated from its source. The Config guide explains how to use them, and the Python, Go and Rust pages list the same API.
Setting
interface Setting<V, Live extends boolean = false, Given extends boolean = true, IsSecret extends boolean = false> {
readonly [mark]: Described
/** what the program reads it as; nothing at run time */
readonly '~value'?: V
readonly '~live'?: Live
readonly '~given'?: Given
readonly '~secret'?: IsSecret
}A setting its declaration says more of than a default would: its rules, a
secret, one a layer must give, or one that may change while the program
runs. V is what the program reads it as, Live whether it may change,
and Given whether it has a default or is required, as a declaration needs.
Secret
class Secret {}A setting's text that prints as *** wherever it goes; reveal gives it.
Secret.reveal
reveal(): stringThe secret's text, where the program hands it to what needs it.
Secret.toString
toString(): stringSecret.toJSON
toJSON(): stringValue
type Value<D> = D extends Setting<infer V, boolean, boolean, boolean> ? V : D extends string ? string : D extends number ? number : D extends boolean ? boolean : D extends null ? null : D extends readonly (infer I)[] ? readonly Value<I>[] : D extends object ? {
readonly [K in keyof D]: Value<D[K]>
} : neverWhat a program reads of a declaration: a setting as its value, a group as its settings.
Changes
type Changes<D> = {
readonly [K in keyof D as LiveIn<D[K]> extends true ? K : never]?: D[K] extends Setting<infer V, true, boolean, boolean> ? V : Changes<D[K]>
}The live settings a change may name, each as the program reads it, at any depth.
Overlay
type Overlay<D> = {
readonly [K in keyof D]?: D[K] extends Setting<infer V, boolean, boolean, boolean> ? V extends Secret ? string : V : D[K] extends readonly unknown[] ? Value<D[K]> : D[K] extends object ? Overlay<D[K]> : Value<D[K]>
}An object in code over the declaration: any of its settings, at any depth, a secret as text.
FileLayer
interface FileLayer {
readonly [layerMark]: 'file'
readonly path: string
readonly optional: boolean
}A file a config reads: TOML, YAML or JSON by its extension.
EnvLayer
interface EnvLayer {
readonly [layerMark]: 'env'
readonly prefix: string
/** a setting's own variable, by its path */
readonly vars: Readonly<Record<string, string>>
readonly files: readonly string[]
readonly from: Readonly<Record<string, string | undefined>> | undefined
}The environment a config reads.
Layer
type Layer<D> = FileLayer | EnvLayer | Overlay<D> | false | null | undefinedA layer of a config's list: an object in code, a file, the environment, or nothing.
Vars
interface Vars {
readonly [key: string]: string | Vars
}Settings' own variables by their paths: { port: 'PORT', db: { url: 'DATABASE_URL' } }.
EnvOptions
interface EnvOptions {
/** a setting's variable of its own, in place of its prefixed one */
vars?: Vars | undefined
/** .env files, whose variables count where the process has none; Bun reads .env itself */
files?: readonly string[] | undefined
/** these variables in place of the process's, the only environment read, as a test gives them */
from?: Readonly<Record<string, string | undefined>> | undefined
}ConfigOptions
interface ConfigOptions<V> {
/**
* the program's own check of the whole value, at open and before a change
* is kept: a Standard Schema such as zod's or valibot's, or a function
* that throws
*/
validate?: StandardSchemaV1 | ((value: V) => unknown) | undefined
/** refuses to open while a kept change no longer fits, rather than ignoring it and saying so */
strict?: boolean | undefined
}UpdateOptions
interface UpdateOptions {
/** keeps the change only while the config is at this version, else ConflictError */
ifVersion?: number | undefined
}ExplainLine
interface ExplainLine {
readonly path: string
/** as JSON, a duration spelled, a secret as *** */
readonly value: string
/** the layer that gave it: APP_PORT, app.yaml, layer 2, the declaration, a change */
readonly from: string
/** the values it went over, newest first */
readonly over: string
}A setting's line of explain.
Explained
type Explained = readonly ExplainLine[] & {
readonly notes: readonly string[]
}Every setting's line, for console.table, and what was read and not used.
Bounds
interface Bounds {
min?: number | undefined
max?: number | undefined
}The bounds of a number: the smallest and the largest it may be.
DurationBounds
interface DurationBounds {
min?: DurationText | undefined
max?: DurationText | undefined
}The bounds of a duration, each a duration's text.
secret
function secret(given: StringConstructor | string): Setting<Secret, false, true, true>A setting that prints as *** wherever it goes and that only a layer gives:
secret(String) must be given, secret('') has a default.
required
function required<T extends Token>(type: T): Setting<Of<T>>
function required<V>(rule: Setting<V, false, false>): Setting<V>A setting with no default: a layer must give it, or the config does not open.
live
function live<V>(rule: Setting<V, false, true>): Setting<V, true>
function live<const V extends Primitive | readonly Primitive[]>(value: V): Setting<Widened<V>, true>A setting that may change while the program runs: its change is kept in
the store, goes over every layer until it is reset, and reaches every
process. live(100), live(int(100, { min: 0 })), live(required(String)).
int
function int(rules?: Bounds): Setting<number, false, false>
function int(fallback: number, rules?: Bounds): Setting<number>A whole number in its bounds: int(8080, { min: 1, max: 65535 }); int({ min: 1 }) goes in required.
oneOf
function oneOf<const O extends readonly [string, ...string[]]>(values: O): Setting<O[number], false, false>
function oneOf<const T extends string, const O extends readonly string[]>(fallback: T, others: O): Setting<T | O[number]>One of a set of texts, its default first: oneOf('info', ['debug', 'warn', 'error'])
reads as 'info' | 'debug' | 'warn' | 'error'; oneOf(['eu', 'us']) goes in required.
duration
function duration(rules?: DurationBounds): Setting<DurationText, false, false>
function duration(fallback: DurationText, rules?: DurationBounds): Setting<DurationText>A duration, read as one is written: duration('30s'), duration({ max: '1h' }) in required.
list
function list<T extends Token>(item: T, options?: ListOptions<Of<T>>): Setting<readonly Of<T>[]>
function list<V>(item: Setting<V, false, boolean>, options?: ListOptions<V>): Setting<readonly V[]>
function list<G extends object>(item: G, options?: ListOptions<Value<G>>): Setting<readonly Value<G>[]>A list: of String, Number or Boolean, of a rule, or of groups, each
item checked; its min and max count its items. A list written as a
value, ['localhost'], needs no list.
file
function file(path: string, options?: FileOptions): FileLayerA file a config reads: TOML, YAML or JSON by its extension, a relative path the program's.
env
function env(prefix: string, options?: EnvOptions): EnvLayerThe environment a config reads: env('APP') reads APP_ and each setting's
path in upper snake case, APP_LIMITS_RPS for limits.rps.
Config
class Config<D> {
readonly name: string
}A program's settings as one typed value, read from memory: open one with
store.config(name, [declaration, ...layers]).
Config.open
static open<D>(link: Link, name: string, layers: readonly unknown[], options: ConfigOptions<Value<D>>): Promise<Config<D>>Opens a config from its list: the declaration first, then its layers in order.
Config.value
get value(): Value<D>The settings as they are now: a read of memory, so read it where it is used.
Config.version
get version(): numberThe version of the changes the value holds, which ifVersion takes.
Config.update
update(changes: Changes<D>, options?: UpdateOptions): Promise<void>Changes live settings: the ones changes names are kept in the store, go
over every layer until they are reset, and reach every handle of the
config. The value they make passes validate first; all are kept or none.
Config.reset
reset(path?: string): Promise<void>Drops the change kept of the setting or the group at path, or of every setting.
Config.watch
watch(watcher: (next: Value<D>, previous: Value<D> | undefined) => void): () => voidCalls watcher with the settings now, then with each change and the value
before it, made in this process or another. It returns the call that stops it.
Config.explain
explain(): ExplainedEvery setting with its value, the layer that gave it and what it went over.
Config.stop
stop(): Promise<void>Stops following the config: the store closes. It resolves once the stream that follows it is cancelled, so that the store's connection ends after its CANCEL: a stream the server still ran would keep a private child, or a sidecar's connection, draining for ten seconds.