@clearly-hub/node

中文文档
0.12.0发布于 2026/10/30SEE LICENSE IN LICENSETypeScriptESM + CJS近 30 天下载 3224

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

中文使用文档
文档目录8 节
  1. 快开始
  2. 浏览器软件包
  3. 受保护数据
  4. 节点软件包
  5. 在数据代理服务器后面
  6. 登记数据
  7. 未覆盖( 尚未覆盖)
  8. 正在研究这项回购

很明显 HUB SDK

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

预览 (0.x). API仍然可能在小版本之间有所改变. 专有: 见 自由主义。 。 。 .

快开始

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

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

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

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. 添加脚本和一个按钮:

<!-- @0.1: follows 0.1.x fixes, not a breaking 0.2 -->
<script src="https://cdn.jsdelivr.net/npm/@clearly-hub/[email protected]/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 签了字后 见 受保护数据
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)数字 :

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)。 。 。 .

行动报到 dataanswer 何时 result 实值 SUCCESS
SELECT_SUBSCRIPTIONsubscription (单位:千美元)_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_HUBhub (单位:千美元)_id, (中文(简体) ), name(中文(简体) )
SELECT_DIGITAL_TWINactiveHub (单位:千美元)_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 头曰. 页面中:

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将数据登记在中枢, 作为签名人或您的应用程序; 参见 登记数据
hub.getProxyContext(req, { audience })在API后面显然。 HUB 数据代理:谁打电话(sub, (中文(简体) ), subType),用于哪个中枢,与哪个角色,以及订阅. null 没有代理标题; 见 在数据代理服务器后面
hub.getUserToken(req), (中文(简体) ), getAppToken()那个人的钥匙和你的应用软件的钥匙 你自己的电话

在数据代理服务器后面

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

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: (中文(简体) )

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。 。 。 .

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 我们会帮忙的 带着你的.

正在研究这项回购

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 共发布 18 个版本,首次发布于 2026/10/22;过去 12 个月发布了 18 个版本。

版本发布日期距今
0.12.0latest2026/10/3011 天前
0.11.02026/10/2614 天前
0.10.02026/10/2614 天前
0.9.02026/10/2614 天前
0.8.12026/10/2417 天前
0.8.02026/10/2417 天前

关于 @clearly-hub/node 的常见问题

@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 和提交记录判断。