QQ NestJS AWS 参数存储配置
无缝巢JS与AWS系统管理器参数存储器的集成——一个犬形SSM合同来统治您的所有配置.
重点
- 萨斯米 合同——执行确定性////模型,消除各小组命名混乱的临时参数
- QQ 单递归负载 — 启动时将所有参数在 // 下获取到内存缓存中, 以零运行时的 SSM 调用即时服务查询
- QQ- fault- Fast 校验 — 在启动时捕捉缺失的片段、 空字符串、 空白空格和非法的“ /” 字符并带有明显的错误信息
- QQ NestJS 12和ES模块——为NestJS 12所建,作为通用JS应用程序通过Node.js加载的ES模块包
require(esm),包含注册()和注册()
目录
说明
管理跨多环境的应用配置,命名空间,以及部署目标,是云内开发中最容易出错的一个方面. NestJS AWS 参数存储配置 通过执行单一的、有条不紊的SSM路径合同消除了这种复杂性:
/<application>/<environment>/<namespace>/<instanceName>/<path...>
这个模块提供了一个一等的NestJS动态模块,在启动时将所有参数加载到内元缓存中,然后曝光一个类型安全,经过验证的搜索API,可以决定性地解决路径.
实际世界使用案例
- ECS/EKS的微服务:每个服务单位都有自己的登记册
namespace财务报告和审定财务报表instanceName,同时通过命名空间共享基础设施参数(数据库主机,秘密ID). - 多种环境部署: 无缝交换
local, (中文(简体) ),development, (中文(简体) ),staging,以及production而不更改单行应用程序代码. - 共享的基础设施元数据: 从
/<app>/<env>缓存一切—— RDS 连接字符串, 秘密管理器引用, Cloud Watch 配置—— 通过简单的路径查看访问 . - Monorepo / 多种服务结构: 不同的服务可以覆盖
namespace财务报告和审定财务报表instanceName每个调用,在不重新登记模块的情况下访问等级中的任何参数.
拥有90+命名空间符号(AWS,GCP,Azure,数据库,消息经纪人等)的内置enum,在错误配置的路径上快速失败的严格验证,以及支持同步和Async模块注册,这个库将AWS参数存储器转变为结构化,可预测的配置主干线,用于您的NestJS应用程序.
QQ 技术堆栈
| 类别 | 技术 |
|---|---|
| 语言 | 类型脚本 |
| 运行时间 | 节点.js |
| 框架 | 网点JS |
| 云头 | AWS 系统管理器( SSM) |
| 构建工具 | 滚动, 类型脚本编译器 |
| 线性 | ESLint, 高级 |
| 排雷中心/发改委 | GitHub 动作,语义释放 |
| 软件包管理器 | 无 |
| 代码质量 | 胡斯基, 科特林特, 林特-斯图德 |
* 特性
- ✨ 条形路径合同 ——所有参数的查找通过严格
/<application>/<environment>/<namespace>/<instanceName>/<path>模式,确保所有服务和环境的一致性 - ✨ 递归参数加载 — 装入所有参数
/<application>/<environment>在启动时使用 pagized SSM API 调用, 建立用于即时检查的内存缓存 - ✨ 同步同步模块注册( A) - 支助
register()用于静态配置和registerAsync()与useFactory, (中文(简体) ),useClass,以及useExisting动态配置模式 - ✨ 逐个覆盖 - 覆盖
namespace, (中文(简体) ),instanceName, (中文(简体) ),application,或environment任何个人get()调用同时保留模块级别默认值 - ✨ 90+ 内建命名空间托肯 — 已破获
ENamespace包括AWS、GCP、Azure服务、数据库、信件经纪人、可观察工具等 - ✨ 生命周期环境 Enum —— 说
EEnvironment提供LOCAL, (中文(简体) ),DEVELOPMENT, (中文(简体) ),STAGING, (中文(简体) ),PRODUCTION,以及TEST框外的符号 - ✨ 严格输入验证 —— 对缺失的片段、 空字符串、 仅空白值和包含的片段的描述错误失败
/ - ✨ ES 模块软件包 - 船舶使用源地图和相对进口的 " 脚本 " 类型申报建造一个ES模块
.js扩展,所以bundler, (中文(简体) ),nodenext和通用JS系统node10消费者所有打字检查 - ✨ 安全参数解密 - 可选
shouldDecryptParameters旗帜可以透明地解密安全结构参数 - ✨ 微博日志模式 - 可选
isVerbose旗下启用详细 NestJS Logger 输入参数时用于调试的输出 - ✨ 全球模块 登记为a
@Global()模块,制作ParameterStoreConfigService可在不重新进口的任何地方注入 - ✨ 0 运行时间依赖 ——仅是同级依附关系
@aws-sdk/client-ssm财务报告和审定财务报表@nestjs/common由您的申请提供
建筑
系统架构
flowchart TD
appModule[AppModule] -->|imports| configModule[ParameterStoreConfigModule]
configModule -->|provides| propertiesProvider[PropertiesProvider]
configModule -->|provides| ssmProvider[SSMClientProvider]
configModule -->|provides| parametersProvider[ParametersProvider]
configModule -->|provides| parameterStoreService[ParameterStoreService]
configModule -->|exports| configService[ParameterStoreConfigService]
ssmProvider -->|creates| ssmClient[SSMClient]
parameterStoreService -->|uses| ssmClient
parametersProvider -->|calls| parameterStoreService
configService -->|reads| propertiesProvider
configService -->|reads| parametersProvider
anyService[Any Injectable Service] -->|injects| configService
数据流动
sequenceDiagram
participant App as NestJS App
participant Module as ConfigModule
participant SSMProvider as SSMClientProvider
participant ParamProvider as ParametersProvider
participant PSService as ParameterStoreService
participant AWS as AWS SSM API
participant Service as Your Service
participant ConfigSvc as ConfigService
App->>Module: register() / registerAsync()
Module->>SSMProvider: Create SSMClient with config
SSMProvider-->>Module: SSMClient instance
Module->>ParamProvider: Initialize parameter loading
ParamProvider->>PSService: getParametersByPath(/app/env)
loop Paginated Loading
PSService->>AWS: GetParametersByPathCommand
AWS-->>PSService: Parameters + NextToken
end
PSService-->>ParamProvider: All Parameter[] cached
ParamProvider-->>Module: In-memory parameter cache ready
Service->>ConfigSvc: get({ path, namespace?, ... })
ConfigSvc->>ConfigSvc: buildLookupPath() + validate
ConfigSvc->>ConfigSvc: Find in cached parameters
ConfigSvc-->>Service: string value or null
项目结构
单击以扩展
NestJS-AWS-Parameter-Store-Config/
├── .github/
│ ├── workflows/
│ │ ├── mirror-to-codecommit.yml
│ │ ├── qodana-quality-scan.yml
│ │ ├── release.yml
│ │ ├── snyk-security-scan.yml
│ │ └── test.yml
│ └── dependabot.yml
├── scripts/
│ ├── test/
│ │ └── consumer-smoke.mjs
│ └── check-declaration-imports.cjs
├── src/
│ ├── modules/
│ │ ├── aws/
│ │ └── config/
│ ├── shared/
│ │ ├── constant/
│ │ ├── enum/
│ │ ├── interface/
│ │ └── provider/
│ └── index.ts
├── test/
│ ├── consumer/
│ └── unit/
├── CHANGELOG.md
├── commitlint.config.js
├── eslint.config.js
├── LICENSE
├── lint-staged.config.js
├── nest-cli.json
├── package.json
├── prettier.config.js
├── README.md
├── release.config.js
├── rollup.config.js
├── tsconfig.build.json
├── tsconfig.json
└── vitest.unit.config.js
· 先决条件
- 节点.js
^22.13.0 || >=24.11.0 @nestjs/common>=12.3.2 <13@aws-sdk/client-ssm>=3.535.0 <4- 配置 AWS 证书( IAM 角色、 环境变量或 AWS CLI 配置)
- AWS SSM 参数按照犬形路径公约创建
* 安装
# Install the package and its required peer dependencies
npm install @elsikora/nestjs-aws-parameter-store-config @aws-sdk/client-ssm @nestjs/common
# Or with Yarn
yarn add @elsikora/nestjs-aws-parameter-store-config @aws-sdk/client-ssm @nestjs/common
# Or with pnpm
pnpm add @elsikora/nestjs-aws-parameter-store-config @aws-sdk/client-ssm @nestjs/common
### Building from Source
# Clone the repository
git clone https://github.com/ElsiKora/NestJS-AWS-Parameter-Store-Config.git
cd NestJS-AWS-Parameter-Store-Config
# Install dependencies
npm install
# Build the ES module output and check its imports
npm run build
# Run linting
npm run lint:all
# Type check
npm run lint:types
# Run unit tests
npm run test:unit
# Pack the build and run it in ESM (bundler, nodenext) and CommonJS (node10, default resolution) consumer apps
npm run test:consumer
使用量
快速启动
1. 登记模块
添加 ParameterStoreConfigModule 转到您的根 AppModule 与您的犬科默认值:
import { Module } from "@nestjs/common";
import { EEnvironment, ENamespace, ParameterStoreConfigModule } from "@elsikora/nestjs-aws-parameter-store-config";
@Module({
imports: [
ParameterStoreConfigModule.register({
application: "gameport",
environment: EEnvironment.STAGING,
namespace: ENamespace.AWS_ECS_FARGATE,
instanceName: "reaper-api",
shouldDecryptParameters: true,
config: {
region: "eu-north-1",
},
}),
],
})
export class AppModule {}
2. 以配置服务进行同步登记
对于取决于环境变量或其他提供者的动态配置:
import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { EEnvironment, ENamespace, ParameterStoreConfigModule } from "@elsikora/nestjs-aws-parameter-store-config";
@Module({
imports: [
ConfigModule.forRoot(),
ParameterStoreConfigModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
application: configService.getOrThrow("APP_NAME"),
environment: configService.getOrThrow("NODE_ENV"),
namespace: ENamespace.AWS_ECS_FARGATE,
instanceName: configService.getOrThrow("SERVICE_NAME"),
shouldDecryptParameters: true,
shouldUseRecursiveLoading: true,
isVerbose: configService.get("VERBOSE") === "true",
config: {
region: configService.getOrThrow("AWS_REGION"),
},
}),
}),
],
})
export class AppModule {}
3. 注入和使用该处
由于模块 @Global()时,您可以注射 ParameterStoreConfigService 在任何提供者中:
import { Injectable } from "@nestjs/common";
import { ENamespace, ParameterStoreConfigService } from "@elsikora/nestjs-aws-parameter-store-config";
@Injectable()
export class DatabaseService {
constructor(private readonly config: ParameterStoreConfigService) {}
getDatabaseHost(): string {
// Resolves: /gameport/staging/aws-rds/aurora-postgres/host
return (
this.config.get({
namespace: ENamespace.AWS_RDS,
instanceName: "aurora-postgres",
path: ["host"],
}) ?? "localhost"
);
}
getDatabasePort(): number {
// Resolves: /gameport/staging/aws-rds/aurora-postgres/port
const port = this.config.get({
namespace: ENamespace.AWS_RDS,
instanceName: "aurora-postgres",
path: ["port"],
});
return port ? parseInt(port, 10) : 5432;
}
}
4. 交叉命名空间查询
不重新登记而从不同的命名空间访问参数 :
@Injectable()
export class AppConfigService {
constructor(private readonly config: ParameterStoreConfigService) {}
// Uses module defaults: /gameport/staging/aws-ecs-fargate/reaper-api/api/version
getApiVersion(): string | null {
return this.config.get({ path: ["api", "version"] });
}
// Override namespace: /gameport/staging/aws-secrets-manager/database/secret-id
getDatabaseSecretId(): string | null {
return this.config.get({
namespace: ENamespace.AWS_SECRETS_MANAGER,
instanceName: "database",
path: ["secret-id"],
});
}
// Override everything: /other-app/production/aws-lambda/processor/timeout
getExternalConfig(): string | null {
return this.config.get({
application: "other-app",
environment: "production",
namespace: ENamespace.AWS_LAMBDA,
instanceName: "processor",
path: ["timeout"],
});
}
}
5. 自定义命名空间字符串
不限于内置语句——通过任意字符串:
this.config.get({
namespace: "custom-service",
instanceName: "my-instance",
path: ["some", "deep", "config"],
});
// Resolves: /gameport/staging/custom-service/my-instance/some/deep/config
配置选项参考
| 选项 | 类型 | 需求 | 默认 | 说明 |
|---|---|---|---|---|
application | string | ✅ | —— 说 | 产品/系统名称(第一路径段) |
environment | EEnvironment | string | ✅ | —— 说 | 生命周期环境标志 |
namespace | ENamespace | string | ✅ | —— 说 | 默认所有者/ 运行时间/ 资源令牌 |
instanceName | string | ✅ | —— 说 | 默认可部署单位或资源实例 |
config | SSMClientConfig | ❌ | {} | AWS SSM 客户端配置 |
shouldDecryptParameters | boolean | ❌ | false | 解密安全结构参数 |
shouldUseRecursiveLoading | boolean | ❌ | true | 递增地加载所有嵌入参数 |
isVerbose | boolean | ❌ | false | 启用参数加载时的动词记录 |
移民笔记
移动到 3. 0
3.0.0 将货包移动至NestJS 12,并将其作为仅作为ES模块来运输. 配置 API, Cononical 路径合同和导出的名称不改变.
| 所需经费 | 2.x 数据 | 3.0 调用 |
|---|---|---|
| 节点.js | 16岁及以后 | ^22.13.0 || >=24.11.0 |
@nestjs/common | ^8 || ^9 || ^10 || ^11 | >=12.3.2 <13 |
| 模块格式 | 无害环境管理和共同JS | 仅限无害环境管理 |
- 首先升级节点.js和NestJS,然后升级 NestJS 移徙指南在 NestJS 11 或 以上,或在 Node.js 20 上的申请,请留在 2.x 上.
- 安装有明确范围的等同位素
npm install @nestjs/common@^12 @aws-sdk/client-ssm@^3,并检查树npm ls。 。 。 . - 只从软件包根导入 。 2.x号
exports地图已经只有.,因此Node.js从未解决过深度进口. 3.0 也删除dist/esm, (中文(简体) ),dist/cjs编辑require条件,所以 TypeScript 与node10决议,而忽略exports,不再找到深路径的类型,例如:@elsikora/nestjs-aws-parameter-store-config/dist/cjs/...也一样.
ES模块应用程序 和以前一样导入软件包 moduleResolution 设置为 bundler, (中文(简体) ), node16 或者说 nodenext. 声明现在 .js 每个相对导入的扩展名, 所以 nodenext 消费者得到的类型.
普通JS应用程序 保留 require("@elsikora/nestjs-aws-parameter-store-config"). Node.js 装入 ES 模块通过 require(esm),这在每一个支持的节点.js发布时都没有旗帜。 类型脚本 module: commonjs 找到这些类型的方式是: moduleResolution: node10 通过顶层 types 字段(文本 6 然后需要) "ignoreDeprecations": "6.0"页:1 moduleResolution,而TypeScript 6 的解析为 bundler,通过 exports。 。 。 .
导入软件包没有副作用: 它加载否 .env 文档,然后写到控制台。 仅在参数加载时进行日志并仅使用 isVerbose: true线人检查了布满的焦油丸.
* 路线图
单击以扩展
| 任务/ 特性 | 状态 |
|---|---|
Canonic SSM路径合同(/<app>/<env>/<ns>/<instance>/<path>(中文(简体) ) | 完毕 |
| 同步和同步模块注册 | 完毕 |
| 已加插的递归参数加载 | 完毕 |
| 按呼命名空间和实例覆盖 | 完毕 |
| 使用故障快速错误严格输入验证 | 完毕 |
| ES模块输出,并附有延期合格申报 | 完毕 |
| 雀巢JS 12支持 | 完毕 |
| 内建的 ENamespace enum( 90+ 令牌) | 完毕 |
| Verbose 记录模式 | 完毕 |
| 自动语义释放后相接 | 完毕 |
| TTL 参数缓存刷新 | 执行中 |
| 参数更改事件订阅 | 执行中 |
批次 getMany() 多路径搜索的 API | 执行中 |
| 关于可检索值的可选 Zod/类验证器计划验证 | 执行中 |
| 单元测试套件和包装弹丸消费者烟雾测试 | 完毕 |
问 题
单击以扩展
经常被问到的问题
问题:此模块是否使 SSM API 调用每个 get() 引用吗?
A: 否. 所有参数在模块初始化(启动)时被加载一次入内存储. 这个 get() 方法对缓存参数进行简单的数组检查——零运行时SSM API呼叫.
问:模块如何处理大量参数?
答复: ParameterStoreService 自动处理 SSM API pagining 。 它继续使用 NextToken 直到所有参数下 /<application>/<environment> 已装入.
问:我能用自定义的字符串而不是内置的音符吗?
答:对! 两者 environment 财务报告和审定财务报表 namespace 接受 string 类型之外 EEnvironment 财务报告和审定财务报表 ENamespace um. 这允许您使用自定义的符号, 如 "my-custom-namespace" 当内置选项不适合.
问:支持哪个 NestJS 版本?
A: 3.x 支持 NestJS 12 (英语:@nestjs/common >=12.3.2 <13对于NestJS 8至11,使用 2.x.
问:我能使用普通JS应用程序的软件包吗?
答:对。 软件包是一个ES模块,和Node.js ^22.13.0 || >=24.11.0 装入它从 require() 结束 require(esm)。TypeScript通过顶级查找类型 types 字段为 node10 决议和通过 exports 与 node16, (中文(简体) ), nodenext 或者说 bundler,这也是 TypeScript 6 用于 module: commonjs 无 moduleResolution。见 移徙说明。 。 。 .
问:我是否需要在每个特性模块中导入模块?
甲:无. ParameterStoreConfigModule 以 @Global(),所以,一旦注册在您的根 AppModule,则 ParameterStoreConfigService 可在应用程序中的任何提供者中注入.
问:如果缺少一个必要的部分(应用、环境等),会发生什么?
A:模块在启动时或浏览时立即抛出描述性错误. 它证明没有线段是 undefined, (中文(简体) ), null,空的,仅空白,或包含 / 字符键.
问:我如何解密安全 String 参数?
A:设置 shouldDecryptParameters: true 在模块注册选项中。 这个通过 WithDecryption: true 向特别安全委员会提交的报告 GetParametersByPathCommand。 。 。 .
问:我能从不同的应用程序或环境访问参数吗?
答:是的,但有一个警告。 这个 get() 方法接受按调用时对 application 财务报告和审定财务报表 environment,但内存缓存中仅包含从模块配置中装入的参数 /<application>/<environment> 前缀。 要访问不同前缀的参数,您需要注册第二个模块实例,或者确保这些参数存在于已加载前缀下.
许可证
这个项目的许可证根据 麻省理工学院。 。 。 .
承认
- 网点JS ——进步节点.js框架,使构建服务器侧应用程序成为欢乐
- JavaScript v3 的 AWS SDK 软件 ——模块化AWS SDK为SSM客户端提供动力
- AWS 系统管理器 ——安全分级配置存储服务
- 语义释放 ——全自动版本管理和软件包出版
- 滚动 - 生产ES模块输出的模块捆绑器
- 埃尔西科拉 ——本单元幕后团队和更广泛的工具生态系统
为雀巢JS社区建造