# @clearly-hub/node 中文文档

规范地址：https://npmcn.com/package/%40clearly-hub/node/

版本：0\.12\.0
npm 元数据更新时间：2026-10-29T18:31:54.591Z
中文译文更新时间：2026-11-10T00:54:30.497Z
软件包许可：SEE LICENSE IN LICENSE

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

原始 npm 页面：https://www.npmjs.com/package/%40clearly-hub/node
原文对照：https://npmcn.com/package/%40clearly-hub/node/?lang=original

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

- 包体积（解压后）：152 kB，7 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=24
- 运行依赖：2 个
- 首次发布：2026-10-22T11:40:20.444Z
- 最新版本发布：2026-10-29T18:31:54.373Z
- 近 30 天下载量：3224（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：18（近 12 个月 18 个）

## 中文简介

显然 节点服务器的HUB:登录、主机屏幕、订阅和一个处理器的使用

## 安装

```sh
npm install @clearly-hub/node
```

也可以使用：`pnpm add @clearly-hub/node`、`yarn add @clearly-hub/node`、`bun add @clearly-hub/node`

## README

# 很明显 HUB SDK

连接您的网络应用到明显 。 HUB有脚本,一些配置和一个服务器处理器. 你会得到 "与明显相签. HUB),主机屏幕(选择一个计划,选择数据,保存结果,选择一个 每个中心都订阅你的应用软件 刷新符号留在您的服务器上; 页面获得 访问符只在它要求保护数据时才使用.

> **预览 (0.x).** API仍然可能在小版本之间有所改变. 专有: 见 [自由主义](https://npmcn.com/package/%40clearly-hub/node/LICENSE)。 。 。 .

## 快开始

**1\. 明确注册您的应用程序。 汉字** (在你的应用页面上,没有代码):

| 设置 | 数值 |
| --- | --- |
| 转到应用程序 | `https://app.example.com/clearly-hub/sign-in` |
| 签名客户端 (H2M): 回调 URL | `https://app.example.com/clearly-hub/callback`, (中文(简体) ), `https://app.example.com/clearly-hub/answer`, (中文(简体) ), `https://hub.clearly.app/components` |
| 签名客户端: 签名退出 URL | `https://app.example.com`, (中文(简体) ), `https://hub.clearly.app/components` |
| M2M 客户端 | 创建它, 保留服务器上的秘密 |
| 计划 | 给每个你自己的计划 id作为它的 _外部参考_,例如 `pro` |

**2\. 挂载服务器处理器** (节点24+):

```js
import express from 'express';
import { clearlyHub } from '@clearly-hub/node';

const hub = clearlyHub({
  clientId: process.env.CLEARLY_HUB_CLIENT_ID,
  m2mClientId: process.env.CLEARLY_HUB_M2M_CLIENT_ID,
  m2mClientSecret: process.env.CLEARLY_HUB_M2M_CLIENT_SECRET,
  appId: process.env.CLEARLY_HUB_APP_ID, // your app's id in Clearly.HUB
  appUrl: 'https://app.example.com',
  secret: process.env.SESSION_SECRET, // 32+ random characters
});

const app = express();
app.use('/clearly-hub', hub.express());
```

不是快递? `hub.handler` 使用一个 `Request` 返回 a `Response`,对于Next.js的路由处理器, 霍诺 邦或德诺 装入 `/clearly-hub/*`。 。 。 .

**3\. 添加脚本和一个按钮:**

```html
<!-- @0.1: follows 0.1.x fixes, not a breaking 0.2 -->
<script src="https://cdn.jsdelivr.net/npm/@clearly-hub/browser@0.1/dist/clearly-hub.js"></script>

<clearly-hub-button action="sign-in"></clearly-hub-button>
<clearly-hub-button action="SELECT_DATA"></clearly-hub-button>

<script type="module">
  const session = await clearlyHub.session(); // { signedIn, user }
  window.addEventListener('clearly-hub-answer', (event) =>
    console.log(event.detail),
  );
</script>
```

或者说 `npm install @clearly-hub/browser` 财务报告和审定财务报表 `import { clearlyHub } from '@clearly-hub/browser'`中添加 `import '@clearly-hub/browser/react'` 有一次,所以JSX知道 `<clearly-hub-button>`。 。 。 .

## 浏览器软件包

|  |  |
| --- | --- |
| `clearlyHub.session()` | `{ signedIn: false }`,或签名用户(`sub`, (中文(简体) ), `email`, (中文(简体) ), `name`, (中文(简体) ), `appUserId`(中文(简体) ) |
| `clearlyHub.signIn()`, (中文(简体) ), `signOut()` | 明显地通过。 HUB 回到这页 |
| `clearlyHub.signIn({ display: 'popup' })` | 以弹出方式签名; 此页面保留 。 决定开会。 也联系一个明显。 HUB 账户给您自己登录的人 |
| `clearlyHub.open(action, { data, display })` | 打开主机屏幕;用它选中的答案解决。 通过点击调用它: 浏览器只允许弹出到那里 |
| `clearlyHub.result()` | 在重新定向的屏幕之后:它的答案,在页面上它回到 |
| `clearlyHub.getToken()` | 该人受保护和付费数据的钥匙,或 `null` 签了字后 见 [受保护数据](https://npmcn.com/package/%40clearly-hub/node/#readme-protected-data) |
| `clearlyHub.onAnswer(callback)` | 每一个回答,一次从弹出,一次从回转后;也可以在回转后开始听(React). 返回停止监听的函数 |
| `<clearly-hub-button action display data label>` | 标记按钮 `sign-in`, (中文(简体) ), `sign-out` 每个屏幕 |
| `clearly-hub-answer` 事件 | 每一个答案,从弹出 或经过方向调整 |
| `clearly-hub-sign-in` 事件 | 签入的弹出完成; `detail` 是会话 |

**搭接按钮.** 它用你的页面字体。 普通案件属性: `variant="outline"`, (中文(简体) ), `size="small"` 或者说 `size="large"`。 CSS 自定义属性用于您的外观 : `--clearly-hub-color`, (中文(简体) ), `--clearly-hub-text-color`, (中文(简体) ), `--clearly-hub-radius`, (中文(简体) ), `--clearly-hub-padding`, (中文(简体) ), `--clearly-hub-font`。对于其它任何问题,请将真实的按钮通过 `::part(button)`数字 :

```css
clearly-hub-button {
  --clearly-hub-color: #0b7471;
  --clearly-hub-radius: 999px;
}
clearly-hub-button::part(button) {
  text-transform: uppercase;
}
```

默认在弹出时打开屏幕( S)`data-display="redirect"` 或者说 `"iframe"` 在脚本标签上 修改。 被堵住的弹出会回到方向.

**在您页面上的对话框中** (单位:千美元)`display: 'iframe'`: 屏幕显示在中央对话框中并使用 在你的应用软件上签名的人, 所以它不签名本身, Google Drive 拾取器的方式 工作时 弹出也一样 很明显没人和他签约 你的应用程序的签到 首先(一个弹出,在同一个窗口)。 需要一个明显的。 汉字 释放允许此选项( 预览) 。 如果你的应用程序有自己的CSP: `frame-src https://hub.clearly.app`。 。 。 . 以 `--clearly-hub-frame-width`, (中文(简体) ), `--clearly-hub-frame-height`, (中文(简体) ), `--clearly-hub-backdrop`,或 `clearly-hub-frame::part(dialog | iframe | close)`。 。 。 .

| 行动 | 报到 `data` | `answer` 何时 `result` 实值 `SUCCESS` |
| --- | --- | --- |
| `SELECT_SUBSCRIPTION` |  | `subscription` (单位:千美元)`_id`, (中文(简体) ), `externalReference` 你的计划id, `subscribedHub` (单位:千美元)`_id`, (中文(简体) ), `name`, (中文(简体) ), `hasMultipleSubscriptions` |
| `SELECT_DATA` | 可选择 `{ formats: ['geojson', 'wms'] }` 只提供这些 | `activeHub` (单位:千美元)`_id`, (中文(简体) ), `name`, (中文(简体) ), `resources` (单位:千美元)`datasetId`, (中文(简体) ), `datasetTitle`, (中文(简体) ), `resourceId`, (中文(简体) ), `resourceName`, (中文(简体) ), `url`, (中文(简体) ), `format`, (中文(简体) ), `accessibility`, (中文(简体) ), `requiresToken`, (中文(简体) ), `hasAccess`(中文(简体) ) |
| `REGISTER_RESOURCE` | `{ url, format }` 在公开的 https URL 中 | `activeHub` (呼号), `dataset` (单位:千美元)`datasetId`, (中文(简体) ), `datasetTitle`, (中文(简体) ), `resource` (单位:千美元)`resourceId`, (中文(简体) ), `resourceName`(中文(简体) ) |
| `SELECT_HUB` |  | `hub` (单位:千美元)`_id`, (中文(简体) ), `name`(中文(简体) ) |
| `SELECT_DIGITAL_TWIN` |  | `activeHub` (单位:千美元)`_id`, (中文(简体) ), `name`, (中文(简体) ), `digitalTwin` (单位:千美元)`_id`, (中文(简体) ), `title`, (中文(简体) ), `description`, (中文(简体) ), `previewImage`, (中文(简体) ), `ownerHub`, (中文(简体) ), `findability`, (中文(简体) ), `viewerUrl`, (中文(简体) ), `resources` 与 `SELECT_DATA` 加号 `selected` 财务报告和审定财务报表 `subLayers` (单位:千美元)`name`, (中文(简体) ), `selected`页:1 |

每一个答案都有 `user` (单位:千美元)`_id`, (中文(简体) ), `email`他回答说:这是明显的。 嘘。 内容 `_id` 这是 个人的 `sub`,与 `session().user.sub`。 。 。 .

## 受保护数据

受保护或付费的资源 `SELECT_DATA` (单位:千美元)`requiresToken: true`拥有一个 `url` 显然。 汉伯, 检查每个人的钥匙 发作吧 `Authorization` 头曰. 页面中:

```js
const response = await fetch(resource.url, {
  headers: { Authorization: await clearlyHub.getToken() },
});
```

映射层( WMS, WMTS, 瓦片) 载入许多 URL 本身: 使用 Leaflet, OpenLayers 或 Cesium 选项 或添加每个请求头的插件。 钥匙持续一小时; `getToken()` 换个新的 时间,所以调用它 而不是保留价值。 在你的服务器上, `hub.fetchAsUser(req, url)` 做同样的.

关键是那个人自己 HUB 密钥: 只发送到资源 URL `SELECT_DATA` (清净. HUB的车 数据代理),并保留您不信任的脚本出自使用它的页面. `fetchAsUser` 拒绝其它 URL .

## 节点软件包

|  |  |
| --- | --- |
| `hub.express()`, (中文(简体) ), `hub.handler` | 路线: `/sign-in`, (中文(简体) ), `/callback`, (中文(简体) ), `/sign-out`, (中文(简体) ), `/session`, (中文(简体) ), `/open`, (中文(简体) ), `/answer`, (中文(简体) ), `/result`, (中文(简体) ), `/token` |
| `onSignIn(person, { request, req })` | 每签入后即召入. 返回自己的用户ID以保留在会话中,或 `{ appUserId, redirectTo }` 选择下一页 |
| `onAnswer(result, { user, data, request, req })` | 在访问浏览器前使用每个检查的答案调用, 例如要设置工作空间 . `data` 屏幕是被发送的;返回的屏幕是 `result.app` |
| `hub.getUser(req)` | 谁签的,在自己的路线 |
| `hub.fetchAsUser(req, url)` | 获取受保护或付费数据(从 `SELECT_DATA`)在你的服务器上,带有人物的钥匙. 只有URL在明显。 HUB 的数据代理 |
| `hub.getSubscription(hubId)`, (中文(简体) ), `getSubscriptions()` | 中心订阅了你的应用软件,或者全部 |
| `hub.getUserContext(req)` | 签字人所在的签字中心及其作用(第2条)`ADMIN` 或者说 `MEMBER`和计划; `null` 当没有人签名时 |
| `hub.reportUsage({ request or sub, hubId, quantity })` | (b) 报告可收取费用的用途; HUB给枢纽开账单. 过 `sub` 很明显 你存储的HUB账户,没有直播登录 |
| `hub.datasets`, (中文(简体) ), `hub.resources`, (中文(简体) ), `hub.authMethods` | 将数据登记在中枢, 作为签名人或您的应用程序; 参见 [登记数据](https://npmcn.com/package/%40clearly-hub/node/#readme-registering-data) |
| `hub.getProxyContext(req, { audience })` | 在API后面显然。 HUB 数据代理:谁打电话(`sub`, (中文(简体) ), `subType`),用于哪个中枢,与哪个角色,以及订阅. `null` 没有代理标题; 见 [在数据代理服务器后面](https://npmcn.com/package/%40clearly-hub/node/#readme-behind-the-data-proxy) |
| `hub.getUserToken(req)`, (中文(简体) ), `getAppToken()` | 那个人的钥匙和你的应用软件的钥匙 你自己的电话 |

### 在数据代理服务器后面

当你的API是一个受保护的资源,很明显。 HUB 的数据代理可以告诉它谁打电话:它增加了一个 `x-oup-context` 信头,一个JWT与明显签署。 HUB的钥匙. `getProxyContext` 检查签名, 期满,并 `audience` (您的资源 id), 用于此资源:

```ts
app.get('/api/flood-depth', async (req, res) => {
  const context = await hub.getProxyContext(req, { audience: resourceId });
  if (!context) return res.sendStatus(401);
  if (context.hub.role !== 'ADMIN') return res.sendStatus(403);
  // context.sub, context.subscription?.id, context.activeHub, ...
});
```

它扔一个 `ClearlyHubError` 有代码 `invalid-context` 当信头在那里,但没有 核实.

**信头只证明如果请求真的通过代理发送,谁会打电话.** 检查 代理机本身的秘密, 资源认证方法( 例如 `CUSTOM_HEADER`),或 仅接受代理机的流量。 代理删除一个 `x-oup-context` 一个客户自己送的. 现在代理只在资源认证方法有时才会添加标题 `forwardSubscriptionId` 继续.

**你自己在钩子上.** 与 `hub.express()`钩子得到快递 `req` 作为 `context.req`,因此他们可以同时使用自己的会话(例如快会话). HUB's: (中文(简体) )

```ts
const hub = clearlyHub<express.Request>({
  // ...
  onSignIn: (person, { req }) => {
    const user = findOrCreateUser(person);
    req!.session.userId = user.id;
    return { appUserId: user.id };
  },
});
```

**它为你检查了什么:** 每个屏幕的回答是Ed25519签名, 它回答一个屏幕 在此浏览器中打开一次( o)`state`),它被赋予你的应用和屏幕 (单位:千美元)`client_id`,召回 URL,动作).

**如何相信一个答案:** 这是他点击的瞬间 晚点再联系, 询问 `getSubscription(hubId)` 当用之. 谁签的 是会话的用户.

会话是用饼干加密的,所以没什么可储存的;它分出几个饼干 因为象征是巨大的。 复制的饼干在刷新令牌过期前仍然有效: 签名退出 只清除此浏览器的副本.

**很明显是本地人 汉伯:** 通过 `urls: { screens, api, proxy, auth, issuer }`; 见 `examples/express/.env.example`。 。 。 .

**另一种路径比 `/clearly-hub`**,例如 `/auth/hub`:放入三处.

-   服务器 : `clearlyHub({ basePath: '/auth/hub', ... })` 并安置在那里, `app.use('/auth/hub', hub.express())`。处理器只在下面回答 `basePath` 并建设其 从它调回URL, 所以单独安装是不够的.
-   页: 1 `data-base-path="/auth/hub"` 在脚本标签上,或 `clearlyHub.configure({ basePath: '/auth/hub' })`。 。 。 .
-   很明显 HUB: 登录客户端的回调 URL 变为 `{app}/auth/hub/callback` 财务报告和审定财务报表 `{app}/auth/hub/answer`,以及 _转到应用程序_ `{app}/auth/hub/sign-in`。 。 。 .

## 登记数据

将您的应用程序的结果注册在您自己的UI的中枢中, 而不包含 `REGISTER_RESOURCE` 屏幕 : 数据集、其资源和认证方法保护资源使用。 只有服务器.

每通电话都从谁行动开始:要求签字人参与,或 `'app'`,为您的 app的自有密钥( n)`m2mClientId`编号 :`m2mClientSecret`例如,在长期工作之后,没有人 签入。 没有任何人签名的请求失败 `UNAUTHENTICATED`。 。 。 .

```ts
const { datasetId } = await hub.datasets.create(req, {
  title: 'Flood depth',
  ownerHubId,
  findability: 'LIMITED',
});

// Protected data: an authentication method first, then a resource behind the data proxy
const method = await hub.authMethods.create(req, ownerHubId, {
  name: 'Our tile server',
  type: 'CUSTOM_HEADER',
  authData: { parameterName: 'X-Api-Key', parameterValue: apiKey },
});
const resource = await hub.resources.add(req, datasetId, {
  name: 'Flood depth (WMS)',
  format: 'wms',
  sourceUrl: 'https://tiles.example.com/wms',
  authenticationMethodId: method.authMethodId,
});
```

| 打电话 | 回返 |
| --- | --- |
| `hub.datasets.create(actor, input)` | `{ datasetId }` |
| `hub.datasets.update(actor, datasetId, input)` | `{ datasetId }` |
| `hub.datasets.delete(actor, datasetId)` | 无 |
| `hub.datasets.get(actor, datasetId, { activeHubId? })` | 数据集,有资源 |
| `hub.resources.add(actor, datasetId, input)` | 资源 |
| `hub.resources.update(actor, datasetId, resourceId, input)` | 资源 |
| `hub.resources.delete(actor, datasetId, resourceId)` | 无 |
| `hub.authMethods.list(actor, hubId, { type?, activeHubId? })` | 中心的方法 |
| `hub.authMethods.create(actor, hubId, input)` | 方法 |
| `hub.authMethods.update(actor, hubId, authMethodId, input)` | 方法 |
| `hub.authMethods.delete(actor, hubId, authMethodId)` | 无 |

**谁能.** 很明显 HUB决定了 个人需要担任中心管理员(数据集和 资源:数据集的所有者中枢)。 您的应用程序的密钥有它自己的作用: 管理拥有的中枢 您的应用程序和它的子中心, 中枢成员的父母, 和编辑器 订阅您的 应用(及其子站点).

| 打电话 | 个人 | 您的应用程序: 所有器和子器 | 它的家长 | 订阅的枢纽 |
| --- | --- | --- | --- | --- |
| 数据集:创建、更新、删除 | 行政 | 对 | 没有 | 对 |
| 数据集:获取、公开 | 谁都行 | 对 | 对 | 对 |
| 数据集:获取, `LIMITED` | 在一个可能找到它的中心 | 对 | 对 | 如果有人能找到的话 |
| 资源:添加、更新、删除 | 行政 | 对 | 没有 | 对 |
| 认证方法:创建、更新、删除 | 行政 | 对 | 没有 | 没有 |
| 认证方法: 列表 | 行政 | 对 | 没有 | 没有 |

将数据集移动到另一个 `ownerHubId` 还需要这个人或应用软件在中心。 市场 师不能作更.

**很高兴知道**

-   `datasets.update` 财务报告和审定财务报表 `resources.update` 照创造而发送一切,你们所遗漏的 可予以清除(`spatial` 页:1 从 `datasets.get()`,返回形状 `update` 拿着. `spatial` 仅存储在更新上,而不是创建上.
-   受保护的资源有: `authenticationMethodId` (单位:千美元) `sourceUrl` (地址: 代理),且无 `url`:很明显。 HUB用它的数据代用。 打开的资源有一个 `url` 只有这个. 付费数据还有: `subscriptionModelId`老板枢机的计划. `format` 很明显。 HUB的车 格式 (单位:千美元)`wms`, (中文(简体) ), `wfs`, (中文(简体) ), `wmts`, (中文(简体) ), `tilejson`, (中文(简体) ), `api`,...). URL需要一个域: `localhost` 实值 拒绝, 使用 `lvh.me`。 。 。 .
-   `authData` 拥有秘密 很明显 HUB从不还的,而且 `update` 替换全部. 每栏 `type`数字 : `BASIC_AUTH` `username`, (中文(简体) ), `password`· ; `URL_PARAMETER` 财务报告和审定财务报表 `CUSTOM_HEADER` `parameterName`, (中文(简体) ), `parameterValue`· ; `ISHARE_AUTH_METHOD` `tokenEndpoint`, (中文(简体) ), `serviceProviderEORI`, (中文(简体) ), `entitledPartyEORI`· ; `JWT_ENDPOINT` `tokenEndpoint`, (中文(简体) ), `username`, (中文(简体) ), `password`, (中文(简体) ), `usernameField`, (中文(简体) ), `passwordField` (和 `accessTokenProperty`, (中文(简体) ), `refreshTokenProperty`(三); `S3` `s3AccessKeyId`, (中文(简体) ), `s3SecretAccessKey`· ; `OAUTH2_CLIENT_CREDENTIALS` `tokenEndpoint`, (中文(简体) ), `clientId`, (中文(简体) ), `clientSecret` (和 `accessTokenProperty`, (中文(简体) ), `secretAsHeader`, (中文(简体) ), `scope`) (中文(简体) ). 类型(`AuthDataByType`)说同.
-   删除数据集删除其资源并取消对其付费资源的订阅.
-   错误是 `ClearlyHubError`很明显 HUB的讯息和 `code` (单位:千美元)`BAD_USER_INPUT`, (中文(简体) ), `FORBIDDEN`, (中文(简体) ), `UNAUTHENTICATED`) (中文(简体) ). SDK在发送前会检查它能做的,有相同的代码.

## 未覆盖( 尚未覆盖)

-   建立自己的工作空间或租户:用手、需要批准的计划或 `onAnswer` 页:1 `SELECT_SUBSCRIPTION`。 。 。 .
-   其他服务器语言(.NET, Python,.):浏览器包与任意 后端可以回答同样的路线. 联系我们 [支持@ futureinsight.nl](mailto:support@futureinsight.nl) 我们会帮忙的 带着你的.

## 正在研究这项回购

```
npm install
npm run build       # both packages
npm test            # vitest
npm run typecheck
npm run lint
npm run example     # examples/express on http://localhost:5175 (copy .env.example to .env first)
```

## 常见问题

### @clearly-hub/node 是什么？

显然 节点服务器的HUB:登录、主机屏幕、订阅和一个处理器的使用

### 如何安装 @clearly-hub/node？

在项目目录运行 npm install @clearly-hub/node，或使用 pnpm add / yarn add / bun add。

### @clearly-hub/node 支持 TypeScript 吗？

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

### @clearly-hub/node 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @clearly-hub/node 需要什么版本的 Node\.js？

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

### @clearly-hub/node 可以商用吗？

@clearly-hub/node 使用 SEE LICENSE IN LICENSE 许可。许可条款写在包内的独立文件中，请阅读该文件确认可否商用。以上为概括，不构成法律意见，请以许可原文为准。

### @clearly-hub/node 的下载量有多少？

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

### @clearly-hub/node 还在维护吗？

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

