### Load Configuration Source: https://github.com/unjs/c12/blob/main/README.md Load the configuration using `loadConfig`. This example shows how to get just the config object, and a more detailed version that also retrieves the config file path and extended layers. ```js // Get loaded config const { config } = await loadConfig({}); ``` ```js // Get resolved config and extended layers const { config, configFile, layers } = await loadConfig({}); ``` -------------------------------- ### Interactive Configuration Setup Source: https://github.com/unjs/c12/blob/main/_autodocs/advanced-usage-patterns.md Use `updateConfig` to programmatically create or update configuration files through an interactive command-line prompt. This is useful for initial setup or guided configuration changes. ```typescript import { updateConfig } from "c12/update"; import * as readline from "readline"; const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); function prompt(question: string): Promise { return new Promise(resolve => { rl.question(question, resolve); }); } async function interactiveSetup() { const port = await prompt("Server port (default 3000): "); const host = await prompt("Server host (default localhost): "); const debug = await prompt("Enable debug mode? (y/n): "); const { configFile, created } = await updateConfig({ cwd: ".", configFile: "config", createExtension: ".ts", onCreate: ({ configFile }) => { console.log(`Creating config at ${configFile}`); return true; }, onUpdate: (config) => { config.port = parseInt(port) || 3000; config.host = host || "localhost"; config.debug = debug.toLowerCase() === "y"; }, }); rl.close(); console.log(`Config ${created ? "created" : "updated"} at ${configFile}`); } await interactiveSetup(); ``` -------------------------------- ### Minimal Config Loading Source: https://github.com/unjs/c12/blob/main/_autodocs/README.md Load configuration with default settings. This is the most basic way to get started. ```typescript const { config } = await loadConfig(); ``` -------------------------------- ### File Manifest Example Source: https://github.com/unjs/c12/blob/main/_autodocs/README.md This is a file manifest showing the structure of the c12 documentation files. ```bash output/ ├── README.md (this file) ├── INDEX.md (navigation guide) ├── overview.md (architecture & concepts) ├── quick-reference.md (fast lookup) ├── api-reference-loadConfig.md (load function) ├── api-reference-watchConfig.md (watch function) ├── api-reference-dotenv.md (dotenv functions) ├── api-reference-updateConfig.md (update function) ├── api-reference-createDefineConfig.md (type-safe helper) ├── types.md (all type definitions) ├── configuration.md (all options) ├── exports-and-constants.md (public API) ├── errors.md (error reference) ├── advanced-usage-patterns.md (complex scenarios) └── loading-flow-and-internals.md (implementation details) ``` -------------------------------- ### Setup .env File Loading Source: https://github.com/unjs/c12/blob/main/_autodocs/README.md Use `setupDotenv` to load environment variables from a specified `.env` file. This is useful for managing environment-specific settings. ```typescript import { setupDotenv } from "c12"; await setupDotenv({ fileName: ".env" }); ``` -------------------------------- ### Usage Example: SUPPORTED_EXTENSIONS Source: https://github.com/unjs/c12/blob/main/_autodocs/exports-and-constants.md Demonstrates how to import and use the SUPPORTED_EXTENSIONS constant to log the supported file types or iterate through them. ```typescript import { SUPPORTED_EXTENSIONS } from "c12"; console.log(SUPPORTED_EXTENSIONS); // [" .js", ".ts", ".mjs", ".cjs", ".mts", ".cts", ".json", ".jsonc", ".json5", ".yaml", ".yml", ".toml"] for (const ext of SUPPORTED_EXTENSIONS) { console.log(`Checking for config${ext}`); } ``` -------------------------------- ### Install chokidar for watchConfig Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md Install the chokidar dependency if it's missing when using the watchConfig function. ```bash npm install chokidar ``` -------------------------------- ### Basic .env File Example Source: https://github.com/unjs/c12/blob/main/_autodocs/quick-reference.md Load environment variables from a .env file. This is useful for managing environment-specific settings like database credentials and API keys. ```env DATABASE_URL=postgresql://localhost/db API_KEY=secret123 ``` -------------------------------- ### Environment-Specific Configuration Example Source: https://github.com/unjs/c12/blob/main/_autodocs/quick-reference.md Demonstrates how to define environment-specific configurations using special keys like $development and $production. These settings override the default values when the environment name matches. ```typescript export default { logLevel: "info", $development: { logLevel: "debug" }, $production: { logLevel: "error" }, }; ``` -------------------------------- ### File References Example Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-dotenv.md Shows how variables ending with _FILE are expanded to the content of the specified file when expandFileReferences is true. ```env DATABASE_PASSWORD_FILE="/run/secrets/db_password" # Becomes: # DATABASE_PASSWORD= ``` -------------------------------- ### Variable Interpolation Example Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-dotenv.md Illustrates how to use variable interpolation with ${VAR_NAME} or $VAR_NAME syntax in .env files when interpolate is true. ```env BASE_DIR="/app" CONFIG_DIR="${BASE_DIR}/config" DATA_DIR="${BASE_DIR}/data" ``` -------------------------------- ### Update Config with User Confirmation Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-updateConfig.md This example shows how to prompt the user for confirmation before creating a new configuration file. It utilizes Node.js's `readline` module for interactive input. ```typescript import { updateConfig } from "c12/update"; import * as readline from "node:readline"; const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const { configFile, created } = await updateConfig({ cwd: ".", configFile: "config", onCreate: ({ configFile }) => { return new Promise((resolve) => { rl.question(`Create config at ${configFile}? (y/n) `, (answer) => { rl.close(); resolve(answer.toLowerCase() === "y"); }); }); }, onUpdate: (config) => { config.initialized = true; config.timestamp = new Date().toISOString(); }, }); if (created) { console.log("New config created!"); } else { console.log("Config updated!"); } ``` -------------------------------- ### Load Configuration Source: https://github.com/unjs/c12/blob/main/_autodocs/overview.md Load configuration with common options like name, environment, dotenv, and package.json support. Ensure 'c12' is installed. ```typescript import { loadConfig } from "c12"; const { config } = await loadConfig({ name: "config", // Loads config.ts, .configrc, package.json envName: "production", // Apply $production overrides dotenv: true, // Load .env packageJson: true, // Load from package.json.config }); ``` -------------------------------- ### Setup File Watcher Source: https://github.com/unjs/c12/blob/main/_autodocs/loading-flow-and-internals.md Sets up a file system watcher using chokidar to monitor the determined list of configuration files. Ignores initial file system events and allows for custom chokidar options. ```typescript const _fswatcher = watch(watchingFiles, { ignoreInitial: true, ...options.chokidarOptions, }); ``` -------------------------------- ### Install chokidar Peer Dependency Source: https://github.com/unjs/c12/blob/main/README.md Install the `chokidar` peer dependency using nypm for configuration watching. ```sh # ✨ Auto-detect npx nypm install chokidar ``` -------------------------------- ### Install c12 Package Source: https://github.com/unjs/c12/blob/main/README.md Install the c12 package using npx and nypm. This command automatically detects and installs the package. ```sh # ✨ Auto-detect npx nypm install c12 ``` -------------------------------- ### Environment-Specific Configuration Example Source: https://github.com/unjs/c12/blob/main/_autodocs/configuration.md Shows how to define environment-specific configuration values using keys like $development, $production, and $env.name. These values are merged into the base configuration based on the current environment name. ```typescript export default { logLevel: "info", // Base config $development: { logLevel: "debug", // Applied if NODE_ENV=development }, $production: { logLevel: "error", // Applied if NODE_ENV=production }, $env: { staging: { logLevel: "warning", // Applied if envName="staging" } } } ``` -------------------------------- ### updateConfig: Creation Aborted Example Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md Shows how updateConfig handles an aborted configuration file creation when the onCreate callback returns false. ```typescript import { updateConfig } from "c12/update"; await updateConfig({ cwd: ".", configFile: "config", onCreate: ({ configFile }) => { // User chose not to create return false; }, }); ``` -------------------------------- ### Install giget Peer Dependency Source: https://github.com/unjs/c12/blob/main/README.md Install the giget peer dependency using nypm for auto-detection. ```sh # ✨ Auto-detect npx nypm install giget ``` -------------------------------- ### Install giget for Remote Source Errors Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md Provides commands to install the `giget` peer dependency, which is required for extending configurations from remote git sources. ```bash # Install the giget peer dependency npm install giget # or pnpm add giget # or yarn add giget ``` -------------------------------- ### Install dotenv for Dotenv Parsing Errors Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md Provides instructions to install the `dotenv` package, which is necessary for parsing `.env` files in older Node.js versions (prior to 20.6). ```bash # Install dotenv for older Node.js versions npm install dotenv ``` -------------------------------- ### Install Peer Dependencies Source: https://github.com/unjs/c12/blob/main/_autodocs/quick-reference.md Install necessary peer dependencies for specific C12 features like watchConfig(), remote extends, TS fallback loading, Node < 20.6 dotenv support, and updateConfig(). ```bash npm install chokidar # For watchConfig() npm install giget # For remote extends npm install jiti # For TS fallback loading npm install dotenv # For Node < 20.6 npm install magicast # For updateConfig() ``` -------------------------------- ### updateConfig: Unsupported Extension Example Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md Shows an attempt to update a configuration file with an unsupported extension, which will result in an error. ```typescript import { updateConfig } from "c12/update"; await updateConfig({ cwd: ".", configFile: "config.json", // Not supported }); // Throws with unsupported extension error ``` -------------------------------- ### Load .env and .env.local files Source: https://github.com/unjs/c12/blob/main/README.md Enables loading of multiple .env files that extend each other. The example shows how environment variables from .env.local override those from .env. ```ini # .env CONNECTION_POOL_MAX="10" DATABASE_URL="<...rds...>" ``` ```ini # .env.local DATABASE_URL="<...localhost...>" ``` ```javascript export default { connectionPoolMax: process.env.CONNECTION_POOL_MAX, databaseURL: process.env.DATABASE_URL, }; ``` ```typescript import { loadConfig } from "c12"; const config = await loadConfig({ dotenv: { fileName: [".env", ".env.local"], }, }); console.log(config.config.connectionPoolMax); // "10" console.log(config.config.databaseURL); // "<...localhost...>" ``` -------------------------------- ### Application State Update with C12 Source: https://github.com/unjs/c12/blob/main/_autodocs/advanced-usage-patterns.md Manage application state by reacting to configuration changes. This example shows how to watch configuration updates and reinitialize specific subsystems like databases or cache managers based on the modified configuration values. ```typescript import { watchConfig } from "c12"; interface AppState { config: any; database: any; cache: any; } const appState: AppState = { config: null, database: null, cache: null, }; const watcher = await watchConfig({ name: "config", onUpdate: async ({ newConfig, getDiff }) => { const diff = getDiff(); console.log("Config changed:"); diff.forEach(change => { console.log(` ${change.key}: ${JSON.stringify(change.oldValue)} → ${JSON.stringify(change.value)}`); }); // Update application state appState.config = newConfig.config; // Reinitialize affected subsystems if (diff.some(d => d.key.startsWith("database"))) { await reinitializeDatabase(newConfig.config.database); } if (diff.some(d => d.key.startsWith("cache"))) { appState.cache = new CacheManager(newConfig.config.cache); } }, }); ``` -------------------------------- ### Basic Configuration Watching Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-watchConfig.md Starts watching for configuration changes. Logs the files being watched and the initial configuration. Ensure to call `watcher.unwatch()` when done to clean up resources. ```typescript import { watchConfig } from "c12"; const watcher = await watchConfig({ name: "config", cwd: ".", }); console.log("Watching files:", watcher.watchingFiles); console.log("Initial config:", watcher.config); // Later, stop watching await watcher.unwatch(); ``` -------------------------------- ### Specific Error Handling for Configuration Loading Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md This TypeScript example demonstrates how to catch and handle specific errors that might occur during C12 configuration loading. It checks error messages to provide tailored feedback for missing files, syntax errors, or issues with remote extensions. ```typescript import { loadConfig } from "c12"; try { const { config } = await loadConfig({ configFile: "config.ts", configFileRequired: true, }); } catch (error) { const message = error.message || ""; if (message.includes("Required config")) { console.error("Config file is missing"); } else if (message.includes("Failed to load config file")) { console.error("Config file has syntax errors"); console.error("Cause:", error.cause); } else if (message.includes("giget")) { console.error("Remote extends require: npm install giget"); } else { console.error("Unknown config error:", error); } } ``` -------------------------------- ### Extend Private GitHub Repository with Dependencies Source: https://github.com/unjs/c12/blob/main/README.md Extend configuration from a private GitHub repository and install its dependencies. Requires a GitHub token for authentication. ```js // config.ts export default { extends: ["gh:user/repo", { auth: process.env.GITHUB_TOKEN, install: true }], }; ``` -------------------------------- ### Configuration Load with Extends Source: https://github.com/unjs/c12/blob/main/_autodocs/quick-reference.md Enable the 'extends' feature to load configurations from multiple files or remote presets. This allows for modular and reusable configuration setups. ```typescript // config.ts export default { extends: ["./base", "gh:user/preset"], myValue: "override", }; const { config, layers } = await loadConfig({ extend: true, // Enable extends }); ``` -------------------------------- ### Handling Unresolvable Extended Config (Non-Fatal) Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md This example shows a configuration that attempts to extend a non-existent config file. C12 logs a warning and proceeds to load the rest of the configuration without the missing layer. ```typescript export default { extends: ["./missing-config"], }; const { config } = await loadConfig({}); // Warning logged, config loads without the extended layer ``` -------------------------------- ### Watching Configuration with Error Handling Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md This TypeScript code shows how to use C12's `watchConfig` function. It includes a try-catch block for initial watcher setup and notes that the watcher itself does not throw errors on configuration updates, only logging warnings. ```typescript import { watchConfig } from "c12"; try { const watcher = await watchConfig({ onUpdate: ({ newConfig }) => { console.log("Config reloaded successfully"); }, }); console.log("Watching config files..."); // If reload fails, console warning appears but watcher continues // No thrown error from watcher } catch (error) { console.error("Failed to start watching:", error); } ``` -------------------------------- ### setupDotenv Source: https://github.com/unjs/c12/blob/main/_autodocs/exports-and-constants.md Loads environment variables from .env files directly into process.env. ```APIDOC ## setupDotenv ### Description Loads environment variables from `.env` files into `process.env`. ### Signature ```typescript export async function setupDotenv(options: DotenvOptions): Promise ``` ### See [setupDotenv documentation](./api-reference-dotenv.md) ``` -------------------------------- ### Search for Options Source: https://github.com/unjs/c12/blob/main/_autodocs/README.md Use your documentation viewer's search to find configuration options like envName, dotenv, and extend. ```markdown Options: `envName`, `dotenv`, `extend`, etc. ``` -------------------------------- ### Handle Remote Source Error (giget missing) Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md This example demonstrates the condition for a `Remote Source Error` when extending configurations from a git source without the `giget` peer dependency installed. ```typescript const { config } = await loadConfig({ // config.ts contains: extends: ["gh:user/repo"] // but giget is not installed }); ``` -------------------------------- ### Filter Out Keys Starting with '$' Source: https://github.com/unjs/c12/blob/main/_autodocs/loading-flow-and-internals.md If `omit$Keys` is true, this step removes all keys from the configuration that start with a '$' character. ```typescript if (options.omit$Keys) { for (const key in r.config) { if (key.startsWith("$")) { delete r.config[key]; } } } ``` -------------------------------- ### setupDotenv Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-dotenv.md Loads and merges environment variables from .env files into process.env. It supports custom options for file names, working directory, and interpolation. ```APIDOC ## setupDotenv ### Description Loads and merges environment variables from `.env` files into `process.env`. It supports custom options for file names, working directory, and interpolation. ### Function Signature ```typescript export async function setupDotenv( options: DotenvOptions ): Promise ``` ### Parameters #### `options` (`DotenvOptions`) - Required Options for loading .env files. - **cwd** (`string`) - Optional - Working directory for resolving relative file paths. Defaults to `process.cwd()`. - **fileName** (`string | string[]`) - Optional - File name(s) to load in order. Defaults to `".env"`. - **env** (`NodeJS.ProcessEnv`) - Optional - Environment object to update. Defaults to `process.env`. - **interpolate** (`boolean`) - Optional - Enable variable interpolation. Defaults to `true`. - **expandFileReferences** (`boolean`) - Optional - Resolve `_FILE` suffixed variables by reading files. Defaults to `false`. ### Return Type `Promise` Returns a promise resolving to the loaded environment object. ### Behavior `setupDotenv` loads variables and merges them into the specified `env` object (or `process.env` by default) with these rules: - Variables not already set in the environment are added from `.env` - Variables already in the environment are preserved unless they were previously loaded from `.env` files - Variables starting with `_` are skipped and never added to the environment - Multiple `.env` files are loaded in order with later files overriding earlier ones ### Examples ```typescript import { setupDotenv } from "c12"; // Load .env into process.env await setupDotenv({ cwd: ".", fileName: ".env", }); console.log(process.env.DATABASE_URL); ``` ```typescript import { setupDotenv } from "c12"; // Load with cascading files await setupDotenv({ cwd: ".", fileName: [".env", ".env.local"], interpolate: true, }); // process.env is now updated ``` ```typescript import { setupDotenv } from "c12"; // Load into custom environment object const customEnv = {}; await setupDotenv({ cwd: ".", fileName: ".env", env: customEnv, }); console.log(customEnv.API_KEY); ``` ``` -------------------------------- ### Create Configuration File if Needed Source: https://github.com/unjs/c12/blob/main/_autodocs/loading-flow-and-internals.md Handles the creation of a configuration file if it does not exist, using a default or custom template provided by the `onCreate` callback. ```typescript const createResult = await opts.onCreate?.({ configFile }) ?? true; if (!createResult) { throw new Error("Config file creation aborted."); } const content = typeof createResult === "string" ? createResult : `export default {} `; await mkdir(dirname(configFile), { recursive: true }); await writeFile(configFile, content, "utf8"); ``` -------------------------------- ### Initial Configuration Load Source: https://github.com/unjs/c12/blob/main/_autodocs/loading-flow-and-internals.md Loads the initial configuration using the provided options. This is the first step in the file watching flow. ```typescript let config = await loadConfig(options); ``` -------------------------------- ### Install magicast Peer Dependency Source: https://github.com/unjs/c12/blob/main/README.md Add `magicast` as a development dependency using nypm. This is required for updating configuration files. ```sh # ✨ Auto-detect npx nypm install -D magicast ``` -------------------------------- ### Load Configuration with Multiple Sources Source: https://github.com/unjs/c12/blob/main/_autodocs/configuration.md Demonstrates loading configuration by specifying various sources like defaults, defaultConfig, packageJson, RC files, main config file, and overrides. The final configuration is a merge of these sources based on their priority. ```typescript const { config } = await loadConfig({ name: "app", cwd: ".", defaults: { port: 3000 }, // Priority: 7 defaultConfig: { host: "localhost" }, // Priority: 5 packageJson: true, // Priority: 4 (app field in package.json) // RC files loaded // Priority: 3 // Main config file loaded // Priority: 2 overrides: { debug: true }, // Priority: 1 }); // Result merges all sources with listed priority // If config file has port: 8080, overrides default // Unless overrides specifies port: 9000, which wins ``` -------------------------------- ### updateConfig: Missing Default Export Example Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md Illustrates a scenario where updateConfig fails because the configuration file lacks a default export. ```typescript // config.ts - No default export export const appConfig = {}; // Calling updateConfig will fail await updateConfig({ cwd: ".", configFile: "config", }); ``` -------------------------------- ### Custom Merger Function for Configuration Loading Source: https://github.com/unjs/c12/blob/main/_autodocs/configuration.md Example of providing a custom merger function to `loadConfig` for alternative merging logic. ```typescript const { config } = await loadConfig({ merger: (overrides, main, rc, packageJson, defaultConfig) => { // Custom merge logic return { ...overrides, ...main, ...rc }; }, }); ``` -------------------------------- ### Import Specific Functions from C12 Source: https://github.com/unjs/c12/blob/main/_autodocs/exports-and-constants.md Demonstrates how to import specific functions like `loadConfig` and `watchConfig` from the main C12 entry point. ```typescript // Import specific functions import { loadConfig, watchConfig } from "c12"; ``` -------------------------------- ### Configuration with Metadata using createDefineConfig Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-createDefineConfig.md Include configuration metadata such as version, author, or description by defining a metadata type and passing it as the second type parameter to createDefineConfig. Use the $meta key to provide the metadata object. ```typescript import { createDefineConfig } from "c12"; interface AppConfig { apiUrl: string; timeout: number; } interface ConfigMeta { version: string; author: string; description?: string; } const defineConfig = createDefineConfig(); export default defineConfig({ apiUrl: "https://api.example.com", timeout: 30000, $meta: { version: "1.0.0", author: "team@example.com", description: "Production API configuration", }, }); ``` -------------------------------- ### User Configuration with Extends Source: https://github.com/unjs/c12/blob/main/README.md This is the main configuration file that extends from a local theme configuration. ```js // config.ts export default { colors: { primary: "user_primary", }, extends: ["./theme"], }; ``` -------------------------------- ### Create New Config File with Template Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-updateConfig.md This snippet demonstrates creating a new configuration file using a template provided in the `onCreate` callback. The `onUpdate` callback can also be used for further customization. ```typescript import { updateConfig } from "c12/update"; const { configFile, created } = await updateConfig({ cwd: ".", configFile: "config", createExtension: ".ts", onCreate: ({ configFile }) => { console.log(`Creating new config file at ${configFile}`); return ` export default { port: 3000, host: 'localhost', database: { url: 'sqlite://db.sqlite', } `; }, onUpdate: (config) => { // Config is empty on creation, but onUpdate still runs // to allow further customization }, }); ``` -------------------------------- ### Accessing Configuration Layers Source: https://github.com/unjs/c12/blob/main/README.md Demonstrates how to access individual configuration layers programmatically, useful for custom merging strategies. ```js [ { config: { /* theme config */ }, configFile: "/path/to/theme/config.ts", cwd: "/path/to/theme ", }, { config: { /* base config */ }, configFile: "/path/to/base/config.ts", cwd: "/path/to/base", }, { config: { /* dev config */ }, configFile: "/path/to/config.dev.ts", cwd: "/path/", }, ]; ``` -------------------------------- ### updateConfig: Magicast Parsing Error Example Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md Demonstrates a Magicast parsing error that occurs when a config file contains invalid JavaScript/TypeScript syntax. ```typescript // config.ts - Invalid syntax export default { key: 'unclosed string }; await updateConfig({ cwd: ".", configFile: "config", }); // Throws magicast parse error ``` -------------------------------- ### loadConfig with Options Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-loadConfig.md Shows how to use loadConfig with various options to customize the configuration loading process, including name, cwd, envName, dotenv, packageJson, defaults, and overrides. ```typescript import { loadConfig } from "c12"; const { config, configFile, layers } = await loadConfig({ name: "myapp", cwd: "./config", envName: "development", dotenv: { fileName: [".env", ".env.local"], interpolate: true, }, packageJson: ["myapp", "appConfig"], defaults: { logLevel: "info", port: 3000, }, overrides: { debug: process.env.DEBUG === "true", }, }); console.log("Config loaded from:", configFile); console.log("Layers:", layers.length); ``` -------------------------------- ### Configuration with Extends Source: https://github.com/unjs/c12/blob/main/_autodocs/quick-reference.md Loads configuration from a base file and overrides or adds properties. ```typescript // config.ts export default { extends: ["./base"], myKey: "myValue", }; ``` -------------------------------- ### loadConfig with Extended Configuration Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-loadConfig.md Demonstrates how to load configurations that extend from other configuration files or remote repositories using the 'extends' key. It also shows how to provide authentication for remote sources via 'giget'. ```typescript import { loadConfig } from "c12"; // config.ts might contain: // export default { // extends: ["./base-config", "gh:user/config-repo"], // colors: { primary: "blue" } // } const { config, layers } = await loadConfig({ name: "config", giget: { auth: process.env.GITHUB_TOKEN, }, }); // Layers includes all extended configs console.log(layers.map(l => l.configFile)); ``` -------------------------------- ### Custom Merger for Array Replacement Source: https://github.com/unjs/c12/blob/main/_autodocs/advanced-usage-patterns.md Replace the default deep merge behavior with a custom merger function. This example demonstrates replacing arrays instead of merging them deeply. ```typescript import { loadConfig } from "c12"; const { config } = await loadConfig({ name: "config", merger: (...sources) => { const result = {}; for (const source of sources) { if (!source) continue; for (const key in source) { if (Array.isArray(source[key])) { // Arrays are replaced, not merged result[key] = source[key]; } else if (typeof source[key] === "object" && source[key] !== null) { // Objects are deep merged result[key] = { ...result[key], ...source[key] }; } else { // Primitives are overridden result[key] = source[key]; } } } return result; }, }); ``` -------------------------------- ### Package JSON Exports Configuration Source: https://github.com/unjs/c12/blob/main/_autodocs/exports-and-constants.md Defines the entry points for the package. Use '.' for the main module and './update' for update utilities. ```json { "exports": { ".": "./dist/index.mjs", "./update": "./dist/update.mjs" } } ``` -------------------------------- ### watchConfig: Config Reload Warning Example Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md Demonstrates the behavior of watchConfig when a config file fails to reload. A warning is logged, but the watcher continues to run with the old configuration. ```typescript import { watchConfig } from "c12"; const watcher = await watchConfig({ onWatch: (event) => { console.log("File changed:", event.path); }, onUpdate: ({ newConfig }) => { // Only called if reload succeeds }, }); // If reload fails, warning is logged but watcher doesn't exit ``` -------------------------------- ### Development Commands Source: https://github.com/unjs/c12/blob/main/AGENTS.md Common CLI commands used for building, testing, and maintaining the project. ```bash pnpm build # Build dist/ pnpm test # Lint + test + type check pnpm vitest run test/loader.test.ts # Run specific test pnpm dev # Vitest watch mode pnpm lint:fix # Auto-fix lint + format ``` -------------------------------- ### Base Configuration Source: https://github.com/unjs/c12/blob/main/README.md The foundational configuration file defining default color values. ```js // base/config.ts export default { colors: { primary: "base_primary", text: "base_text", }, }; ``` -------------------------------- ### Variable Interpolation Example Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-dotenv.md Loads environment variables with variable interpolation enabled, allowing values to reference other variables defined in the .env file. Ensure `interpolate` is set to `true`. ```typescript import { loadDotenv } from "c12"; // Variable interpolation const env = await loadDotenv({ cwd: ".", fileName: ".env", interpolate: true, }); // If .env contains: // BASE_URL="https://api.example.com" // API_ENDPOINT="${BASE_URL}/v1" // Then env.API_ENDPOINT === "https://api.example.com/v1" ``` -------------------------------- ### Load Configuration with Dotenv Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-dotenv.md Demonstrates loading configuration using c12's loadConfig, enabling dotenv integration with custom file names and interpolation. ```typescript import { loadConfig } from "c12"; const { config } = await loadConfig({ name: "config", dotenv: { fileName: [".env", ".env.local"], interpolate: true, expandFileReferences: true, }, }); // process.env is now populated from .env files // and config is loaded with access to those variables ``` -------------------------------- ### Configuration Definition Without createDefineConfig (for comparison) Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-createDefineConfig.md Illustrates a configuration file without using createDefineConfig, highlighting the loss of type safety within the configuration file itself. This serves as a comparison to demonstrate the benefits of the helper function. ```typescript // config.ts - No type safety export default { port: 3000, // TypeScript won't catch this mistake: invalid_key: true, // ❌ No error }; ``` -------------------------------- ### Default Merge Algorithm (defu) Source: https://github.com/unjs/c12/blob/main/_autodocs/loading-flow-and-internals.md Demonstrates the usage of the `defu` function for merging configuration objects with right-to-left priority. Earlier sources override later ones. ```typescript const result = defu(overrides, main, rc, packageJson, defaultConfig); // Priority: overrides > main > rc > packageJson > defaultConfig ``` -------------------------------- ### Custom import function with jiti Source: https://github.com/unjs/c12/blob/main/README.md Demonstrates using a custom jiti instance for loading configuration files, providing more control over the import process. ```javascript import { createJiti } from "jiti"; const jiti = createJiti(import.meta.url, { /* jiti options */ }); const { config } = await loadConfig({ import: (id) => jiti.import(id), }); ``` -------------------------------- ### Configuration Loading with Fallback Mechanism Source: https://github.com/unjs/c12/blob/main/_autodocs/advanced-usage-patterns.md Implement resilient configuration loading by providing default values and a fallback mechanism. This ensures your application can start even if configuration files are missing or malformed, by returning to a safe default state. ```typescript import { loadConfig } from "c12"; async function loadConfigWithFallback() { const defaultConfig = { port: 3000, host: "localhost", debug: false, }; try { const { config } = await loadConfig({ name: "config", configFileRequired: false, defaults: defaultConfig, }); return config; } catch (error) { console.error("Failed to load config:", error); console.warn("Using default config"); return defaultConfig; } } const config = await loadConfigWithFallback(); ``` -------------------------------- ### Basic loadConfig Usage Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-loadConfig.md Demonstrates the minimal configuration required to load a configuration object using loadConfig. ```typescript import { loadConfig } from "c12"; // Minimal config load const { config } = await loadConfig({}); // Access the resolved configuration console.log(config); ``` -------------------------------- ### Selective Hot Module Replacement (HMR) Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-watchConfig.md Implements selective HMR by defining custom logic within `acceptHMR`. This example demonstrates skipping reloads if only nested configuration values change, focusing on top-level key modifications. ```typescript import { watchConfig } from "c12"; const watcher = await watchConfig({ name: "config", acceptHMR({ getDiff, newConfig }) { const diff = getDiff(); // Only reload if top-level keys changed // Skip if only nested values changed const topLevelChanges = diff.filter(d => !d.key.includes(".")); if (topLevelChanges.length === 0) { console.log("Skipping reload for nested changes"); return true; } return false; }, }); ``` -------------------------------- ### Load Basic Configuration Source: https://github.com/unjs/c12/blob/main/_autodocs/overview.md Loads configuration for a given application name, with support for environment variables via dotenv. ```typescript import { loadConfig } from "c12"; const { config } = await loadConfig({ name: "myapp", dotenv: true, }); console.log(config); ``` -------------------------------- ### Import Type-Safe Config Helper from C12 Source: https://github.com/unjs/c12/blob/main/_autodocs/exports-and-constants.md Demonstrates importing the `createDefineConfig` helper for creating type-safe configuration objects. ```typescript // Import type-safe config helper import { createDefineConfig } from "c12"; ``` -------------------------------- ### Search for Function Names Source: https://github.com/unjs/c12/blob/main/_autodocs/README.md Use your documentation viewer's search to find function names like loadConfig and watchConfig. ```markdown Function names: `loadConfig`, `watchConfig`, etc. ``` -------------------------------- ### Minimal Configuration Source: https://github.com/unjs/c12/blob/main/_autodocs/quick-reference.md A basic configuration file exporting an object with port and host properties. ```typescript // config.ts export default { port: 3000, host: "localhost", }; ``` -------------------------------- ### Import Dotenv Functions from C12 Source: https://github.com/unjs/c12/blob/main/_autodocs/exports-and-constants.md Illustrates importing functions related to dotenv configuration, like `loadDotenv` and `setupDotenv`. ```typescript // Import dotenv functions import { loadDotenv, setupDotenv } from "c12"; ``` -------------------------------- ### Import Supported Extensions from C12 Source: https://github.com/unjs/c12/blob/main/_autodocs/exports-and-constants.md Shows how to import the `SUPPORTED_EXTENSIONS` constant, which lists the file extensions C12 can process. ```typescript // Import supported extensions import { SUPPORTED_EXTENSIONS } from "c12"; ``` -------------------------------- ### Search for Concepts Source: https://github.com/unjs/c12/blob/main/_autodocs/README.md Use your documentation viewer's search to find core concepts like environment, extends, and merge. ```markdown Concepts: `environment`, `extends`, `merge`, etc. ``` -------------------------------- ### TypeScript Function Signature: setupDotenv Source: https://github.com/unjs/c12/blob/main/_autodocs/exports-and-constants.md Defines the signature for the setupDotenv function, which loads environment variables from .env files directly into process.env. ```typescript export async function setupDotenv(options: DotenvOptions): Promise ``` -------------------------------- ### Search for Types Source: https://github.com/unjs/c12/blob/main/_autodocs/README.md Use your documentation viewer's search to find type definitions like LoadConfigOptions and ResolvedConfig. ```markdown Types: `LoadConfigOptions`, `ResolvedConfig`, etc. ``` -------------------------------- ### Handle Different Extend Formats Source: https://github.com/unjs/c12/blob/main/_autodocs/loading-flow-and-internals.md Demonstrates the various formats supported for the `extends` key, including strings, arrays of strings, objects with source and options, and mixed arrays. ```typescript extends: "path" // String ``` ```typescript extends: ["path1", "path2"] // Array of strings ``` ```typescript extends: { // Object with source and options source: "path", options: { auth: "token" } } ``` ```typescript extends: ["path", { auth: "..." }] // Array [source, options] ``` -------------------------------- ### Extend Configuration from GitHub Repository Source: https://github.com/unjs/c12/blob/main/README.md Extend configuration from a GitHub repository by specifying the repository path. ```js // config.ts export default { extends: "gh:user/repo", }; ``` -------------------------------- ### Load Configuration with Metadata Source: https://github.com/unjs/c12/blob/main/_autodocs/quick-reference.md Retrieve configuration along with metadata such as the configuration file path and loaded layers. This is useful for debugging and understanding configuration sources. ```typescript const { config, configFile, layers } = await loadConfig(); ``` -------------------------------- ### Handle Unsupported Config File Extension Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-updateConfig.md Demonstrates how to catch an error when attempting to update a configuration file with an unsupported extension. Ensure the file extension is one of the supported types. ```typescript import { updateConfig } from "c12/update"; try { await updateConfig({ cwd: ".", configFile: "config.json", // Invalid extension }); } catch (error) { console.error("Update failed:", error.message); // "Unsupported config file extension: .json" } ``` -------------------------------- ### Load Configuration with Context Source: https://github.com/unjs/c12/blob/main/README.md Load configuration dynamically by providing a context object to `loadConfig`. This context can be used by configuration functions to determine values. ```ts // Usage import { loadConfig } from "c12"; const config = await loadConfig({ context: { dev: true }, }); ``` -------------------------------- ### Configuration Watching with Callbacks Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-watchConfig.md Enhances configuration watching with callbacks for file system events and configuration updates. The `acceptHMR` callback allows for conditional updates, while `onUpdate` provides detailed change information. ```typescript import { watchConfig } from "c12"; const watcher = await watchConfig({ name: "config", onWatch: (event) => { console.log(`[watcher] ${event.type}: ${event.path}`); }, acceptHMR({ getDiff, oldConfig, newConfig }) { const diff = getDiff(); if (diff.length === 0) { console.log("No actual changes detected!"); return true; // Skip full update } return false; // Proceed with full update }, onUpdate({ getDiff, oldConfig, newConfig }) { const diff = getDiff(); console.log("Config updated:"); diff.forEach((change) => { console.log(` ${change.key}: ${change.oldValue} → ${change.value}`); }); }, }); console.log("Watching config..."); ``` -------------------------------- ### C12 Main Imports Source: https://github.com/unjs/c12/blob/main/_autodocs/quick-reference.md Import core functions like `loadConfig` and `watchConfig` from the main C12 entry point. ```typescript // Main entry import { loadConfig, watchConfig, loadDotenv, setupDotenv, createDefineConfig, SUPPORTED_EXTENSIONS, } from "c12"; ``` -------------------------------- ### Import c12 Functions (ESM) Source: https://github.com/unjs/c12/blob/main/README.md Import the `loadConfig` and `watchConfig` functions using standard ESM import syntax. ```js // ESM import import { loadConfig, watchConfig } from "c12"; ``` -------------------------------- ### Update or Create Configuration File Source: https://github.com/unjs/c12/blob/main/README.md Use the `updateConfig` utility to modify existing configuration files or create new ones. The `onCreate` hook allows defining initial content, and `onUpdate` can modify existing configurations. ```js const { configFile, created } = await updateConfig({ cwd: ".", configFile: "foo.config", onCreate: ({ configFile }) => { // You can prompt user if wants to create a new config file and return false to cancel console.log(`Creating new config file in ${configFile}...`); return "export default { test: true }"; }, onUpdate: (config) => { // You can update the config contents just like an object config.test2 = false; }, }); console.log(`Config file ${created ? "created" : "updated"} in ${configFile}`); ``` -------------------------------- ### Import c12 Functions (Dynamic Import) Source: https://github.com/unjs/c12/blob/main/README.md Import the `loadConfig` and `watchConfig` functions using dynamic import, suitable for asynchronous module loading. ```js // or using dynamic import const { loadConfig, watchConfig } = await import("c12"); ``` -------------------------------- ### loadConfig with Environment-Specific Config Source: https://github.com/unjs/c12/blob/main/_autodocs/api-reference-loadConfig.md Illustrates loading configuration that varies based on the environment name provided to loadConfig. It uses environment-specific keys like $development, $production, and $env. ```typescript import { loadConfig } from "c12"; // config.ts // export default { // logLevel: "info", // $development: { logLevel: "debug" }, // $production: { logLevel: "error" }, // $env: { // staging: { logLevel: "warning" } // } // } const { config } = await loadConfig({ name: "config", envName: "production", // Uses $production }); console.log(config.logLevel); // "error" ``` -------------------------------- ### Load Configuration with Layers Source: https://github.com/unjs/c12/blob/main/_autodocs/overview.md Loads configuration and provides access to all resolved layers. Layers are ordered by merge priority. ```typescript const { config, layers } = await loadConfig({ name: "config", extend: true, }); // layers[0] = { // config: { /* extended config */ }, // configFile: "/path/to/extended/config.ts", // cwd: "/path/to/extended", // }, // layers[1] = { // config: { /* main config */ }, // configFile: "/path/to/config.ts", // cwd: "/path/to", // } ``` -------------------------------- ### Environment-Specific Configuration Source: https://github.com/unjs/c12/blob/main/README.md Define default and environment-specific configurations for settings like logLevel. c12 matches the environment name to apply overrides. ```js export default { // Default configuration logLevel: "info", // Environment overrides $test: { logLevel: "silent" }, $development: { logLevel: "warning" }, $production: { logLevel: "error" }, $env: { staging: { logLevel: "debug" }, }, }; ``` -------------------------------- ### updateConfig: Handling Unsupported Extension Source: https://github.com/unjs/c12/blob/main/_autodocs/errors.md Demonstrates how to catch and handle the 'Unsupported config file extension' error when using updateConfig. ```typescript import { updateConfig } from "c12/update"; try { await updateConfig({ cwd: ".", configFile: "config", }); } catch (error) { if (error.message.includes("Unsupported config file extension")) { console.error("Config format not supported"); } } ```