Find and load configuration from a package.json property, rc file, TypeScript module, and more!
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Cosmiconfig provides extensive configuration options to customize search behavior, file loading, and result transformation.
Options shared between async and sync APIs:
interface CommonOptions {
/** Package.json property name or path array to search for configuration */
packageProp?: string | Array<string>;
/** Array of places to search for configuration files */
searchPlaces?: Array<string>;
/** Skip empty configuration files during search */
ignoreEmptySearchPlaces?: boolean;
/** Directory to stop searching (defaults to os.homedir()) */
stopDir?: string;
/** Enable or disable caching of results */
cache?: boolean;
}Options for async API extending CommonOptions:
interface Options extends CommonOptions {
/** Custom async loaders for different file extensions */
loaders?: Loaders;
/** Transform function to modify results before returning */
transform?: Transform;
}Options for sync API extending CommonOptions:
interface OptionsSync extends CommonOptions {
/** Custom sync loaders for different file extensions */
loaders?: LoadersSync;
/** Transform function to modify results before returning (sync) */
transform?: TransformSync;
}Specifies which property in package.json to use for configuration.
packageProp?: string | Array<string>;Usage Examples:
import { cosmiconfig } from "cosmiconfig";
// Look for config in package.json under "babel" property
const explorer = cosmiconfig("babel", {
packageProp: "babel"
});
// Look for nested property using array path
const nestedExplorer = cosmiconfig("myapp", {
packageProp: ["config", "myapp"]
});
// This would find configuration in:
// {
// "config": {
// "myapp": {
// "setting": "value"
// }
// }
// }Array of places to search for configuration files.
searchPlaces?: Array<string>;Default Search Places:
For a module named "myapp", the default search places are:
package.json (using packageProp).myapprc.myapprc.json.myapprc.yaml.myapprc.yml.myapprc.js.myapprc.ts.myapprc.mjs.myapprc.cjsmyapp.config.jsmyapp.config.tsmyapp.config.mjsmyapp.config.cjsUsage Examples:
// Custom search places
const explorer = cosmiconfig("myapp", {
searchPlaces: [
"package.json",
".myapprc",
".myapp.json",
"myapp.config.js",
".config/myapp.json"
]
});
// Search only in specific config files
const configOnlyExplorer = cosmiconfig("tool", {
searchPlaces: [
"tool.config.js",
"tool.config.json"
]
});Skip empty configuration files during search.
ignoreEmptySearchPlaces?: boolean;Usage Examples:
// Skip empty config files (default: false)
const explorer = cosmiconfig("myapp", {
ignoreEmptySearchPlaces: true
});
// This will skip files that are empty or contain only whitespace
// and continue searching for non-empty configurationDirectory where searching should stop.
stopDir?: string;Usage Examples:
import path from "path";
// Stop searching at a specific directory
const explorer = cosmiconfig("myapp", {
stopDir: path.resolve("/Users/username/projects")
});
// Stop at project root (common pattern)
const projectExplorer = cosmiconfig("myapp", {
stopDir: path.resolve(process.cwd(), "..")
});Enable or disable caching of results.
cache?: boolean;Usage Examples:
// Disable caching (default: true)
const noCacheExplorer = cosmiconfig("myapp", {
cache: false
});
// Useful during development or testing when config files change frequently
const devExplorer = cosmiconfig("myapp", {
cache: process.env.NODE_ENV !== "development"
});Transform functions allow you to modify configuration results before they are returned.
Async transform function:
type Transform = (CosmiconfigResult: CosmiconfigResult) => Promise<CosmiconfigResult> | CosmiconfigResult;Sync transform function:
type TransformSync = (CosmiconfigResult: CosmiconfigResult) => CosmiconfigResult;Transform Examples:
import { cosmiconfig } from "cosmiconfig";
// Add metadata to configuration
const addMetadataTransform = (result) => {
if (!result) return result;
return {
...result,
config: {
...result.config,
_metadata: {
loadedFrom: result.filepath,
loadedAt: new Date().toISOString()
}
}
};
};
// Validate configuration structure
const validateTransform = (result) => {
if (!result) return result;
if (!result.config.name) {
throw new Error(`Configuration must have a "name" property in ${result.filepath}`);
}
return result;
};
// Apply environment variable substitution
const envTransform = (result) => {
if (!result) return result;
const config = JSON.parse(
JSON.stringify(result.config).replace(
/\$\{(\w+)\}/g,
(_, envVar) => process.env[envVar] || ""
)
);
return { ...result, config };
};
// Use transforms
const explorer = cosmiconfig("myapp", {
transform: addMetadataTransform
});
// Chain multiple transforms
const chainedTransform = async (result) => {
result = await validateTransform(result);
result = await envTransform(result);
result = await addMetadataTransform(result);
return result;
};
const complexExplorer = cosmiconfig("myapp", {
transform: chainedTransform
});import { cosmiconfig } from "cosmiconfig";
import path from "path";
// Comprehensive configuration example
const explorer = cosmiconfig("mycomplex", {
// Search configuration
searchPlaces: [
"package.json",
".mycomplexrc",
".mycomplexrc.json",
".mycomplexrc.yaml",
".mycomplexrc.js",
"mycomplex.config.js",
".config/mycomplex.json"
],
// Package.json property
packageProp: ["tools", "mycomplex"],
// Search behavior
ignoreEmptySearchPlaces: true,
stopDir: path.resolve(process.cwd(), "../.."),
cache: process.env.NODE_ENV !== "test",
// Custom loaders
loaders: {
".json": (filepath, content) => JSON.parse(content),
".yaml": (filepath, content) => require("js-yaml").load(content),
".yml": (filepath, content) => require("js-yaml").load(content),
".js": async (filepath) => {
const module = await import(filepath);
return module.default || module;
},
noExt: (filepath, content) => require("js-yaml").load(content)
},
// Transform function
transform: async (result) => {
if (!result) return result;
// Validate required properties
if (!result.config.name) {
throw new Error(`Configuration must have a "name" property`);
}
// Add computed properties
return {
...result,
config: {
...result.config,
_computed: {
configDir: path.dirname(result.filepath),
isDefaultConfig: result.filepath.includes("package.json")
}
}
};
}
});Configuration options can affect error handling behavior:
// Graceful handling of missing configurations
const explorer = cosmiconfig("optional-tool", {
searchPlaces: ["optional-tool.config.js"],
transform: (result) => {
// Provide defaults if no configuration found
if (!result) {
return {
config: { enabled: false, defaults: true },
filepath: "defaults",
isEmpty: false
};
}
return result;
}
});
// Strict validation
const strictExplorer = cosmiconfig("strict-tool", {
transform: (result) => {
if (!result) {
throw new Error("Configuration is required for strict-tool");
}
const required = ["name", "version", "settings"];
const missing = required.filter(key => !(key in result.config));
if (missing.length > 0) {
throw new Error(
`Missing required configuration properties: ${missing.join(", ")} in ${result.filepath}`
);
}
return result;
}
});