# @crvouga/mockingbird-service-garmin-health 中文文档

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

版本：0\.4\.0
npm 元数据更新时间：2026-11-11T02:14:37.975Z
中文译文更新时间：2026-11-11T09:54:54.038Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：4.3 MB，18 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：2 个
- 首次发布：2026-10-21T17:03:18.074Z
- 最新版本发布：2026-11-11T02:14:37.659Z
- 近 30 天下载量：2326（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：14（近 12 个月 14 个）

## 中文简介

州立加明健康模拟器:OAuth PKCE,回填请求,推和ping webhoks并注销注册.

## 安装

```sh
npm install @crvouga/mockingbird-service-garmin-health
```

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

## README

# @crvouga/mockingbird-service-garmin-健康(英语:

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

WIP Garmin Connect 开发者程序健康API模拟器用于计划同步流:OAuth 2.0与PKCE,用户代号,回填请求(每类型和窗口一次),推并按下交付给您的应用程序的网络hooks,并注销对合成数据的注册. Garmin的端点规格在经过批准的-开发者门户网站后方,因此每条有线细节都是一份真正的消费者发送和剖析的合同(问题#545),而不是供应商验证. 见 [证据和最佳猜测](https://npmcn.com/package/%40crvouga/mockingbird-service-garmin-health/#readme-evidence-and-best-guesses)。 。 。 .

## 安装

`bun add @crvouga/mockingbird-service-garmin-health`

## 使用量

```ts
import { createServer } from "@crvouga/mockingbird-service-garmin-health/server"

// Test setup: a local Garmin. One origin serves the API, token and consent routes, so it replaces
// https://apis.garmin.com, https://diauth.garmin.com and https://connect.garmin.com in the app. The
// emulator posts webhooks to your receiver, so tell it your webhook base URL.
const server = await createServer({
  webhooks: { baseUrl: "http://localhost:8000/api/v1/garmin/webhooks", clientId: "my-client-id" },
})
const garmin = server.url

// Application code: the requests it sends to Garmin (default user garmin-user-1 and its token).
const headers = { authorization: "Bearer mock_garmin_token", accept: "application/json" }
const me = (await (await fetch(`${garmin}/wellness-api/rest/user/id`, { headers })).json()) as {
  userId: string
}
const day = 1767225600 // 2026-01-01T00:00:00Z
const backfill = await fetch(
  `${garmin}/wellness-api/rest/backfill/sleeps?summaryStartTimeInSeconds=${day}&summaryEndTimeInSeconds=${day + 86400}`,
  { headers },
)
// 202 with an empty body; a POST to http://localhost:8000/api/v1/garmin/webhooks/push follows.
console.log(me.userId, backfill.status)

await server.close()
```

运行 `mockingbird-garmin-health serve --port 12131 --webhook-base-url http://localhost:8000/api/v1/garmin/webhooks`. Garmin没有发布公众JS SDK,消费者使用生HTTP:指其API出处,符号URL并授权URL(三个设置)在模拟器出处. 浏览器在 HTTP 上到达同意页面, 因此使用已服务仿真器而不是在进程内 `fetch` 为那一步. 无 `--webhook-base-url` 任何物品都无法交付,直到 `PUT /__admin/webhook-base-url` 设一.

## 路线

| 路线 | 它会做什么 |
| --- | --- |
| `GET /oauth2Confirm` | 同意页`https://connect.garmin.com/oauth2Confirm` (关于供应商)。 需求 `response_type=code`, (中文(简体) ), `client_id`, (中文(简体) ), `redirect_uri`, (中文(简体) ), `code_challenge` 财务报告和审定财务报表 `code_challenge_method=S256`· ; `state` 是可选的,并重复;否 `scope`重新编号(302) `redirect_uri?code=<code>&state=<state>`,或 `?error=access_denied&error_description=...&state=...` 当 `denyConsent` 设置开始。 未知客户端或未注册的重定向 URI 从未被重定向到 (400) `invalid_request`) (中文(简体) ). |
| `POST /di-oauth2-service/oauth/token` | 表格机构、机构内的客户证书`client_id`, (中文(简体) ), `client_secret`;基本内容也被接受). `authorization_code` (与 `redirect_uri` 财务报告和审定财务报表 `code_verifier`和 `refresh_token` 赠款。 答复 200 `access_token`, (中文(简体) ), `token_type: "bearer"`, (中文(简体) ), `expires_in` (整数秒), `refresh_token`。重复使用或过期的代码、错误的核查者或错误 `redirect_uri` 为 400 `invalid_grant`; 不良客户资格 400 `invalid_client` (401与Basic;不明、已退休或已注销登记的新订证券400) `invalid_grant`。 。 。 . |
| `GET /wellness-api/rest/user/id` | `{ "userId": "<id>" }` 为无记名符号背后的用户. |
| `GET /wellness-api/rest/backfill/{type}` | `type` 实值 `activities`, (中文(简体) ), `sleeps`, (中文(简体) ), `dailies`, (中文(简体) ), `epochs`, (中文(简体) ), `bodyComps` 或者说 `hrv`· ; `summaryStartTimeInSeconds` 财务报告和审定财务报表 `summaryEndTimeInSeconds` 是整数秒(启动后结束,最多相隔90天)。 202 有一具空躯. 同一用户,类型和窗口又是409. 未知型号为404,坏界为400. |
| `DELETE /wellness-api/rest/user/registration` | 204,没有尸体。 用户的每个符号,然后回答401,刷新符号是 `invalid_grant`。 。 。 . |
| `GET /wellness-api/rest/{type}?uploadStartTimeInSeconds=&uploadEndTimeInSeconds=&token=` | 这个 `callbackURL` 电话通知。 由其认证 `token` 查询参数,而不是由标题; 200 带有 JSON 摘要阵列, 401 表示未知的符号、另一种类型或已注销的用户. |

API 拨打无记名信使,或无记名信使,过期(在模拟时钟上)或注销注册,回答401 `{"error":"unauthorized","message":...}`。授权代码为单用并持续了10分钟;访问符号为最后 `tokenTtlSeconds` (默认86400)在模拟器时钟上;刷新会旋转刷新符并让旧符退休(`rotateRefreshTokens: false` 保持它,省略 `refresh_token` 从反应,所以消费者保留了旧的。 失败的交换( 错误的校验或重定向 URI) 不消耗代码 。 默认客户端是 `mock_garmin_client` 编号 : `mock_garmin_secret` (任何方向调整的URI,除非 `clients[].redirectUris` ;默认用户是 `garmin-user-1` 无记名者 `mock_garmin_token` 并刷新标志 `mock_garmin_refresh`直到2100年时钟结束.

## 后补和交货

每个用户、类型和窗口(起止秒)接受回填。 当它被接受时, 模拟器会选择用户的种子摘要 `[start, end)` (单位:千美元)`startTimeInSeconds`,或 `measurementTimeInSeconds` 页:1 `bodyComps`),并按照用户的 `delivery` 模式 :

-   **推动** (默认) : `POST <baseUrl>/push` 与 `{ "<type>": [ { "userId": ..., ...summary } ] }`,摘要与种子加 `userId`。 。 。 .
-   **ing**数字 : `POST <baseUrl>/ping` 与 `{ "<type>": [ { "userId": ..., "callbackURL": "<emulator origin>/wellness-api/rest/<type>?uploadStartTimeInSeconds=S&uploadEndTimeInSeconds=E&token=<token>" } ] }`复选需要取消 `Authorization` 头并服务与 JSON 阵列相同的摘要 。 在命名空间中, URL 携带 `/__admin/ns/<name>` 因此,它达到了正确的数据 没有标题。 这个 `publicUrl` 设置取代消费者在另一个地址到达模拟器时的源头,而不是回填调用.

每一次送货都带着 `garmin-client-id` 页眉( `clientId` 选项,默认 `mock_garmin_client`无签名。 没有种子摘要的窗口仍然是202个,没有交付;窗口按要求计算。 默认种子给出 `garmin-user-1` 2026-01-01(UTC)上各有1个类型汇总;上方的第一个窗口覆盖了全部. 摘要为通过:一项活动没有种子 `durationInSeconds` 由消费者决定怎么做.

Webhook 路径 `/push`, (中文(简体) ), `/ping`, (中文(简体) ), `/deregistration` 财务报告和审定财务报表 `/permissions` 在基准 URL 下 (`paths` 覆盖每个). 标准 Webhook 枢机运行送货:在非-2xx 答案上用默认的后退来重试(`retryDelaysMs` 改变它, `GET /__admin/webhooks` \* 列出每批交货的状态(`delivered`, (中文(简体) ), `failed`, (中文(简体) ), `dropped`和接收器的状态 每一次尝试, `GET /__admin/webhooks/events` 这些尸体, `POST /__admin/webhooks/:id/replay` 财务报告和审定财务报表 `/webhooks/flush` 重新运行它们.

## 测试控制

种子与 `createRuntime`编号 :`createServer` 选项(`users`, (中文(简体) ), `clients`, (中文(简体) ), `grants`, (中文(简体) ), `codes`, (中文(简体) ), `summaries`, (中文(简体) ), `settings`, (中文(简体) ), `webhooks`)或以下管理路线(相对于 `/__admin`,可通过 `adminPrefix`:

| 管理路线 | 对 |
| --- | --- |
| `GET`编号 :`PUT /settings` | `autoDeliver` (虚假持有接受的通知), `denyConsent`, (中文(简体) ), `consentUserId` (谁将同意页的符号输入;默认第一个用户), `rotateRefreshTokens`, (中文(简体) ), `tokenTtlSeconds`, (中文(简体) ), `publicUrl`。 。 。 . |
| `GET`编号 :`PUT /users` | 列表,或添加或替换 `{ userId, delivery: "push" | "ping", registered?, permissions? }`。 。 。 . |
| `PUT /summaries` | 种子 `[{ userId, type, data, key? }]`。 。 。 . `data` 需求 `startTimeInSeconds` (单位:千美元)`measurementTimeInSeconds` 页:1 `bodyComps`); 重复 `key` 替换. |
| `GET /backfills` | 接收回填请求的历史和通知(编号、类型、模式、, `pending`, (中文(简体) ), `sent` 或者说 `dropped`,项目计数;绝不是尸体. |
| `POST /notifications/deliver` `{ ids? }` 编号 : `POST /notifications/drop` `{ ids? }` | 发送或永远不发送持有的通知(全部或所命名的通知). |
| `PUT /webhook-base-url` `{ baseUrl, clientId?, paths? }` | 设置命名空间的 Webhook 端点 。 启动时设定的终点( E)`webhooks.baseUrl`, (中文(简体) ), `--webhook-base-url`)服务于每个取名空间并保留;这些被添加. |
| `POST /users/:userId/deregister` | 在 Garmin Connect 中切断用户的功能:他们的代号停止工作 `POST <baseUrl>/deregistration` 携带 `{ "deregistrations": [ { "userId", "userAccessToken" } ] }`。 。 。 . |
| `POST /users/:userId/permissions` `{ permissions: { "<name>": boolean } }` | 合并用户权限 `POST <baseUrl>/permissions` 与 `{ "userPermissionsChange": [ { "userId", "permissions" } ] }`。 。 。 . |
| `POST /users/:userId/expire-token` `{ revokeRefresh? }` | 在不移动时钟的情况下过期用户的访问符; `revokeRefresh` 还退休 刷新符号. |

`POST /clock {"advance": "2h"}` 移动命名空间时钟:访问比 `expires_in` 然后回答401, 超过10分钟的代码被拒绝。 标准 `/__admin/health`, (中文(简体) ), `/state` (会费) `users`, (中文(简体) ), `clients`, (中文(简体) ), `grants`, (中文(简体) ), `codes`, (中文(简体) ), `summaries`, (中文(简体) ), `backfills`, (中文(简体) ), `notifications`, (中文(简体) ), `callbacks`, (中文(简体) ), `settings`, (中文(简体) ), `/reset`, (中文(简体) ), `/requests`,有时间线检查站和故障。 标题 `x-mockingbird-namespace`, (中文(简体) ), `/__admin/ns/<name>` 路径和证书映射(承接符)将每个命名空间的用户、摘要、符号和回填历史隔离。 期刊中包含元数据,从不摘要或符号.

预设`POST /__admin/faults {"preset": "<name>", "count": n}`: `unauthorized` (卫生API 401), `conflict` (回填409个), `rate_limited` (429处) `Retry-After: 1`, (中文(简体) ), `server_error` (500个), `refresh_rejected` (端点400) `invalid_grant`, (中文(简体) ), `connection_drop` (回填下套接字),和webhook模式 `duplicate`, (中文(简体) ), `webhook_drop` 财务报告和审定财务报表 `webhook_reorder` (下一次交货是两次发送,从未发送,或与之后的一次互换). 预设体是被脚本固定的.

## 证据和最佳猜测

健康API需要一个经批准的开发商账户, 来源是第545期(消费者寄送和剖析的内容)中的消毒线和概览 [https://developer.garmin.com/gc-developer-program/health-api/ 互联网档案馆的存檔,存档日期2013-12-21](https://developer.garmin.com/gc-developer-program/health-api/)。下面的一切都是一个 **最好猜,不是甲骨文验证**,跟踪为 `needs-oracle-check`数字 :

-   同意重定向形状和PKCE检查(仅S256,一个43至128字符核查器,单用10分钟代码,一个无法使用代码的交换);
-   400个 `invalid_grant` 重新使用的代码、错误的验证器、错误的重新定向URI和一个未知或已退役的刷新符,以及400 `invalid_client` (a) 不良证书(该期说400或401是一个被拒绝的刷新令牌);
-   刷新键旋转( 默认; 旋转设置存在, 因为不知道供应商的行为) 和 `token_type: "bearer"`· ;
-   用户 id 形状 (`garmin-user-1`;真实的id是不透明的)和 `expires_in` \* 86400;
-   202 带有被接受回填的空正文, 409 为重复类型和窗口(密钥为用户,类型,始末),90天窗口盖有400个,404为未知类型,JSON出错正文 `{"error","message"}`· ;
-   a. 一个空窗口,回答202,但无所提供(问题留下“不交付或空交付”);
-   其中摘要选择窗口(`[start, end)` 在摘要本身的开始时间, `measurementTimeInSeconds` (a) 每件接受回填一次,按其类型键归类;
-   429个尸体和 `Retry-After` 标题,401机构,和204,删除登记(该问题只需要成功状态);
-   交货没有签名,只有 `garmin-client-id`,并重试非-2xx答案的政策(枢纽的标准后退);
-   铃声 `callbackURL` 形状,其符号是唯一的认证,并且该符号在用户取消注册之前仍然重复请求.

如果问题和供应商文件可能不同,模拟者就沿着问题的线走.

## 甲骨文和测试

`bun test` 运行接受测试(服务请求的每个编号行为一次,通过 `test/consumer.ts`,是消费者的 httpx 供应商级和 FastAPI 接收器的端口,其中Webhook 枢接器向接收器发送并超过一个已服务过的 HTTP 槽),并且每一次操作都具有分解检测的自平. `bun run parity` 需求 `GARMIN_HEALTH_ACCESS_TOKEN`,只执行保险箱 `user/id` ,并永远不要打印标识符或证书。 后补,去注册和网络呼喊 并不是运行对加明.

## 故意不模拟

下方的拉出点 `/wellness-api/rest/{type}?uploadStartTimeInSeconds=...&token=...` 作为被调查的读取路径( 仅限平声) `callbackURL` ),牵引电源生成,活动细节,压力,呼吸,脉冲-牛,皮肤温度,血压,MoveIQ和所有其他回填类型,Garmin Connection(非健康)APIs,更古老的OAuth 1.0a流量,同意UI(同意由决定) `denyConsent` 设定和浏览器仅被重定向), 跨范围同意和开发者门户的固定范围, 权限执行(仅宣布许可变更), 费率限制核算和供应商的回填配额 超出每个类型和窗口一个请求(限制仅通过预设来脚本), webhook 认证超出 `garmin-client-id` 页: 1.

## API 密码

根运行时间导出 : `GarminHealthAPI`, (中文(简体) ), `GARMIN_HEALTH_NAMESPACE`, (中文(简体) ), `SUMMARY_TYPES`, (中文(简体) ), `MAX_BACKFILL_SECONDS`, (中文(简体) ), `isSummaryType`, (中文(简体) ), `summaryTime`, (中文(简体) ), `createRuntime`, (中文(简体) ), `GARMIN_HEALTH_PRESETS`, (中文(简体) ), `WEBHOOK_PATHS`, (中文(简体) ), `webhookEndpoints`, (中文(简体) ), `document`, (中文(简体) ), `operationIds`, (中文(简体) ), `supportedOperationIds`类型包括: `GarminHealthAPIOptions`, (中文(简体) ), `GarminUser`, (中文(简体) ), `DeliveryMode`, (中文(简体) ), `Client`, (中文(简体) ), `Grant`, (中文(简体) ), `OAuthCode`, (中文(简体) ), `Summary`, (中文(简体) ), `SummarySeed`, (中文(简体) ), `SummaryType`, (中文(简体) ), `BackfillRecord`, (中文(简体) ), `Notification`, (中文(简体) ), `CallbackToken`, (中文(简体) ), `Settings`, (中文(简体) ), `GarminWebhookEvent`, (中文(简体) ), `GarminHealthRuntimeOptions`, (中文(简体) ), `GarminHealthRuntime`, (中文(简体) ), `GarminHealthWebhooks`, (中文(简体) ), `OperationId`, (中文(简体) ), `SupportedOperationId`。 。 。 .

`/server` 出口 `createServer`, (中文(简体) ), `serveTarget`, (中文(简体) ), `DEFAULT_PORT` 类型 `GarminHealthServerOptions`, (中文(简体) ), `GarminHealthServer`。 。 。 .

## 常见问题

### @crvouga/mockingbird-service-garmin-health 是什么？

州立加明健康模拟器:OAuth PKCE,回填请求,推和ping webhoks并注销注册\.

### 如何安装 @crvouga/mockingbird-service-garmin-health？

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

### @crvouga/mockingbird-service-garmin-health 支持 TypeScript 吗？

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

### @crvouga/mockingbird-service-garmin-health 支持 ESM 还是 CommonJS？

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

### @crvouga/mockingbird-service-garmin-health 可以商用吗？

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

### @crvouga/mockingbird-service-garmin-health 的下载量有多少？

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

### @crvouga/mockingbird-service-garmin-health 还在维护吗？

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

