npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@eyaeya/xgg-core

v2.1.0

Published

Core runtime library for xgg, the Xiaomi Gateway Geek Edition CLI

Readme

@eyaeya/xgg-core

@eyaeya/xgg-corexgg 的协议、会话、schema、资源和用例层。它面向需要在 Node.js 程序中复用小米中枢网关极客版能力的开发者。

大多数用户应该直接安装 CLI:

npm install -g @eyaeya/xgg-cli

@eyaeya/xgg-cli 会自动安装匹配版本的 @eyaeya/xgg-core。只有在 Node.js 程序里直接复用协议、schema 或 usecase 层时,才需要单独安装:

npm install @eyaeya/xgg-core

GitHub 仓库:eyaeya/xiaomi-central-hub-gateway-cli

包内容

npm tarball 只包含:

  • dist/
  • LICENSE
  • README.md

npm 包只包含运行 core 所需的 dist、许可证与本 README;它不依赖仓外参考文件、开发文档、探测记录或快照。

说明

网关通信不是普通 HTTP API,而是通过 WebSocket 承载的加密二进制协议。除低层逃生口外,core 层会用 schema 校验网关返回,避免调用方直接依赖未建模响应。

写操作与 workflow 租约

公开的 typed mutator(规则、变量和备份资源写 API)会自动取得对应网关的 workflow 租约,并在同一个 daemon 连接上完成整段 live pre-read、校验、read-modify-write、写入和必要的 readback。复合 mutator 内部继续调用其他 typed mutator 时会复用同一个租约,不会重复获取。

低层 agentCall({ kind: 'write' }) 在没有外层 workflow 时也会自动取得一个仅覆盖该 RPC 的租约,以兼容既有 Node.js 调用。单 RPC 租约不能保护调用方自己拼接的复合读改写;此类流程必须显式包在 withMutationWorkflow 中:

await withMutationWorkflow(
  { baseUrl, store, operation: 'my-rule-update' },
  async () => {
    const before = await agentCall({ baseUrl, store, method: '/api/getGraph', params: { id } });
    await agentCall({
      baseUrl,
      store,
      method: '/api/setGraph',
      params: update(before),
      kind: 'write',
    });
    return agentCall({ baseUrl, store, method: '/api/getGraph', params: { id } });
  },
);

loadBackup() 是异步 restore 的安全复合 API:它在同一租约中先调用 downloadBackup 并确认缓存进度到 100,再调用 loadBackup 并确认恢复进度到 100。下载 ACK/进度含糊时不会进入 load;load ACK 缺少进度句柄、任一阶段超时或确认丢失都会抛出 NotConfirmedError 并 fence 当前 mutation。调用方应 logout、重新登录并检查 live state,不能盲目重试。可用第三个参数配置 pollIntervalMspollTimeoutMs,每个阶段获得独立超时预算;需要真实 terminal 明细时传 includeProgress: true,返回 { downloadResult, downloadProgress, result, progress }。高层 API 不接受进度查询注入,不能跳过真实 terminal 确认。

standalone raw agentCall() 调用 /api/loadBackup 时也执行同样的 terminal wait。若 raw restore 已处于显式 withMutationWorkflow 中,调用方仍必须在该 callback 返回前完成 /api/getBackupProgress 的 terminal 确认。

Typed 节点 ID

addNode({ shortcut }) 新建 typed 节点时,显式 shortcut.id 必须符合小米网页编辑器的 [A-Za-z0-9]+;省略则由 core 生成兼容 ID。校验发生在 workflow 租约、session 与任何 RPC 之前。只有 export/import 重放已存在的 modeled typed 节点时,才可同时传 legacyNodeIdReplay: true 和明确的非 canonical shortcut.id;该 intent 对 raw node、缺少 ID 或已兼容 ID 都会拒绝,不能用来放宽普通新建语法。持久化旧图和 opaque node 的读取 schema 仍保持宽松,不会静默改名。

规则校验的 I/O 契约

validateGraph({ graph }) 默认只执行本地、确定性的 schema/字段/表达式检查,不会隐式访问 daemon、网关或公网 MIoT spec 服务。需要设备 spec-aware 检查时,调用方必须显式注入 getDeviceSpec,并自行决定使用网络、缓存还是本地 fixture:

const localIssues = await validateGraph({ graph });

const specAwareIssues = await validateGraph({
  graph,
  getDeviceSpec: (urn) => getDeviceSpec(urn, { timeoutMs: 5000 }),
});

在线变量校验通过 listAvailVars 显式注入清单;每项必须保留完整的 { scope, id, type: 'number' | 'string' }。校验器按精确 scope/id 判断存在性,并在所有可判定的引用点核对实际类型。省略 callback 时仍执行合法 scope 和本地图结构检查,但不会假装知道变量是否存在或是什么类型。exportRuleFromView(..., strictRoundtrip=true) 会读取源网关规则内与 global 变量的实际类型,在生成任何 staging 脚本前拒绝路径化 mismatch 或缺失 global;permissive export 保留 warning。

createRule() 若由 SDK 调用方直接携带初始变量卡,也会在首笔 /api/setGraph 前执行同一在线类型门禁;CLI 的空图 rule new 不增加这次预读取。只有明确的 raw/restore 流程才应传 CreateRuleOptions.varCheck: false

getDeviceSpec 会复核 property 卡的 notify/read/write access、dtype/domain 与 action input 契约。若调用方还有目标网关设备清单,可同时注入 getDevice(did),对 deviceInput / deviceInputSetVar property/event push source 追加实例级 pushAvailable 诊断;没有该回调时不得把离线结果表述成已证明 push 可用。AddNodeShortcut.allowNoPush: true 仅是本次 typed add 的 transient runtime-probe intent,不持久化、不绕过任何 property access;后续带 getDevicevalidateGraph 会继续如实报告 no-push。preload 也只控制启用时首次查询/评估,不改变 notify/read 资格。

spec registry 的 404 会返回 warning,表示该 URN 的外部检查被跳过;网络/超时/5xx 或 schema 失败会返回独立 error issue。两者都不会中止图遍历,因此同一次结果仍包含已经发现的本地问题。validateGraphOrThrow 会在收集完整 issue 列表后,按既有契约对第一个 error 抛出 ConfigError

注入 spec 后,deviceOutput property-write 会核对属性存在性与 write access、literal 的 MIoT 原生类型和 value-list/value-range/step,以及 variable ref 的实际类型、dtype 与有效 range metadata;action input 继续使用同一 literal/变量基础契约,并额外检查 action.inprops.ins 的完整逐索引映射。

deviceOutput typed variable ref 只支持不含 value-list 字段的 string 目标,或不含该字段且带有效 value-range 的 number 目标。当前 xgg 对 boolean 与任何存在 value-list 字段的目标(包括空数组)采用 literal-only 契约;spec-aware validation 会诊断 persisted legacy ref,strict export 与 enableRule 会 fail closed。默认 enable 只对实际存在的 output ref 做聚焦 spec 证明,404、网络/超时或无效 spec 都阻止 enable,且不会查询或扩大校验到无关旧设备节点;显式传入 EnableRuleOptions.getDeviceSpec 时仍保留全图 spec-aware 行为。

DATA 响应大小限制

core 在解密 DATA frame 后、同步解压前执行两层上限检查:压缩数据默认最多 16 MiB,声明及实际解压后的 UTF-8 JSON 默认最多 64 MiB。长度声明必须为正数,zlib 的 maxOutputLength 还会阻止实际输出越过声明值。超限或损坏的响应会作为网络/协议失败结束当前 session。

默认值由 DEFAULT_MAX_INNER_COMPRESSED_BYTESDEFAULT_MAX_INNER_JSON_BYTES 导出。确实需要处理更大备份响应的库调用方可以显式配置 SessionChannel,但应使用部署中测得的有限值,不要取消上限:

const channel = new SessionChannel({
  send,
  recv,
  receiveLimits: {
    maxCompressedBytes: 32 * 1024 * 1024,
    maxJsonBytes: 96 * 1024 * 1024,
  },
});