@elsikora/nestjs-crud-config

中文文档
5.1.0发布于 2026/11/04MITTypeScriptES Module近 30 天下载 7382

通过数据库存储 NestJS 应用程序配置

中文使用文档
文档目录46 节
  1. 目录
  2. 说明
  3. * 特性
  4. * 安装
  5. 先决条件
  6. 自动化 5 兼容性
  7. 迁移到 5.0
  8. 数据库支持
  9. 使用量
  10. 基本设置
  11. 使用配置服务
  12. Async 模块注册
  13. 移民系统
  14. 关键特性
  15. 移民状态 Enum
  16. 基本迁移配置
  17. 创建迁移文件
  18. 特定环境移徙
  19. 高级迁移配置
  20. 移徙最佳做法
  21. 移徙监测
  22. 测试移民
  23. API 文档
  24. 配置区域( 默认 ): /config/section (中文(简体) )
  25. 配置数据( 默认 ): /config/data (中文(简体) )
  26. 自定义 API 端点
  27. 数据库Schema
  28. 配置区域表 (E) config_section (中文(简体) )
  29. 配置数据表( E) config_data (中文(简体) )
  30. 高级配置
  31. 加密支持
  32. 交易和复制保护
  33. 无头模式( 没有控制器)
  34. 与多种环境合作
  35. * 路线图
  36. 问 题
  37. 支持哪些数据库?
  38. 这与环境变量有何比较?
  39. 我能从环境变量中迁移吗?
  40. 我如何处理敏感的配置数据?
  41. 我能用这个微服务吗?
  42. 我如何定制表格名称和字段大小?
  43. 如果数据库不可用怎么办?
  44. 我能用这个吗?
  45. 准备好生产了吗?
  46. 许可证

project-logo

雀巢JS CRUD 配置

具有全部CRUD能力的 NestJS 应用程序的数据库支持配置管理

ElsiKora TypeScript NestJS Node.js PostgreSQL MySQL SQLite MongoDB Swagger

目录

说明

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/typeorm 12和类型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 },
  },
 },
});

移徙最佳做法

  1. 命名公约: 使用带有序列号的描述性名称

    • ✅ 001_initial_app_config
    • ✅ 002_add_feature_flags
    • ❌ migration1, (中文(简体) ), config_setup
  2. 重试安全性: 使用 set() 作为配置密钥的更新

    await configService.set({ eventManager: entityManager, ...properties });
    
  3. 处理错误: 总是优雅地处理错误

    try {
     await configService.set({ eventManager: entityManager, ...properties });
    } catch (error) {
     console.error("Migration failed:", error);
     throw error; // Re-throw to mark migration as failed
    }
    
  4. 回滚支持: 总是执行 down 方法

    async down(configService: CrudConfigService, entityManager?: EntityManager): Promise<void> {
      // Implement rollback logic
    }
    
  5. 环境意识: 使用特定环境配置

    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 - 获取部分的ID
  • PUT /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", 没有任何种类的恐惧, 释放或被卷入, 包括但不限制在 危机的保障, 证明一个特定的目的和无关。 任何索赔、索赔或其他负债,无论是合同、交易或其他行为,产生于、产生于或涉及软件或软件的使用或其他交易的行为,都不得作为担保.

版本与发布记录

@elsikora/nestjs-crud-config 共发布 49 个版本,首次发布于 2025/07/14;过去 12 个月发布了 35 个版本。

版本发布日期距今
5.1.0latest2026/11/049 天前
5.1.0-dev.1beta2026/11/049 天前
5.0.02026/11/0310 天前
5.0.0-dev.62026/11/0310 天前
5.0.0-dev.52026/11/0211 天前
5.0.0-dev.42026/11/0211 天前

关于 @elsikora/nestjs-crud-config 的常见问题

@elsikora/nestjs-crud-config 是什么?

通过数据库存储 NestJS 应用程序配置

如何安装 @elsikora/nestjs-crud-config?

在项目目录运行 npm install @elsikora/nestjs-crud-config,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:lodash(^4.18.1)、fastify(^5.12.7)、typeorm(^1.1.2)、@nestjs/core(^12.3.2)、@nestjs/common(^12.3.2)、@nestjs/swagger(^12.0.0)、@nestjs/typeorm(^12.0.1)、class-validator(^0.15.1)、@nestjs/passport(^12.0.0)、@nestjs/throttler(^6.7.1)、class-transformer(^0.5.1)、@nestjs/platform-fastify(^12.3.2)、@elsikora/nestjs-crud-automator(^5.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@elsikora/nestjs-crud-config 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@elsikora/nestjs-crud-config 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@elsikora/nestjs-crud-config 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js ^22.13.0 || >=24.11.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@elsikora/nestjs-crud-config 可以商用吗?

@elsikora/nestjs-crud-config 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@elsikora/nestjs-crud-config 的下载量有多少?

根据 npm 官方下载统计,@elsikora/nestjs-crud-config 在 2026/10/14 – 2026/11/12 这 30 天内被下载 7,382 次,日均约 246 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@elsikora/nestjs-crud-config 还在维护吗?

最新版本 5.1.0 发布于 2026/11/04(9 天前);至今共发布 49 个版本,其中过去 12 个月发布了 35 个;首次发布于 2025/07/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。