plumjs-config
v1.0.54
Published
A powerful Node.js configuration management library with YAML support and dynamic configuration loading
Maintainers
Readme
plumjs-config
一个强大的 Node.js 配置管理库,支持 YAML、动态配置加载和 Nacos 集成,具有完整的 TypeScript 类型安全支持。
🚀 核心特性
- � 多源配置支持: YAML 文件、JSON 文件、环境变量、Nacos 远程配置
- 🎯 类型安全: 自动从 YAML 配置生成 TypeScript 类型定义
- ⚡ CLI 工具: 一键生成外部项目的类型安全配置访问
- 🔄 动态配置更新: 支持运行时配置热更新和事件通知
- 🔗 变量插值: 配置值支持变量替换和表达式计算
- 📁 灵活文件格式: 支持 YAML、JSON 配置文件
- 🧪 测试友好: 易于在测试环境中模拟和替换配置
- 📖 完整文档: 详细的 API 文档和使用示例
📦 安装
npm install plumjs-config
# 或者使用 pnpm
pnpm install plumjs-config🎯 快速开始
基础用法
import { createConfig, getConfig } from 'plumjs-config';
// 初始化配置
await createConfig({
configDir: './config',
enableEnvironmentVariables: true
});
// 访问配置值
const appName = getConfig('app.name', 'default-app');
const dbHost = getConfig('database.host', 'localhost');
const dbPort = getConfig('database.port', 5432);
console.log(`启动应用 ${appName},数据库: ${dbHost}:${dbPort}`);类型安全的配置访问
import { createConfig, getConfig, plumjsConfigTypes } from 'plumjs-config';
// 初始化配置(会自动生成类型)
await createConfig({
configDir: './config'
});
// 使用生成的类型进行类型安全访问
const appConfig = getConfig(plumjsConfigTypes.app.name); // 自动类型推断
const dbConfig = getConfig(plumjsConfigTypes.database.host); // 完整的 IntelliSense 支持🛠️ CLI 工具
plumjs-config 提供了强大的 CLI 工具来生成外部项目的类型定义。
生成类型定义
# 为指定配置目录生成类型定义
npx plumjs-config types --config ./config
# 或者在已安装的项目中
plumjs-config types -c ./my-config-directory配置文件结构
创建配置文件夹,例如 ./config/:
config/
├── app.yml # 应用基本配置
├── database.yml # 数据库配置
├── server.yml # 服务器配置
└── cache.yml # 缓存配置app.yml 示例:
name: my-awesome-app
version: 1.0.0
environment: development
debug: truedatabase.yml 示例:
host: localhost
port: 5432
username: ${DB_USER:admin}
password: ${DB_PASSWORD:secret}
database: myapp
pool:
min: 2
max: 10📚 API 参考
核心函数
createConfig(options)
初始化配置管理器。
interface ConfigOptions {
configDir: string; // 配置文件目录
enableEnvironmentVariables?: boolean; // 是否启用环境变量
nacosConfig?: NacosConfig; // Nacos 配置(可选)
}
await createConfig({
configDir: './config',
enableEnvironmentVariables: true
});getConfig(path, defaultValue?)
获取配置值,支持点分隔路径。
// 基础用法
const value = getConfig('database.host');
const valueWithDefault = getConfig('database.port', 3306);
// 类型安全用法
const typedValue = getConfig(plumjsConfigTypes.app.name);getAllConfig()
获取完整的配置对象。
const allConfig = getAllConfig();
console.log(allConfig);reloadConfig()
重新加载配置。
await reloadConfig();类型安全访问
使用 plumjsConfigTypes 对象进行类型安全的配置访问:
import { plumjsConfigTypes, getConfig } from 'plumjs-config';
// 自动补全和类型检查
const appName = getConfig(plumjsConfigTypes.app.name);
const dbHost = getConfig(plumjsConfigTypes.database.host);
const serverPort = getConfig(plumjsConfigTypes.server.port);🔧 高级用法
环境变量插值
配置文件支持环境变量插值:
# database.yml
host: ${DB_HOST:localhost}
port: ${DB_PORT:5432}
username: ${DB_USER:admin}
password: ${DB_PASSWORD}Nacos 集成
await createConfig({
configDir: './config',
nacosConfig: {
serverAddr: 'localhost:8848',
namespace: 'development',
shareConfigs: [
{
dataId: 'app-config',
group: 'DEFAULT_GROUP',
refresh: true
}
]
}
});配置变更监听
import { onConfigChange } from 'plumjs-config';
onConfigChange(() => {
console.log('配置已更新!');
// 重新获取配置或执行其他操作
});📦 包发布与类型安全
🔄 自动类型重置
为了确保发布的包具有最大的兼容性,我们实现了自动类型重置机制:
⚡ 自动重置流程
发布前自动重置:
npm run prepublishOnly # 自动执行 reset-types ./scripts/publish-package.sh config patch # 发布脚本也会重置类型手动重置:
npm run reset-types # 重置为通用 any 类型
🎯 解决的问题
- ❌ 问题:如果包含项目特定的生成类型,其他用户安装后会遇到类型错误
- ✅ 解决:发布前自动重置为通用
any类型,确保兼容性
📋 类型管理工作流
# 开发阶段 - 生成具体类型
npm run generate-types /path/to/your/config
# 发布阶段 - 自动重置为通用类型
npm run prepublishOnly # 或者
./scripts/publish-package.sh config patch
# 发布后的包 - 包含通用 any 类型,用户可以:
# 1. 直接使用(any 类型)
# 2. 生成自己的具体类型🔧 技术实现
- 重置脚本:
scripts/reset-types.js - 构建集成:
prepublishOnly钩子 - 发布集成:
publish-package.sh脚本 - 默认类型:所有配置返回
any类型
这确保了:
- 📦 发布的包具有最大兼容性
- 🔧 用户可以选择是否生成具体类型
- 🚀 零配置即可使用
1. 配置文件组织
config/
├── app.yml # 应用配置
├── database.yml # 数据库配置
├── server.yml # 服务器配置
├── cache.yml # 缓存配置
├── logging.yml # 日志配置
└── security.yml # 安全配置2. 环境特定配置
# app.yml
name: my-app
environment: ${NODE_ENV:development}
debug: ${DEBUG:false}3. 类型安全的配置访问
// 推荐:使用生成的类型
const config = getConfig(plumjsConfigTypes.database.host);
// 避免:硬编码字符串
const config = getConfig('database.host');🧪 测试
import { createConfig, getConfig } from 'plumjs-config';
describe('配置测试', () => {
beforeEach(async () => {
await createConfig({
configDir: './test-config'
});
});
it('应该加载配置', () => {
const appName = getConfig('app.name');
expect(appName).toBe('test-app');
});
});📋 配置选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| configDir | string | - | 配置文件目录路径 |
| enableEnvironmentVariables | boolean | false | 是否启用环境变量加载 |
| nacosConfig | NacosConfig | - | Nacos 配置选项 |
🤝 贡献
欢迎贡献代码!请查看 贡献指南 了解更多信息。
开发设置
# 克隆仓库
git clone https://github.com/yourusername/plumjs.git
cd plumjs
# 安装依赖
pnpm install
# 构建项目
pnpm build --filter plumjs-config
# 运行测试
pnpm test --filter plumjs-config发布流程
项目包含自动化发布脚本,详见 发布指南。
# 1. 配置 NPM Token
echo "NPM_TOKEN=your_token_here" > .env
# 2. 发布新版本
npm run publish:patch # 补丁版本
npm run publish:minor # 次要版本
npm run publish:major # 主要版本📄 许可证
MIT License - 查看 LICENSE 文件了解详情。
🔗 相关链接
PlumJS Config - 让配置管理变得简单而安全 🚀 pnpm install
For Nacos support, also install:
```bash
npm install nacosQuick Start
Basic Usage
import { createConfig } from 'plumjs-config';
// Initialize configuration
const config = await createConfig({
configDir: './config',
enableEnvironmentVariables: true
});
// Access configuration values
const appName = config.getBootstrapConfig<string>('app.name', 'default-app');
const dbHost = config.getBootstrapConfig<string>('database.host', 'localhost');
const dbPort = config.getBootstrapConfig<number>('database.port', 5432);
console.log(`Starting ${appName} on ${dbHost}:${dbPort}`);Type-Safe Configuration
The package automatically generates TypeScript types from your YAML configuration files:
import { createConfig, TypedConfigManager } from 'plumjs-config';
// Create configuration manager
const configManager = await createConfig({
configDir: './config'
});
// Create type-safe wrapper
const typedConfig = new TypedConfigManager(configManager);
// Get strongly-typed configuration
const appConfig = typedConfig.getAppConfig(); // Full IntelliSense support
if (appConfig) {
console.log(`App: ${appConfig.name} v${appConfig.version}`);
console.log(`Environment: ${appConfig.environment}`); // 'development' | 'staging' | 'production' | 'test'
console.log(`Debug mode: ${appConfig.debug}`);
}
// Get database configuration with full type safety
const dbConfig = typedConfig.getDatabaseConfig();
if (dbConfig) {
console.log(`DB: ${dbConfig.host}:${dbConfig.port}/${dbConfig.database}`);
console.log(`Pool: ${dbConfig.pool.min}-${dbConfig.pool.max} connections`);
}
// Generic type-safe access
const timeout = typedConfig.getBootstrapConfig<number>('server.timeout', 5000);
const features = typedConfig.getBootstrapConfig<{enableAuth: boolean}>('features');Generating Types
Types are automatically generated when you build the package. You can also generate them manually:
npm run generate-typesThis scans your YAML configuration files and creates TypeScript interfaces in src/generated-types.ts.
CLI Type Generation (External Projects)
For external projects using plumjs-config, you can generate type-safe configuration access:
# Install plumjs-config in your project
npm install plumjs-config
# Create your configuration files
mkdir config
echo "
app:
name: 'my-app'
version: '1.0.0'
environment: 'production'
database:
host: 'localhost'
port: 5432
" > config/app.yml
# Generate types for your configuration
npx plumjs-config types
# Now use type-safe configuration in your codeimport { initConfig, getConfig } from 'plumjs-config';
await initConfig('./config');
// Type-safe configuration access with full IntelliSense
const appConfig = getConfig('app'); // Type: AppConfig | undefined
const dbConfig = getConfig('database'); // Type: DatabaseConfig | undefined
if (appConfig) {
console.log(`${appConfig.name} v${appConfig.version}`);
console.log(`Environment: ${appConfig.environment}`); // 'development' | 'staging' | 'production'
}The CLI tool automatically:
- 📁 Scans your configuration directory
- 🔍 Analyzes YAML structure and infers types
- 📝 Generates TypeScript interfaces
- 🔧 Updates the package's type definitions in node_modules
- ⚡ Provides instant type safety and IntelliSense
See CLI Usage Guide for detailed instructions.
Configuration Files
Create YAML configuration files in your config directory:
config/app.yml
app:
name: "my-application"
version: "1.0.0"
environment: "development"
database:
host: "localhost"
port: 5432
database: "myapp"
server:
host: "${database.host}"
port: 3000
url: "http://${server.host}:${server.port}"Environment Variables
Environment variables are automatically loaded and converted from snake_case to dot notation:
export APP_NAME="production-app"
export DATABASE_HOST="prod-db.example.com"
export DATABASE_PORT="5432"Access them using:
const appName = config.getDefaultConfig('app.name'); // "production-app"
const dbHost = config.getDefaultConfig('database.host'); // "prod-db.example.com"API Reference
ConfigManager
The main class for configuration management.
Methods
createConfig(options?: ConfigLoaderOptions): Promise<ConfigManager>
Create and initialize a new configuration manager.
const config = await createConfig({
configDir: './config',
enableEnvironmentVariables: true,
enableNacos: false,
filePatterns: ['**/*.yml', '**/*.yaml']
});getBootstrapConfig<T>(path: string, defaultValue?: T): T
Get configuration from the bootstrap namespace (loaded from files).
getDefaultConfig<T>(path: string, defaultValue?: T): T
Get configuration from the default namespace (environment variables).
getCommonConfig<T>(path: string, defaultValue?: T): T
Get configuration from the common namespace.
getDynamicConfig<T>(path: string, defaultValue?: T): T
Get configuration from the dynamic namespace (runtime updates).
setConfig(namespace: ConfigNamespace, data: ConfigData, source?: ConfigSource): void
Set configuration for a specific namespace.
onConfigChange(listener: ConfigChangeListener): void
Listen for configuration changes.
config.onConfigChange((event) => {
console.log(`Configuration changed in ${event.namespace}`);
console.log('New value:', event.newValue);
});Configuration Namespaces
- BOOTSTRAP: Configuration loaded from files at startup
- DEFAULT: Configuration from environment variables
- COMMON: Shared configuration (often from Nacos)
- DYNAMIC: Runtime configuration updates
Variable Interpolation
Variables can be referenced using ${path.to.variable} syntax:
database:
host: "localhost"
port: 5432
server:
host: "${database.host}"
url: "http://${server.host}:3000"Advanced Usage
Type-Safe Configuration
Define interfaces for your configuration:
interface AppConfig {
name: string;
version: string;
environment: 'development' | 'staging' | 'production';
}
interface DatabaseConfig {
host: string;
port: number;
database: string;
ssl: boolean;
}
const appConfig = config.getBootstrapConfig<AppConfig>('app');
const dbConfig = config.getBootstrapConfig<DatabaseConfig>('database');Nacos Integration
const config = new ConfigManager({
enableNacos: true,
nacosConfig: {
serverAddr: 'localhost:8848',
namespace: 'public',
username: 'nacos',
password: 'nacos',
shareConfig: [
{
dataId: 'app-config.yaml',
group: 'DEFAULT_GROUP',
nameSpace: ConfigNamespace.COMMON,
refresh: true // Enable automatic refresh
}
]
}
});
await config.initialize();Configuration Validation
const requiredFields = [
'app.name',
'app.version',
'database.host',
'database.port'
];
const missingFields = requiredFields.filter(field =>
config.getBootstrapConfig(field) === undefined
);
if (missingFields.length > 0) {
throw new Error(`Missing required configuration: ${missingFields.join(', ')}`);
}Configuration Precedence
Configuration values are resolved in the following order (highest to lowest priority):
- Dynamic Configuration (runtime updates)
- Bootstrap Configuration (files)
- Environment Variables (default namespace)
- Default Values (provided in code)
Examples
See the examples directory for complete usage examples:
- Basic Usage - Simple configuration loading and access
- Nacos Integration - Using Nacos for distributed configuration
Testing
Run the test suite:
npm testRun tests with coverage:
npm run test:coverageConfiguration Options
ConfigLoaderOptions
interface ConfigLoaderOptions {
configDir?: string; // Directory containing config files
enableNacos?: boolean; // Enable Nacos integration
nacosConfig?: NacosConfig; // Nacos configuration
enableEnvironmentVariables?: boolean; // Load environment variables
filePatterns?: string[]; // File patterns to match
}NacosConfig
interface NacosConfig {
serverAddr: string; // Nacos server address
namespace?: string; // Nacos namespace
username?: string; // Authentication username
password?: string; // Authentication password
shareConfig?: Array<{
dataId: string; // Configuration data ID
group: string; // Configuration group
nameSpace: ConfigNamespace; // Target namespace
refresh?: boolean; // Enable auto-refresh
}>;
}Best Practices
- Use Type-Safe Configuration: Define interfaces for your configuration structures
- Validate Required Fields: Check for required configuration at startup
- Use Environment-Specific Files: Organize configuration by environment
- Monitor Configuration Changes: Use event listeners for configuration updates
- Secure Sensitive Data: Use environment variables for secrets and passwords
- Use Variable Interpolation: Reduce duplication with variable references
- Test Configuration Loading: Include configuration in your test suite
Error Handling
The library provides detailed error messages for common issues:
- Missing configuration files
- Invalid YAML syntax
- Circular variable references
- Nacos connection failures
try {
const config = await createConfig({ configDir: './config' });
await config.initialize();
} catch (error) {
console.error('Configuration error:', error.message);
process.exit(1);
}Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
License
MIT License - see LICENSE file for details.
