# @crvouga/mockingbird-service-aws-iot 中文文档

规范地址：https://npmcn.com/package/%40crvouga/mockingbird-service-aws-iot/

版本：0\.10\.0
npm 元数据更新时间：2026-11-11T01:59:37.093Z
中文译文更新时间：2026-11-11T06:21:04.366Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40crvouga/mockingbird-service-aws-iot
原文对照：https://npmcn.com/package/%40crvouga/mockingbird-service-aws-iot/?lang=original
项目主页：https://github.com/crvouga/mockingbird/tree/main/packages/service/aws-iot#readme
源码仓库：https://github.com/crvouga/mockingbird

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：4.7 MB，18 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：1 个
- 首次发布：2026-10-11T01:55:56.403Z
- 最新版本发布：2026-11-11T01:59:36.756Z
- 近 30 天下载量：3002（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：19（近 12 个月 19 个）

## 中文简介

AWS IoT Core Data平面的状态仿真器:由SigV4签名的HTTP Publishing和由TCP和WebSocket负责的MQTT 5消息经纪人,有自定义授权政策和持续会话.

## 安装

```sh
npm install @crvouga/mockingbird-service-aws-iot
```

也可以使用：`pnpm add @crvouga/mockingbird-service-aws-iot`、`yarn add @crvouga/mockingbird-service-aws-iot`、`bun add @crvouga/mockingbird-service-aws-iot`

## README

# @crvouga/mockingbird-service-aws-iot (英语)

> 本地模拟器。 真正的API合同. 部分 [嘲笑鸟](https://github.com/crvouga/mockingbird)。 。 。 .

国家模拟器 **AWS IOT 核心数据平面** 测试套房和地方开发: IoTData 计划 `Publish` hTTP 有签名版本 4 验证和 MQTT 5 信件 tCP和WebSocket的经纪人(`/mqtt`)与自定义授权政策,AWS IoT的持久性 课程规则及其与 MQTT 规格的偏离。 它在测试中运行 在没有 AWS 账户的 OS 指定端口上进行处理,会话到期会跟随套件的时钟 移动而不是等待.

-   行动覆盖( HTTP): [支助](https://github.com/crvouga/mockingbird/blob/main/packages/service/aws-iot/SUPPORT.md)
-   没有AWS账户被用作甲骨文. 行为遵循 [发布 API 引用](https://docs.aws.amazon.com/iot/latest/apireference/API_iotdata_Publish.html), (中文(简体) ), 页:1 [MQTT 数据](https://docs.aws.amazon.com/iot/latest/developerguide/mqtt.html), (中文(简体) ), [自定义认证](https://docs.aws.amazon.com/iot/latest/developerguide/custom-auth.html), (中文(简体) ), [政策](https://docs.aws.amazon.com/iot/latest/developerguide/pub-sub-policy.html) 财务报告和审定财务报表 [配额](https://docs.aws.amazon.com/general/latest/gr/iot-core.html#message-broker-limits) 页面,以及AWS的SDK标志. 未结算的列在下面 [未核实](https://npmcn.com/package/%40crvouga/mockingbird-service-aws-iot/#readme-unverified)。 。 。 .
-   这不是EM Q的模仿者 与另一个名字: (单位:千美元)`@crvouga/mockingbird-service-emqx`)),各随自取.

## 安装

```bash
npm install -D @crvouga/mockingbird-service-aws-iot
```

仅限无害环境管理。 节点 22或 Bun 1.2. 无土生属地. 给它服务 `npx mockingbird-aws-iot serve` 或者说 `createServer` 从 `./server` (节点和邦). `createRuntime` (默认条目)是可移植的:服务 `Publish` 结束 `fetch` 和 MQTT 通过 `runtime.attach`没有听者.

## 使用量

将应用程序的 IOT 数据端点指向 `url` 及其在 `mqttUrl` 或者说 `wsUrl`没有 TLS: 使用 `http://`, (中文(简体) ), `mqtt://` 财务报告和审定财务报表 `ws://` 给定的 URL .

```ts
import { createServer } from "@crvouga/mockingbird-service-aws-iot/server"
import { IoTDataPlaneClient, PublishCommand } from "@aws-sdk/client-iot-data-plane"
import mqtt from "mqtt"

// Test setup: start the emulator with the credentials and authorizer policies the test needs.
const arn = (resource: string) => `arn:aws:iot:us-east-1:123456789012:${resource}`
const iot = await createServer({
  settings: {
    // HTTP: SigV4 signatures are verified against these keys.
    credentials: [{ accessKeyId: "test-key", secretAccessKey: "test-secret" }],
    // MQTT: what the custom authorizer answers for a username and password.
    authorizers: [
      {
        username: "alice",
        password: "alice-token",
        policyDocuments: [
          {
            Version: "2012-10-17",
            Statement: [
              { Effect: "Allow", Action: "iot:Connect", Resource: arn("client/alice-*") },
              { Effect: "Allow", Action: "iot:Subscribe", Resource: arn("topicfilter/user/alice") },
              { Effect: "Allow", Action: "iot:Receive", Resource: arn("topic/user/alice") },
            ],
          },
        ],
      },
    ],
  },
})

// Application code: the MQTT client and AWS SDK client it already uses, pointed at the emulator.
const device = await mqtt.connectAsync(iot.mqttUrl, {
  protocolVersion: 5,
  clientId: "alice-phone",
  clean: false,
  properties: { sessionExpiryInterval: 600 },
  username: "alice",
  password: "alice-token",
})
await device.subscribeAsync("user/alice", { qos: 1 })

const client = new IoTDataPlaneClient({
  region: "us-east-1",
  endpoint: iot.url,
  credentials: { accessKeyId: "test-key", secretAccessKey: "test-secret" },
})
await client.send(new PublishCommand({ topic: "user/alice", qos: 1, payload: '{"hello":"alice"}' }))

await device.endAsync()
await iot.close() // closes every listener and drops every client
```

```bash
npx mockingbird-aws-iot serve --port 8851 --mqtt-port 8883 \
  --credential test-key:test-secret --settings ./aws-iot-settings.json
```

每个 `createServer()` 是它自己拥有自己的港口的经纪人,其中两个没有分享任何东西。 下 邦顿, `mqtt`节点 WebSocket 传输没有启动( Bun) `ws` 没有 `createWebSocketStream`,所以连接到 `wsUrl` 与库的浏览器传输 (单位:千美元)`new MqttClient((c) => browserStreamBuilder(c, options), options)` 从 `mqtt/lib/connect/ws`, (中文(简体) ), 或用途 `connectStream(runtime)` 从 `./server` 用于无套接字连接。 在平原的节点上 `mqtt.connect("ws://…/mqtt")` 工作时.

话题是客户发送的。 AWS IOT 与 `/` 并给出 `:` 没有意义, 因此,一个名为主题的应用程序 `user:example` 并公布为 `user/example` 这样做 映射本身;模拟器像AWS一样,从未看到第一个形式.

### 路线

| 路线 | 行为 |
| --- | --- |
| `POST /topics/{topic}?qos=0|1` | IoTData 计划 `Publish`身体是有效载荷,作为发送的字节。 话题为 %- 解码一次( Q)`user%2Fexample` 实值 `user/example`· ; `a%252Fb` 字义 `a%2Fb`);未编码的鞭打也被接受,如AWS本身的例子. `200 {"message": "OK", "traceId": "…"}` 无论是否有人订阅。 另见: `retain`, (中文(简体) ), `contentType`, (中文(简体) ), `responseTopic`, (中文(简体) ), `messageExpiry` (调整为1-60480) `x-amz-mqtt5-user-properties`, (中文(简体) ), `x-amz-mqtt5-payload-format-indicator` 财务报告和审定财务报表 `x-amz-mqtt5-correlation-data` 信头, 以 MQTT 5 属性覆盖订阅者 . |
| 错误 | `{"message": "…", "traceId": "…"}` 与 `x-amzn-ErrorType`。 。 。 . `400 InvalidRequestException` 对于一个已空出、有通配符、超过256字节或7下划线或从 `$`页:1 `qos` 0或1以外; 错误 `retain`, (中文(简体) ), `messageExpiry` 或 MQTT 5 头; 畸形% 逃出; 有效载荷超过 128 KB. `401 UnauthorizedException` 当签名身份政策不允许时 `iot:Publish` 关于这个话题. `403` (单位:千美元)`Forbidden`请求未经签字或其签字未核实. `405 MethodNotAllowedException` 对于任何其他动词或路径。 一个 `x-mockingbird-reason` 信头显示检查失败 . |

**SigV4 (英语).** 与 `credentials` 空的, 任何包含一个完整格式的请求 `Authorization: AWS4-HMAC-SHA256 …` 信头不被验证(作为Mockingbird的另一个AWS) 模拟者也这样做),未签名的请求仍然被拒绝. 已配置了证书 签名必须验证:服务 `iotdata`,配置的区域, `host` 财务报告和审定财务报表 `x-amz-date` 签名, 路径在犬科请求中编码了第二次(除了S3之外的所有服务),有效载荷 将身体的SHA -256,和 `x-amz-security-token` 匹配临时证书. 证书的 `policyDocuments`当给定时,必须允许 `iot:Publish` 打开 `arn:aws:iot:<region>:<account>:topic/<topic>`。 。 。 .

### MQTT 数据

MQTT 5.0 在TCP和WebSocket上运行 `/mqtt` (副议定书) `mqtt`) (中文(简体) ). 都一样 各届会议和同一届会议 `Publish` 送货给.

| 区域 | 行为 |
| --- | --- |
| 认证 | 只自定义认证 . `authorizers` 使用 MQTT 用户名和密码( 用户名) 列出自定义授权者的结果 `?x-amz-customauthorizer-name=…` 查询读取或删除;或 通过 `authorizer` 改为 `createRuntime`,接收 Lambda 事件的函数(`protocolData.mqtt.{username, password (base64), clientId}`返回时 `{isAuthenticated, principalId, policyDocuments}`。没有匹配条目, `isAuthenticated: false`,或不允许 `iot:Connect` 打开 `client/<clientId>` 关闭 `0x87`。由于既没有配置每个客户端的连接,所以允许一切. |
| 政策 | `iot:Connect` 打开 `client/<id>`, (中文(简体) ), `iot:Publish` 财务报告和审定财务报表 `iot:Receive` 打开 `topic/<name>`, (中文(简体) ), `iot:Subscribe` 打开 `topicfilter/<filter>`默认拒绝; 明示 `Deny` 覆盖任意 `Allow`。 。 。 . `*` 财务报告和审定财务报表 `?` 为通配符( e)`*` ; MQTT 级别 `+` 财务报告和审定财务报表 `#` 在策略中是普通字符,所以策略必须给客户端订阅的过滤器命名. `${iot:ClientId}` 扩张。 一个否认的子公司是SUBACK `0x87`; 被拒绝的Qos 1 PUBLISH 是 PUBACK `0x87`; 无 `iot:Receive` 对于一个话题,默默地从它没有得到任何东西. |
| 结束 | 最大QoS 1, 保留可用 0 (见下文), 最大包大小 149504, Topy Alias 最大 8, 接受最大 100, Wildcard 订阅 可用 1, 订阅标识 可用 0, 共享订阅 可用 0. 服务器在 AWS 更改客户端时保持存活 : 1200 for `0` 或超过1200人,30人不满30人. |
| 常年会议 | Clean Start 0,会话间隔超过 0 。 间隔以账户配额为上限(`persistentSessionExpirySeconds`,默认1小时,最多7天),调整后的价值在CONNACK中返回. 一个会话只保留其订阅和QoS 1消息(QoS 0没有被存储). 连接结束时开始计时器; 到期时会话及其队列被丢弃 . |
| 客户端 ID | 最多128个字节( CONNACK) `0x85` 页:1 接受与连接客户端 ID 的第二个连接,并发送第一个 DICONNECT `0x8E`。 。 。 . |
| 专题 | 最多 256 字节和 7 前向斜线; 话题和过滤器开始 `$` 被拒绝(SUBACK) `0x8F`胶片 `0x90`) (中文(简体) ). `sensor/#` 匹配 `sensor/` 财务报告和审定财务报表 `sensor/a/b` 没有 `sensor`。 。 。 . |
| 基辅语Name | 0和1. 要求QoS 2的子公司得不到分包;QoS 2 PUBLISH被回答 `0x9B`。没有人订阅的刊物会被确认 `0x00`。 。 。 . |
| 有效载荷 | 最多128 KB;一个更大的PUBLISH断开客户端. |
| 订阅标识符 | 不支持,如关于AWS:DICONNECT `0xA1`。 。 。 . |

### 管理员(超过标准合同)

| 路线 | 效果 |
| --- | --- |
| `GET /__admin/publishes` | `{total, publishes}`: 接受的最后1000种出版物为元数据(`topic`, (中文(简体) ), `qos`, (中文(简体) ), `bytes`, (中文(简体) ), `source: "http" | "mqtt" | "admin"`, (中文(简体) ), `clientId`, (中文(简体) ), `matched`, (中文(简体) ), `at`) (中文(简体) ). 有效载荷从不保存. |
| `GET /__admin/clients`, (中文(简体) ), `GET /__admin/clients/:clientId` | 会话 : `connected`, (中文(简体) ), `transport`, (中文(简体) ), `sessionExpiryInterval`, (中文(简体) ), `expiresAt`,计数 `subscriptions`, (中文(简体) ), `queued`, (中文(简体) ), `inflight`; 其中一会还列出其 `topics`。 。 。 . |
| `GET /__admin/subscriptions?clientId=` | 订阅: `topicFilter`,准予 `qos`,选项. |
| `POST /__admin/inject` | `{topic, payload | payloadBase64, qos?: 0 | 1}`:向该话题的订阅者提供生字节,绕过签名,验证并发布政策(`iot:Receive` 页:1 用它来表示一个消费者的解析器必须拒绝。 答复 `{matched}`。 。 。 . |
| `POST /__admin/transport/cut` | `{clientId?}`:一个客户端或所有客户端的网络断电. 现场连接因没有DICONNECT而死亡,新的CONNECT被放弃,没有得到答复. 会话未受影响,按自己的时间安排过期. |
| `POST /__admin/transport/restore` | `{clientId?}`:结束停产. `GET /__admin/transport` 列出切出的内容. |
| `POST /__admin/clients/:clientId/disconnect` | `{reasonCode?}`: 发送 DICONNECT( 默认) `0x98`)和结束;会议将停止. |
| `GET` 编号 : `PUT /__admin/settings` | `{credentials?, authorizers?, region?, accountId?, persistentSessionExpirySeconds?}` 呼叫的命名空间。 无法评估的仿真文件被拒绝使用 `400`重置运行时间创建的值的返回. |
| `POST /__admin/clock` | 标准 移动时钟解决会话即时失效. |
| `POST /__admin/reset`检查站 | 标准 重置会降低每个连接和会话 。 恢复检查点会恢复会话,订阅和队列,并会减少直播连接. |

错误预设( E)`POST /__admin/faults {"preset": "<name>", "count"?: n}`· ; `GET /__admin/faults/presets`: `publish_throttled` (单位:千美元)`429 ThrottlingException`, (中文(简体) ), `publish_unauthorized` (单位:千美元)`401 UnauthorizedException`, (中文(简体) ), `publish_internal_failure` (单位:千美元)`500 InternalFailureException`, (中文(简体) ), `connect_not_authorized` (结束) `0x87`, (中文(简体) ), `connect_bad_credentials` (单位:千美元)`0x86`, (中文(简体) ), `connect_quota_exceeded` (单位:千美元)`0x97`) (中文(简体) ). CONNECT是故障操作 `MqttConnect`,所以任何原因 代码可以强制 : `{"operationId": "MqttConnect", "effect": "connack", "params": {"reasonCode": 137}}`。 。 。 .

### 命名空间

平行工人通过命名空间孤立自己. HTTP : (韩语) `x-mockingbird-namespace`页:1 `/__admin/ns/<name>` 前缀在终点,或通过访问密钥 id (单位:千美元)`PUT /__admin/credentials {"credentials": {"<AWS_ACCESS_KEY_ID>": "<namespace>"}}`(原始内容存档于2017-09-26). MQTT: the WebSocket URL 网络软件 `ws://…/__admin/ns/<name>/mqtt`,或由 CONNECT 键入的同一证书地图 用户名(没有查询字符串),然后是其客户端 ID。 未实现客户端使用默认值 名称空间.

### 未核实

文档不会解决这些问题; 模拟者的选择被声明为套房不会 给卖家弄错了

-   圆满之体. API的参考文献说 `Publish` 回答空正文; AWS 的自定义 认证教程显示 `{"message": "OK", "traceId": "…"}`。模拟器发送 后者,SDK忽略了这一点.
-   拒证. 未签名的请求或未验证仿真器的签名 答题 `403 {"message": "Forbidden", "traceId"}` 与 `x-amzn-ErrorType: ForbiddenException`数字 : 主体是拒绝的自定义授权签名的 AWS 文件、状态和 标题是推断的。 用于有效签名而无需 `iot:Publish` 它回答了文件 `401 UnauthorizedException`;无论AWS回答401还是403,都没有确认.
-   AWS 是否发送 `x-amzn-ErrorType`,则 `message` 每个文本 `400`,则 HTTP 错误 128 KB以上的有效载荷(模拟器用途) `400 InvalidRequestException`) (中文(简体) ).
-   "128 KB"和"146 KB"被取为131072和149504字节. AWS的MQTT页面也提到 最大包大小"不能超过128 KB";使用配额页146 KB.
-   客户所看到的 `isAuthenticated: false` (AWS说它"结束了连接"; 模拟器发送 CONNACK `0x87` 首先,对于一个超越限制范围或始于 `$` (AWS说此类操作"可以导致终止连接";模拟器回答 苏巴克 `0x8F` / 弹夹 `0x90` 并保持连接),以及超大小的MQTT有效载荷 (DISCONENECT 存档副本) `0x95`) (中文(简体) ).
-   一个QoS 2 子公司获得没有SUBACK是AWS的有记录的行为,在没有协议的情况下声明 版本;它被应用于已写入的 MQTT 5 .
-   当服务器保持生存时,接收最大值(100, 从未承认出版物配额中提取) 发送,指定客户端 ID 的格式,以及 Lambda 事件是否 `username` 包括查询字符串(模拟器将其剥去).
-   签名日期不与时钟相对照,所以套房可以冻结时间.

### 故意不模拟

-   MQTT 3.1和3.1.1(与该协议的回回码重用), TLS, X. 509 客户端 证书、 ALPN 和 SNI 以及 SigV4 指定的 WebSocket URL .
-   自定义对 HTTP 、 符号签名和 `disconnectAfterInSeconds` 编号 : `refreshAfterInSeconds` (接受,未执行).
-   政策 `Condition`, (中文(简体) ), `NotAction` 财务报告和审定财务报表 `NotResource` (拒绝使用这些文件)政策 变量 `${iot:ClientId}`,以及 `iot:RetainPublish`。 。 。 .
-   保留消息: CONNACK 表示保留可使用 0, 保留 MQTT 的发布被解答 分解系统 `0x9A`,以及 `retain=true` 超过HTTP是 `400`AWS本身支持它们.
-   将信件(收受于CONNECT,从未发布),共享订阅(SUBACK) `0x9E`, (中文(简体) ), 保留动态超时、消息过期、外出主题别名和保留 `$aws/…` 专题.
-   比率和计数配额(每秒publishes、每条连接或每条附属CRIBE、, 存储会话的每秒重放10个消息.
-   记录 阴影 规则和行动 工作 供给 其它数据平面 业务、账单和基础设施管理.

## API 密码

| 导出 | 仁爱 | 说明 |
| --- | --- | --- |
| `createRuntime` | 函数 | 服务合同的模拟者。 选项 : `settings`, (中文(简体) ), `authorizer`, (中文(简体) ), `clock`, (中文(简体) ), `seed`, (中文(简体) ), `adminPrefix`, (中文(简体) ), `adminKey`, (中文(简体) ), `onLog`, (中文(简体) ), `sqlite`添加 `attach(transport, info?, namespace?)` 为 MQTT 连接, `webSocketPath(pathname)`, (中文(简体) ), `endpoints`,以及 `stop()`。 。 。 . |
| `AwsIotAPI` | 类 | 一个命名空间 : `fetch(request)` 页:1 `Publish`, (中文(简体) ), `broker` 为MQTT, `state`, (中文(简体) ), `reset()`选项: `sqlite`, (中文(简体) ), `now`, (中文(简体) ), `namespace`, (中文(简体) ), `settings`, (中文(简体) ), `authorizer`, (中文(简体) ), `connectFault`。 。 。 . |
| `AWS_IOT_PRESETS` | 对象 | 每个命名的断层预设. |
| `AWS_IOT_NAMESPACE` | 字符串 | 服务名称, `"aws-iot"`。 。 。 . |
| `SIGNING_NAME` | 字符串 | `"iotdata"`,SigV4签名名称. |
| `MQTT_CONNECT_OPERATION`, (中文(简体) ), `MQTT_WEBSOCKET_PATH` | 字符串 | `"MqttConnect"`(一) 操作id出错规则用于CONNECT;以及 `"/mqtt"`。 。 。 . |
| `MAX_PAYLOAD_BYTES`, (中文(简体) ), `MAX_PACKET_SIZE`, (中文(简体) ), `MAX_TOPIC_BYTES`, (中文(简体) ), `MAX_TOPIC_SLASHES`, (中文(简体) ), `MAX_CLIENT_ID_BYTES`, (中文(简体) ), `MAX_MESSAGE_EXPIRY_SECONDS`, (中文(简体) ), `MAX_PERSISTENT_SESSION_EXPIRY_SECONDS`, (中文(简体) ), `KEEP_ALIVE_RANGE` | 数字 | AWS IOT Core的极限是模拟器执行的. |
| `DEFAULT_SETTINGS` | 对象 | 地区 `us-east-1`账户 `123456789012`,无证书或授权人,1小时会议配额. |
| `parseSettings` | 函数 | 验证 JSON 的设置补丁; 丢出错误字段的命名 . |
| `parsePolicyDocument`, (中文(简体) ), `isAllowed`, (中文(简体) ), `resourceArn`, (中文(简体) ), `PolicyError` | 函数,类 | 分析一个政策文件(对象或JSON字符串),对它进行动作和目标评价,并构建 ARN 以检查动作. |
| `accessKeyCredential`, (中文(简体) ), `splitUsername` | 函数 | 已签名请求的存取密钥 ID; MQTT 用户名和授权方的查询字符串名( 如何将权限映射到命名空间) . |
| `ReasonCode` | 对象 | MQTT 5 名下理性码. |
| `document`, (中文(简体) ), `operationIds`, (中文(简体) ), `supportedOperationIds` | 数值 | HTTP合同及其操作代号. |
| `createServer`, (中文(简体) ), `connectStream`, (中文(简体) ), `loadSettingsFile`, (中文(简体) ), `serveTarget`, (中文(简体) ), `DEFAULT_PORT`, (中文(简体) ), `DEFAULT_MQTT_PORT` (单位:千美元)`./server`(中文(简体) ) | 节点 | 服务HTTP、WebSocket和TCP`{url, mqttUrl, mqttPort, wsUrl, runtime, close()}`; 选项添加 `port`, (中文(简体) ), `mqttPort`, (中文(简体) ), `host`, (中文(简体) ), `sweepMs`; 正在处理的 MQTT 流; 读取 `--settings` 文件; 该 `serve` CLI目标;港口8851和8883. |

部分 [嘲笑鸟](https://github.com/crvouga/mockingbird)。 。 。 .

## 常见问题

### @crvouga/mockingbird-service-aws-iot 是什么？

AWS IoT Core Data平面的状态仿真器:由SigV4签名的HTTP Publishing和由TCP和WebSocket负责的MQTT 5消息经纪人,有自定义授权政策和持续会话\.

### 如何安装 @crvouga/mockingbird-service-aws-iot？

在项目目录运行 npm install @crvouga/mockingbird-service-aws-iot，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 mockingbird-aws-iot，可以用 npx mockingbird-aws-iot 直接运行。

### @crvouga/mockingbird-service-aws-iot 支持 TypeScript 吗？

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

### @crvouga/mockingbird-service-aws-iot 支持 ESM 还是 CommonJS？

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

### @crvouga/mockingbird-service-aws-iot 可以商用吗？

@crvouga/mockingbird-service-aws-iot 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @crvouga/mockingbird-service-aws-iot 的下载量有多少？

根据 npm 官方下载统计，@crvouga/mockingbird-service-aws-iot 在 2026/10/11 – 2026/11/09 这 30 天内被下载 3,002 次，日均约 100 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @crvouga/mockingbird-service-aws-iot 还在维护吗？

最新版本 0\.10\.0 发布于 2026/11/11（今天）；至今共发布 19 个版本，其中过去 12 个月发布了 19 个；首次发布于 2026/10/11。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

