雀巢JS CRUD 配置
具有全部CRUD能力的 NestJS 应用程序的数据库支持配置管理
目录
说明
NestJS CRUD Cfig是一个强大的配置管理模块,它革命化了NestJS应用程序如何处理配置数据. 与传统环境可变方法不同的是,这种库存储配置在一个拥有完整 CRUD 操作的数据库中,使它在跨越多个环境和服务的动态配置管理上变得完美.
该模块通过章节和数据条目提供分级组织,支持敏感值的可选AES-256-GCM加密,并包括用于配置管理的自动REST API端点. 由TypeScript-First设计并使用NestJS CRUD Automator用于自动API生成而来,它具有运行时动态实体创建的特点,命名为交易所有权,以及智能缓存.
无论是管理跨不同环境的API密钥,存储地物旗,还是维护需要不进行再调用而改变的应用程序设置,本模块为微服务架构,多租户应用程序,以及任何需要集中的,数据库支持的配置管理,以及实时更新的系统提供了稳健,安全和可扩展的解决方案.
* 特性
- QQ 数据库支持的配置存储 - 将配置储存在任何TypeORM支持的数据库中,以便持久和可扩展
- * 动态实体创建 - 实体在运行时有自定义的表格名称、字段长度和限制
- * 等级组织 - 利用章节和数据条目组织配置,以更好地构建和管理结构
- AES-256-GCM 加密支持 - 利用行业标准算法保护内置加密的敏感配置值
- * 多种环境支助 - 管理整个开发、中转和生产环境的配置
- * 完整的 CRUD 操作 - 完成创建、读取、更新、删除自动 REST API 端点的操作
- 自动 Swagger 文档 - 为所有配置终点生成 OpenAPI 文件
- QQ TypeScript 第一设计 - 有综合接口和类型定义的完整类型安全
- NestJS CRUD 自动化器集成 - 控制器和服务高级CRUD自动化
- 智能缓存 - 内置缓存支持,可配置 TTL 和缓存大小限制
- * 已命名交易所有权 - 每个自动化人拥有的工作单位使用一个精确的TypeORM管理器,包括联合迁移写作
- 高度定制 - 配置表格前缀、字段长度、验证规则和实体关系
- XQ 灵活控制器配置 - 自定义 API 路径、禁用端点或以无头模式运行
- 高级 CRUD 定制 - 全面控制航道、扫描文档和控制者行为
- 模块架构 - 为您的使用设置所需的启用/残疾特性
- 生产准备移民系统 - 应用程序启动期间初始化和管理配置状态
* 安装
这些文件描述了 CrudConfig 5 合同: Automator 5, NestJS 12, TypeORM 1, 仅ES模块. 使用5.x范围,它也接受5.0.0预放:
# npm
npm install @elsikora/nestjs-crud-config@^5.0.0-0
# yarn
yarn add @elsikora/nestjs-crud-config@^5.0.0-0
# pnpm
pnpm add @elsikora/nestjs-crud-config@^5.0.0-0
先决条件
节点.js ^22.13.0 || >=24.11.0。安装所需的同伴依赖:
npm install @elsikora/nestjs-crud-automator@^5.0.0-0 @nestjs/common@^12 @nestjs/core@^12 @nestjs/typeorm@^12 typeorm@^1
npm install @nestjs/passport@^12 @nestjs/platform-fastify@^12 @nestjs/swagger@^12 @nestjs/throttler class-transformer class-validator fastify lodash
包船仅作为ES模块. 通用JS应用程序保存 require("@elsikora/nestjs-crud-config"),该节点Js装入 require(esm)。导入软件包 .env 文件: 设置 NCC_LOG_LEVEL 在环境中,或负载 .env 在应用程序中,例如: ConfigModule.forRoot()。 。 。 .
自动化 5 兼容性
CrudConfig 5 需要一个 @elsikora/nestjs-crud-automator ^5.0.0。自动化器 4 和 4 以上不支持.
生成的路径运行自动化器 ApiAuthorizationGuard。当区域或数据控制器启用时,导入 Automator 全局 ApiAuthorizationModule 在根模块中一次, 如以下示例; 没有它, 应用程序启动时失败 Nest can't resolve dependencies of the ApiAuthorizationGuard无头模式不需要它.
生成的路由覆盖继续使用自动生成配置 :
DELETE: {
generation: {
isEnabled: false,
},
},
配置数据 CREATE 财务报告和审定财务报表 UPDATE 使用自动嵌入的请求关系加载。 内置的章节关系期望请求机构,如 { "section": { "id": "section-uuid" } }。 。 。 .
CrudConfig 通过创建每个生成的服务 createDynamicService() 财务报告和审定财务报表 @ApiService({ entity }),因此其所继承的同实体 CRUD 方法满足了自动生成-路由能力边界. 应用程序不需要包装或相容层.
迁移到 5.0
CrudConfig 5 移动到最新的主机和舰只作为ES模块. CrudConfig运行时间合同没有变化:
- 同位素移动到自动化器 5, NestJS 12, Swagger 12,
@nestjs/typeorm12和类型ORM 1;节点.js^22.13.0 || >=24.11.0· ; - 仅基于无害环境管理:
dist/esm, (中文(简体) ),dist/cjs编辑require导出条件已去, CommunityJS 应用程序装入软件包require(esm)· ; - 页:1
@nestjs/cache-manager依赖性移动到12,所以npm ci不再失败ERESOLVE(c) 监视12; - 包不再导入
dotenv/config: 从不装入.env,以及NCC_LOG_LEVEL来源于应用程序的环境; - 模块选项,
CrudConfigService,生成的路由,数据库计划和交易所有权不变.
见完整 5.0 移徙指南编辑 4.0 (韩语) 财务报告和审定财务报表 3.0 调用 旧的升级仍提供移徙指南.
数据库支持
此软件包与 TypeORM 支持的任何数据库工作 :
- 邮递SQL
- MySQL/马里亚DB
- SQLite (通过
better-sqlite3驱动程序; TypeORM 1 删除sqlite(中文(简体) ) - 微软 SQL 服务器
- 甲骨文
- 蒙戈DB
- 鸡尾酒
使用量
基本设置
// app.module.ts
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { ApiAuthorizationModule } from "@elsikora/nestjs-crud-automator";
import { CrudConfigModule, TOKEN_CONSTANT } from "@elsikora/nestjs-crud-config";
@Module({
imports: [
// Automator's generated routes run ApiAuthorizationGuard; import this global module once in the root module
ApiAuthorizationModule,
// First register CrudConfigModule to create dynamic entities
CrudConfigModule.register({
environment: "development",
shouldAutoCreateSections: true,
// Cache configuration
cacheOptions: {
isEnabled: true,
maxCacheItems: 1000,
maxCacheTTL: 3600000, // 1 hour in milliseconds
},
// Encryption configuration
encryptionOptions: {
isEnabled: true,
encryptionKey: process.env.CONFIG_ENCRYPTION_KEY, // 32+ character key
},
// Controller configuration (optional)
controllersOptions: {
section: {
isEnabled: true,
properties: {
path: "api/config/sections",
},
},
data: {
isEnabled: true,
properties: {
path: "api/config/data",
},
},
},
// Entity customization
entityOptions: {
tablePrefix: "app_",
timestampColumnType: "timestamptz", // PostgreSQL; defaults to Date, the timestamp type of the driver
configSection: {
tableName: "config_sections",
maxNameLength: 128,
maxDescriptionLength: 512,
},
configData: {
tableName: "config_data",
maxValueLength: 8192,
maxEnvironmentLength: 64,
maxNameLength: 128,
maxDescriptionLength: 512,
},
},
}),
// Then register TypeORM with dynamic entities using registerAsync
TypeOrmModule.forRootAsync({
imports: [CrudConfigModule],
inject: [TOKEN_CONSTANT.CONFIG_SECTION_ENTITY, TOKEN_CONSTANT.CONFIG_DATA_ENTITY],
useFactory: async (sectionEntity, dataEntity) => ({
type: "postgres",
host: "localhost",
port: 5432,
username: "postgres",
password: "postgres",
database: "config_db",
entities: [
// Your other entities
// UserEntity, ProductEntity, etc.
// Dynamic entities from CrudConfigModule
sectionEntity,
dataEntity,
],
synchronize: true,
}),
}),
],
})
export class AppModule {}
使用配置服务
// config.service.ts
import { Injectable } from "@nestjs/common";
import { CrudConfigService } from "@elsikora/nestjs-crud-config";
@Injectable()
export class MyConfigService {
constructor(private readonly configService: CrudConfigService) {}
async setupApplicationConfig() {
// Set a configuration value
await this.configService.set({
section: "api-settings",
name: "API_KEY",
value: "my-secret-api-key",
description: "Production API key",
environment: "production",
});
// Retrieve configuration by section and name
const apiConfig = await this.configService.get({
section: "api-settings",
name: "API_KEY",
environment: "production",
shouldLoadSectionInfo: true,
useCache: true,
});
console.log("API Configuration:", apiConfig);
// apiConfig.value will be automatically decrypted if it was encrypted
return apiConfig;
}
async getConfigurationList() {
// Get all configurations in a section
const configs = await this.configService.getList({
section: "api-settings",
environment: "production",
useCache: true,
});
return configs;
}
async deleteConfiguration() {
// Delete a configuration
await this.configService.delete({
section: "api-settings",
name: "API_KEY",
environment: "production",
});
}
}
Async 模块注册
使用时 registerAsync(),必须通过 staticOptions 属性, 因为 NestJS 不支持 async 控制器注册 :
// app.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { ApiAuthorizationModule } from "@elsikora/nestjs-crud-automator";
import { CrudConfigModule } from "@elsikora/nestjs-crud-config";
@Module({
imports: [
ApiAuthorizationModule,
ConfigModule.forRoot(),
CrudConfigModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
// Dynamic options - resolved asynchronously
useFactory: async (configService: ConfigService) => ({
environment: configService.get("NODE_ENV", "development"),
encryptionOptions: {
isEnabled: true,
encryptionKey: configService.get("ENCRYPTION_KEY"),
},
cacheOptions: {
isEnabled: true,
maxCacheItems: 1000,
maxCacheTTL: 3600000,
},
}),
// Static options - must be known at module registration time
staticOptions: {
controllersOptions: {
section: {
isEnabled: true,
properties: {
path: "api/config/sections",
},
},
data: {
isEnabled: true,
properties: {
path: "api/config/data",
},
},
},
entityOptions: {
tablePrefix: "app_",
timestampColumnType: "timestamptz", // Must be static for dynamic entities
configSection: {
tableName: "config_sections",
maxNameLength: 128,
},
configData: {
tableName: "config_data",
maxValueLength: 8192,
},
},
migrationEntityOptions: {
tableName: "config_migrations",
},
},
}),
],
})
export class AppModule {}
重要内容: 这个 staticOptions 属性包含在模块编译时必须知道的配置 :
controllersOptions- REST API 控制器配置entityOptions- 数据库实体定制(表格名称、字段长度、时间戳类型)migrationEntityOptions- 迁移跟踪表配置
移民系统
NestJS CRUD 配置模块包含一个强大的 生产准备移民系统 它允许您在应用程序启动时初始化和管理配置状态。 该系统确保您的应用程序始终拥有不同环境和部署所需的配置数据.
关键特性
- 启动时自动执行 - 应用程序拖带时自动迁移
- QQ 已命名的交易支持 - 在一个名为Automator的拥有者内部进行交易式迁移
- 环境专题小组 - 为不同的环境创建不同的配置
- 移徙跟踪 - 有时间戳和执行状况的完整审计线索
- 后退支持 - 为每次迁移确定回滚程序
- 被困移民清理 - 自动暂停和清理已坠毁的迁移
- * 类型安全状态跟踪 - 用途
EConfigMigrationStatus可靠状态管理说明 - * 种族条件保护 - 安全执行防止同时发生的冲突
移民状态 Enum
移徙系统使用 EConfigMigrationStatus 用于跟踪移民状况的提示:
import { EConfigMigrationStatus } from "@elsikora/nestjs-crud-config";
// Available statuses:
EConfigMigrationStatus.PENDING; // Migration is pending execution
EConfigMigrationStatus.RUNNING; // Migration is currently running
EConfigMigrationStatus.COMPLETED; // Migration completed successfully
EConfigMigrationStatus.FAILED; // Migration failed with error
EConfigMigrationStatus.STUCK; // Migration is stuck (timeout)
基本迁移配置
在模块注册中配置迁移 :
import { CrudConfigModule } from "@elsikora/nestjs-crud-config";
import { initialAppConfigMigration } from "./migrations/001-initial-app-config.migration";
@Module({
imports: [
CrudConfigModule.register({
environment: process.env.NODE_ENV || "development",
// Migration configuration
migrationOptions: {
isEnabled: true,
shouldRunOnStartup: true,
useTransaction: true,
stuckMigrationTimeoutMinutes: 30,
tableName: "config_migrations", // Optional: custom table name
migrations: [
initialAppConfigMigration,
// Add more migrations here
],
},
// Other configuration options...
}),
],
})
export class AppModule {}
与 useTransaction: true (默认),执行拥有一个 crud-config-migrations 交易并传递准确 EntityManager 每一次迁移回调。 传那个经理作为 eventManager 在迁移的每个配置操作。 把它从 set() 试图打开单独的 crud-config-set 拥有者,而自动化器拒绝嵌入式拥有者.
与 useTransaction: false,没有全移民的拥有者和接收回电 undefined独立 set() 仍然拥有自己的原子 crud-config-set 交易,所以多个配置写不是全或一无所有。 倒行刑总是使用被命名为"迁移"的主人.
创建迁移文件
创建带有所需结构的迁移文件 :
// migrations/001-initial-app-config.migration.ts
import type { IConfigMigrationDefinition } from "@elsikora/nestjs-crud-config";
import type { CrudConfigService } from "@elsikora/nestjs-crud-config";
import type { EntityManager } from "typeorm";
export const initialAppConfigMigration: IConfigMigrationDefinition = {
name: "001_initial_app_config",
description: "Initialize basic application configuration",
async up(configService: CrudConfigService, entityManager?: EntityManager): Promise<void> {
// Create application settings
await configService.set({
section: "app-settings",
name: "APP_NAME",
value: "My Application",
description: "Application name",
environment: "default",
eventManager: entityManager,
});
await configService.set({
section: "app-settings",
name: "APP_VERSION",
value: "1.0.0",
description: "Application version",
environment: "default",
eventManager: entityManager,
});
// Create API settings
await configService.set({
section: "api-settings",
name: "API_RATE_LIMIT",
value: "100",
description: "API rate limit per minute",
environment: "default",
eventManager: entityManager,
});
},
async down(configService: CrudConfigService, entityManager?: EntityManager): Promise<void> {
// Rollback: remove configurations created by this migration
const configurationsToRemove = [
{ name: "APP_NAME", section: "app-settings" },
{ name: "APP_VERSION", section: "app-settings" },
{ name: "API_RATE_LIMIT", section: "api-settings" },
];
for (const config of configurationsToRemove) {
try {
await configService.delete({
section: config.section,
name: config.name,
environment: "default",
eventManager: entityManager,
});
} catch (error) {
// Expected if config was never created
console.warn(`Failed to delete config ${config.section}:${config.name} during rollback`);
}
}
},
};
特定环境移徙
创建在不同环境中工作的迁移:
// migrations/002-environment-specific-config.migration.ts
export const environmentSpecificConfigMigration: IConfigMigrationDefinition = {
name: "002_environment_specific_config",
description: "Environment-specific configuration settings",
async up(configService: CrudConfigService, entityManager?: EntityManager): Promise<void> {
const environments = ["development", "staging", "production"];
for (const env of environments) {
// Environment-specific debug settings
await configService.set({
section: "app-settings",
name: "DEBUG_MODE",
value: env === "development" ? "true" : "false",
description: "Enable debug mode",
environment: env,
eventManager: entityManager,
});
// Environment-specific API limits
const rateLimits = {
development: "1000",
staging: "500",
production: "100",
};
await configService.set({
section: "api-settings",
name: "API_RATE_LIMIT",
value: rateLimits[env],
description: "API rate limit per minute",
environment: env,
eventManager: entityManager,
});
}
},
async down(configService: CrudConfigService, entityManager?: EntityManager): Promise<void> {
const environments = ["development", "staging", "production"];
const configurationsToRemove = [
{ name: "DEBUG_MODE", section: "app-settings" },
{ name: "API_RATE_LIMIT", section: "api-settings" },
];
for (const config of configurationsToRemove) {
for (const environment of environments) {
try {
await configService.delete({
section: config.section,
name: config.name,
environment: environment,
eventManager: entityManager,
});
} catch (error) {
console.warn(
`Failed to delete config ${config.section}:${config.name}:${environment} during rollback`,
);
}
}
}
},
};
高级迁移配置
配置带有自定义选项的迁移 :
CrudConfigModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
environment: configService.get("NODE_ENV", "development"),
migrationOptions: {
isEnabled: true,
shouldRunOnStartup: true,
useTransaction: true,
stuckMigrationTimeoutMinutes: 60, // Custom timeout
migrations: [
initialAppConfigMigration,
environmentSpecificConfigMigration,
// Add more migrations in order
],
},
// Other dynamic options...
}),
// Static options for entities and controllers
staticOptions: {
migrationEntityOptions: {
tableName: "my_migrations", // Custom table name must be in staticOptions
maxNameLength: 256,
},
controllersOptions: {
section: { isEnabled: true },
data: { isEnabled: true },
},
},
});
移徙最佳做法
-
命名公约: 使用带有序列号的描述性名称
- ✅
001_initial_app_config - ✅
002_add_feature_flags - ❌
migration1, (中文(简体) ),config_setup
- ✅
-
重试安全性: 使用
set()作为配置密钥的更新await configService.set({ eventManager: entityManager, ...properties }); -
处理错误: 总是优雅地处理错误
try { await configService.set({ eventManager: entityManager, ...properties }); } catch (error) { console.error("Migration failed:", error); throw error; // Re-throw to mark migration as failed } -
回滚支持: 总是执行
down方法async down(configService: CrudConfigService, entityManager?: EntityManager): Promise<void> { // Implement rollback logic } -
环境意识: 使用特定环境配置
const currentEnv = process.env.NODE_ENV || "development"; await configService.set({ eventManager: entityManager, environment: currentEnv, // ... other options });
移徙监测
使用日志监视迁移执行 :
import { EConfigMigrationStatus } from "@elsikora/nestjs-crud-config";
@Injectable()
export class MigrationMonitorService {
constructor(private readonly migrationService: ConfigMigrationService) {}
async getMigrationStatus(): Promise<void> {
const migrations = await this.migrationService.getExecutedMigrations();
const completed = migrations.filter((m) => m.status === EConfigMigrationStatus.COMPLETED);
const failed = migrations.filter((m) => m.status === EConfigMigrationStatus.FAILED);
const stuck = migrations.filter((m) => m.status === EConfigMigrationStatus.STUCK);
console.log(
`Migrations - Completed: ${completed.length}, Failed: ${failed.length}, Stuck: ${stuck.length}`,
);
}
async getFailedMigrations(): Promise<IConfigMigration[]> {
const migrations = await this.migrationService.getExecutedMigrations();
return migrations.filter((m) => m.status === EConfigMigrationStatus.FAILED);
}
}
测试移民
测试您在不同环境中的迁移 :
describe("Initial App Config Migration", () => {
let configService: CrudConfigService;
let migration: IConfigMigrationDefinition;
beforeEach(async () => {
// Setup test environment
migration = initialAppConfigMigration;
});
it("should create required configurations", async () => {
await migration.up(configService);
const appName = await configService.get({
section: "app-settings",
name: "APP_NAME",
environment: "default",
});
expect(appName.value).toBe("My Application");
});
it("should rollback configurations", async () => {
await migration.up(configService);
await migration.down(configService);
await expect(
configService.get({
section: "app-settings",
name: "APP_NAME",
environment: "default",
}),
).rejects.toThrow();
});
});
API 文档
该模块会自动生成 REST API 端点, 并带有自定义路径 :
配置区域( 默认 ): /config/section(中文(简体) )
GET /config/section- 列出所有章节POST /config/section- 创建一个新的部分GET /config/section/:id- 获取部分的IDPUT /config/section/:id- 更新部分DELETE /config/section/:id- 删除一节
请求 POST/PUT 的正文 :
{
"name": "api-settings",
"description": "API configuration settings"
}
配置数据( 默认 ): /config/data(中文(简体) )
GET /config/data- 列出所有配置数据POST /config/data- 创建新配置GET /config/data/:id- 由ID进行配置PUT /config/data/:id- 更新配置DELETE /config/data/:id- 删除配置
请求 POST/PUT 的正文 :
{
"name": "API_KEY",
"value": "your-secret-key",
"environment": "production",
"description": "Production API key",
"isEncrypted": true,
"section": { "id": "section-uuid-here" }
}
自定义 API 端点
CrudConfigModule.register({
controllersOptions: {
section: {
properties: {
path: "api/v1/settings/sections",
name: "CustomSectionController",
swagger: {
tags: ["Configuration Sections"],
},
},
},
data: {
properties: {
path: "api/v1/settings/data",
routes: {
DELETE: { generation: { isEnabled: false } }, // Disable deletion
},
},
},
},
});
使用自动化路由选项 generation.isEnabled 用于路由生成。 关系加载使用类型ORM relationLoadStrategy 数值("query" 或者说 "join"); 内置配置数据段关系使用 "query"。 。 。 .
数据库Schema
该模块创建了两个主要表格,其默认结构如下:
配置区域表 (E)config_section(中文(简体) )
CREATE TABLE config_section (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(128) NOT NULL UNIQUE,
description VARCHAR(512),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
配置数据表( E)config_data(中文(简体) )
CREATE TABLE config_data (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(128) NOT NULL,
value VARCHAR(8192) NOT NULL,
environment VARCHAR(64) NOT NULL,
description VARCHAR(512),
is_encrypted BOOLEAN DEFAULT FALSE,
section_id UUID NOT NULL REFERENCES config_section(id) ON DELETE CASCADE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(name, environment, section_id)
);
高级配置
加密支持
该模块为敏感配置值提供内置的AES-256-GCM加密:
// Enable encryption with bounded derived-key reuse for repeated uncached reads
CrudConfigModule.register({
cacheOptions: { isEnabled: false },
encryptionOptions: {
isEnabled: true,
encryptionKey: process.env.CONFIG_ENCRYPTION_KEY, // 32+ character key
derivedKeyCacheMaxEntries: 64,
},
});
// When encryption is enabled, all values are encrypted automatically
await configService.set({
section: "database",
name: "DB_PASSWORD",
value: "my-secret-password",
});
// Retrieve and decrypt automatically
const config = await configService.get({
section: "database",
name: "DB_PASSWORD",
useCache: false,
});
console.log(config.value); // Automatically decrypted value
console.log(config.isEncrypted); // true
encryptionOptions.derivedKeyCacheMaxEntries 使用 lru-cache关闭它或设置它 0 以禁用再利用; 正安全整数使其得以使用。 同一选项可通过 registerAsync()。 。 。 .
此缓存在进程内存中保留了衍生的加密密钥,而不是配置值. 与 useCache: false,每个读取器仍然获取当前数据库值,每个解密调用AES-GCM认证所提供的密码文本。 只有成功的解密输入或促进缓存条目。 用不同的加密密钥来解密受影响的密钥缓冲器。 加密存储格式和同步加密API不变.
交易和复制保护
CrudConfigService.set() 没有调用时, 拥有一个名为自动化的交易 eventManager当迁移时,所有生成的配置科和配置数据服务业务都加入了同一交易.
包裹不需要消费者 EventEmitterModule 接线 配置数据独有性由整个数据库执行 name, (中文(简体) ), environment,以及 section; 自动化人映射一个相冲突生成的创建或更新到 409 CONFIGDATA_DUPLICATE_KEY。将特定应用程序的验证或审计放入应用程序服务/生命周期层,而不是包放入前事件.
无头模式( 没有控制器)
CrudConfigModule.register({
controllersOptions: {
section: { isEnabled: false },
data: { isEnabled: false },
},
});
这是完美的:
- 仅需要方案获取的背景服务
- 通过信件队列管理配置的微服务
- 带有自定义 GraphQL 或 gRPC 接口的应用程序
与多种环境合作
// multi-env.service.ts
@Injectable()
export class MultiEnvironmentService {
constructor(private readonly configService: CrudConfigService) {}
async setupEnvironmentConfigs() {
const environments = ["development", "staging", "production"];
for (const env of environments) {
await this.configService.set({
section: "database",
name: "DATABASE_URL",
environment: env,
value: `postgres://localhost:5432/${env}_db`,
description: `Database URL for ${env} environment`,
});
}
}
}
* 路线图
| 任务/ 特性 | 状态 |
|---|---|
| 核心动态实体系统 | 完毕 |
| TypeORM 与所有数据库的整合 | 完毕 |
| 等级配置(区/数据) | 完毕 |
| 使用 REST API 的 CRUD 操作 | 完毕 |
| 斯瓦格/ OpenAPI 文档 | 完毕 |
| 多种环境支助 | 完毕 |
| 已命名的自动化交易所有权 | 完毕 |
| 带有 TTL 的缓存系统 | 完毕 |
| 自定义表格名称和前缀 | 完毕 |
| 审定和制约因素 | 完毕 |
| NestJS CRUD 自动化器集成 | 完毕 |
| 脚本接口和类型 | 完毕 |
| AES-256-GCM 加密支持 | 完毕 |
| Async 模块注册 | 完毕 |
| 自动分区创建 | 完毕 |
| 图QL API 端点 | 执行中 |
| 配置版本和历史 | 执行中 |
| 基于角色的出入控制 | 执行中 |
| 配置模板和继承 | 执行中 |
| 通过 WebSocket 实时配置更新 | 执行中 |
| 配置验证计划 | 执行中 |
| 批量进出口功能 | 执行中 |
| 配置 diff 和合并工具 | 执行中 |
| 审计记录和变更跟踪 | 执行中 |
| 配置备份并恢复 | 执行中 |
| 与外部秘密管理人员合并 | 执行中 |
问 题
支持哪些数据库?
该模块支持TypeORM支持的任何数据库,包括:
- 邮递SQL - 建议的生产
- MySQL/马里亚DB - 网络应用程序的流行选择
- SQL 点 - 适合开发和测试(TypeORM 1驱动程序)
better-sqlite3(中文(简体) ) - 微软 SQL 服务器 - 企业数据库支助
- 甲骨文 - 企业级数据库
- 蒙戈DB - 无SQL文档数据库
- 鸡尾酒 - 分布式SQL数据库
这与环境变量有何比较?
虽然环境变量对于简单的配置来说很大,但本模块提供:
- 数据库的持久性 - 在容器重启后幸存的配置
- 运行时间更新 - 不重新部署而改变配置
- 等级组织 - 组相关配置
- 多种环境支助 - 从一个地方管理去除/储存/记录
- 加密支持 - 安全敏感数据
- (原始内容存档于2013-10-12) (英语). REST API - 方案管理配置
- 审计线索 - 音轨配置变化
我能从环境变量中迁移吗?
没错! 您可以在应用程序启动期间通过程序设置配置轻松地迁移 :
async function migrateFromEnvVars() {
const configs = [
{ section: "database", name: "DATABASE_URL", value: process.env.DATABASE_URL },
{ section: "api", name: "API_KEY", value: process.env.API_KEY },
// ... more configurations
];
for (const config of configs) {
await configService.set(config);
}
}
我如何处理敏感的配置数据?
该模块提供内置的AES-256-GCM加密支持:
CrudConfigModule.register({
encryptionOptions: {
isEnabled: true,
encryptionKey: process.env.CONFIG_ENCRYPTION_KEY,
},
});
敏感值在存储前自动加密,被检索后解密.
我能用这个微服务吗?
当然 该模块对于微服务架构是完美的:
- 集中配置 - 所有服务可以共享相同的配置数据库
- 特定服务科 - 按服务组织配置
- 环境隔离 - 单独的去除/固定/程序配置
- 动态更新 - 不重启服务的更新配置
我如何定制表格名称和字段大小?
该模块提供了广泛的定制选项:
CrudConfigModule.register({
entityOptions: {
tablePrefix: "myapp_",
timestampColumnType: "timestamptz",
configSection: {
tableName: "configuration_sections",
maxNameLength: 256,
maxDescriptionLength: 1024,
},
configData: {
tableName: "configuration_values",
maxValueLength: 16384, // 16KB values
maxEnvironmentLength: 128,
maxNameLength: 256,
maxDescriptionLength: 1024,
},
},
});
timestampColumnType 适用于本节所有九个时间栏、数据和移徙实体。 默认为 Date,哪个 TypeORM 映射到每个驱动程序的时间戳类型 : timestamp 关于PostgreSQL和 datetime 在MySQL, MariaDB, SQLite 上 (中文(简体) )better-sqlite3)和SQL.js,因此默认实体对每个实体都工作. 设置特定驱动程序类型, 如 "timestamptz" 用于 PostgreSQL ,只有在应用程序需要时。 为现有的数据库修改它仍然需要相应的计划迁移.
如果数据库不可用怎么办?
模块包括缓存处理临时数据库中断:
- 内存缓存 - 最近访问的配置被缓存
- 可配置 TTL - 控制缓存配置的时间
- 严重退化 - 数据库不可用时返回到缓存值
我能用这个吗?
没错! 该模块支持禁用控制器的"无头模式":
CrudConfigModule.register({
controllersOptions: {
section: { isEnabled: false },
data: { isEnabled: false },
},
});
准备好生产了吗?
没错! 该模块的建造考虑到了生产用途:
- 类型安全 - 完整类型脚本支持防止运行时间出错
- 作战测试 - 以已证实的技术(NestJS、TypeORM)建造
- 可缩放 - 企业数据库方面的工作
- 安全 - 内置加密和验证
- 可观察 - 综合伐木和监测钩
许可证
这个项目的许可证根据 MIT 许可证
版权(c) 2025 Elsi Kora
特此准许任何人免费获得本软件和相关文件文件("软件")的副本,不受限制地在软件中进行交易,包括不受限制地享有软件的使用、复制、修改、合并、出版、分发、分版和(或)销售的权利,并允许软件获得者这样做,但须符合下列条件: 1
上述版权通知和许可通知应载入软件的所有副本或大部分.
软件是提供的"AS IS", 没有任何种类的恐惧, 释放或被卷入, 包括但不限制在 危机的保障, 证明一个特定的目的和无关。 任何索赔、索赔或其他负债,无论是合同、交易或其他行为,产生于、产生于或涉及软件或软件的使用或其他交易的行为,都不得作为担保.