Simple config handling for your app or module
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Complete guide to setting up and configuring Conf instances with all available options for storage location, validation, encryption, and behavior customization.
Creates a new Conf instance with the specified configuration options.
/**
* Creates a new configuration store
* @param options - Configuration options for the store
*/
constructor(options?: Partial<Options<T>>): Conf<T>;Usage Examples:
import Conf from "conf";
// Basic configuration with project name
const config = new Conf({ projectName: "my-app" });
// With TypeScript typing
interface AppConfig {
username: string;
theme: "light" | "dark";
notifications: boolean;
}
const typedConfig = new Conf<AppConfig>({
projectName: "my-app",
defaults: {
theme: "light",
notifications: true
}
});Options that define the basic behavior and storage of the configuration.
interface CoreOptions<T> {
/**
* Required unless `cwd` is specified.
* Used to determine config file location following OS conventions.
*/
projectName?: string;
/**
* Name of the config file (without extension).
* Useful for multiple config files per project.
* @default "config"
*/
configName?: string;
/**
* Default values for config items.
* Overrides `default` values in schema.
*/
defaults?: Readonly<T>;
/**
* Custom config directory path.
* Overrides projectName-based location.
* You most likely don't need this.
*/
cwd?: string;
/**
* Config file extension.
* @default "json"
*/
fileExtension?: string;
/**
* Project directory suffix to avoid conflicts.
* @default "nodejs"
*/
projectSuffix?: string;
}Usage Examples:
// Multiple config files for different environments
const devConfig = new Conf({
projectName: "my-app",
configName: "development",
defaults: { debug: true }
});
const prodConfig = new Conf({
projectName: "my-app",
configName: "production",
defaults: { debug: false }
});
// Custom file extension for shareable configs
const userPrefs = new Conf({
projectName: "my-app",
configName: "preferences",
fileExtension: "prefs"
});Options for JSON Schema validation to ensure data integrity.
interface ValidationOptions<T> {
/**
* JSON Schema for validating config data.
* Define as object where each key is a property name
* and each value is a JSON schema for that property.
*/
schema?: Schema<T>;
/**
* Top-level schema properties excluding `properties` field.
*/
rootSchema?: Omit<JSONSchema, 'properties'>;
/**
* Options passed to AJV validator.
* allErrors and useDefaults are true by default.
*/
ajvOptions?: AjvOptions;
/**
* Clear config if reading causes SyntaxError.
* Good for unimportant data that may get corrupted.
* @default false
*/
clearInvalidConfig?: boolean;
}
type Schema<T> = {[Property in keyof T]: ValueSchema};
type ValueSchema = JSONSchema;Usage Examples:
interface UserConfig {
name: string;
age: number;
email: string;
preferences: {
theme: string;
notifications: boolean;
};
}
const config = new Conf<UserConfig>({
projectName: "user-app",
schema: {
name: {
type: "string",
minLength: 1,
default: "Anonymous"
},
age: {
type: "number",
minimum: 0,
maximum: 150
},
email: {
type: "string",
format: "email"
},
preferences: {
type: "object",
properties: {
theme: {
type: "string",
enum: ["light", "dark"],
default: "light"
},
notifications: {
type: "boolean",
default: true
}
}
}
},
rootSchema: {
additionalProperties: false
}
});
// This will throw a validation error
config.set("age", -5); // Error: Config schema violation: `age` should be >= 0Options for encryption, file permissions, and storage format customization.
interface SecurityOptions<T> {
/**
* Encryption key for config file obfuscation (not security).
* Helps deter users from manually editing config files.
*/
encryptionKey?: string | Uint8Array | NodeJS.TypedArray | DataView;
/**
* File permission mode for config file.
* @default 0o666
*/
configFileMode?: number;
/**
* Custom serialization function.
* @default value => JSON.stringify(value, null, '\t')
*/
serialize?: Serialize<T>;
/**
* Custom deserialization function.
* @default JSON.parse
*/
deserialize?: Deserialize<T>;
}
type Serialize<T> = (value: T) => string;
type Deserialize<T> = (text: string) => T;Usage Examples:
import yaml from "js-yaml";
// Encrypted config for obfuscation
const secretConfig = new Conf({
projectName: "secure-app",
encryptionKey: "my-secret-key-not-for-security"
});
// YAML format instead of JSON
const yamlConfig = new Conf({
projectName: "yaml-app",
fileExtension: "yaml",
serialize: yaml.dump,
deserialize: yaml.load
});
// Restrictive file permissions (user-only access)
const privateConfig = new Conf({
projectName: "private-app",
configFileMode: 0o600
});Options that control how the configuration store behaves.
interface BehaviorOptions {
/**
* Enable nested property access via dot notation.
* @default true
*/
accessPropertiesByDotNotation?: boolean;
/**
* Watch config file for external changes.
* Useful when multiple processes modify the same file.
* @default false
*/
watch?: boolean;
}Usage Examples:
// Disable dot notation - treat dots as literal key characters
const literalConfig = new Conf({
projectName: "literal-app",
accessPropertiesByDotNotation: false
});
literalConfig.set("foo.bar.baz", "value");
console.log(literalConfig.get("foo.bar.baz")); // => "value"
// Enable file watching for multi-process scenarios
const watchedConfig = new Conf({
projectName: "multi-process-app",
watch: true
});
watchedConfig.onDidAnyChange((newValue, oldValue) => {
console.log("Config changed externally:", { newValue, oldValue });
});Options for handling version-based configuration migrations.
interface MigrationOptions<T> {
/**
* Project version - required if using migrations.
* Used to determine which migrations to run.
*/
projectVersion?: string;
/**
* Migration handlers keyed by version or semver range.
* Each handler receives the store instance.
*/
migrations?: Migrations<T>;
/**
* Callback executed before each migration step.
* Useful for logging or preparing migration data.
*/
beforeEachMigration?: BeforeEachMigrationCallback<T>;
}
type Migrations<T> = Record<string, (store: Conf<T>) => void>;
type BeforeEachMigrationCallback<T> = (store: Conf<T>, context: BeforeEachMigrationContext) => void;
interface BeforeEachMigrationContext {
fromVersion: string;
toVersion: string;
finalVersion: string;
versions: string[];
}Usage Examples:
const migratingConfig = new Conf({
projectName: "evolving-app",
projectVersion: "2.1.0",
beforeEachMigration: (store, context) => {
console.log(`Migrating from ${context.fromVersion} to ${context.toVersion}`);
},
migrations: {
"1.0.0": (store) => {
// Migrate to v1.0.0 - add debug flag
store.set("debug", false);
},
"1.5.0": (store) => {
// Migrate to v1.5.0 - restructure settings
const oldTheme = store.get("theme");
store.delete("theme");
store.set("ui.theme", oldTheme || "light");
},
">=2.0.0": (store) => {
// Migrate to v2.x.x - upgrade settings format
store.set("version", 2);
store.set("migrated", true);
}
}
});interface Options<T extends Record<string, any>> {
// Core options
projectName?: string;
configName?: string;
defaults?: Readonly<T>;
cwd?: string;
fileExtension?: string;
projectSuffix?: string;
// Validation options
schema?: Schema<T>;
rootSchema?: Omit<JSONSchema, 'properties'>;
ajvOptions?: AjvOptions;
clearInvalidConfig?: boolean;
// Security options
encryptionKey?: string | Uint8Array | NodeJS.TypedArray | DataView;
configFileMode?: number;
serialize?: Serialize<T>;
deserialize?: Deserialize<T>;
// Behavior options
accessPropertiesByDotNotation?: boolean;
watch?: boolean;
// Migration options
projectVersion?: string;
migrations?: Migrations<T>;
beforeEachMigration?: BeforeEachMigrationCallback<T>;
}