# @bitcoinerrorlog/pubky-shop 中文文档

规范地址：https://npmcn.com/package/%40bitcoinerrorlog/pubky-shop/

版本：0\.1\.7
npm 元数据更新时间：2026-10-16T07:39:06.289Z
中文译文更新时间：2026-11-08T04:50:14.533Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40bitcoinerrorlog/pubky-shop
原文对照：https://npmcn.com/package/%40bitcoinerrorlog/pubky-shop/?lang=original
项目主页：https://github.com/pubky/pubky-shop-sdk#readme
源码仓库：https://github.com/pubky/pubky-shop-sdk

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

- 包体积（解压后）：918 kB，176 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22
- 运行依赖：2 个
- peer 依赖：@synonymdev/pubky ^0\.11\.0
- 首次发布：2026-09-21T05:58:02.245Z
- 最新版本发布：2026-10-16T07:39:06.123Z
- 近 30 天下载量：3453（2026-10-08 至 2026-11-06，npm 官方下载统计）
- 已发布版本数：8（近 12 个月 8 个）

## 中文简介

已打入的Pubky商店库存SDK、确定进口/出口编码以及销售商CLI

## 安装

```sh
npm install @bitcoinerrorlog/pubky-shop
```

也可以使用：`pnpm add @bitcoinerrorlog/pubky-shop`、`yarn add @bitcoinerrorlog/pubky-shop`、`bun add @bitcoinerrorlog/pubky-shop`

## README

# @bitcoinerrorlog/pubky-shop (英语)

用于Pubky Marketplace 库存 HTTP 合同的SDK类型, 确定性JSON/CSV交换和持久的进口规划 `pubky-shop` 销售商CLI和一通Shopify桥。 一揽子措施仅限无害环境管理,而且 需要节点22或更新。 现公布于npm `@bitcoinerrorlog/pubky-shop` (单位:千美元)`latest` (单位:美元) `publish.yml` 工作流程 当 GitHub 发布时.

```sh
npm install @bitcoinerrorlog/pubky-shop
npx pubky-shop --help
```

它所谈的服务 [`pubky/pubky-marketplace-service`](https://github.com/pubky/pubky-marketplace-service)· ; 其 HTTP 路由记录在 [`docs/api.md`](https://github.com/pubky/pubky-marketplace-service/blob/main/docs/api.md)。 。 。 .

## 软件包出口

-   `.` 是浏览器安全条目: 解码器, `PubkyShopClient` (编一清单) 和波浪 3a HTTP),以及内嵌入式进口规划器(`planImport`, (中文(简体) ), `planImportStream`, (中文(简体) ), `MemoryManifestStore`, (中文(简体) ), `resumeTasks`,块 `sync-many` 帮助者)。 它与Web Crypto兼容的SHA-256相接,从未 进口 `node:` 或者说 `@synonymdev/pubky`。 。 。 .
-   `./node` 是节点池规划器 : `FileManifestStore`,磁盘备份 `planImport` 编号 : `planImportStream`, (中文(简体) ), `resumeTasks`,以及 `streamResumeTasks`。 。 。 .
-   `@synonymdev/pubky` 是仅由 CLI 使用的可选对等点 / `./node`。 。 。 .

```ts
import {
  MemoryManifestStore,
  PubkyShopClient,
  planImport,
} from "@bitcoinerrorlog/pubky-shop";
import { FileManifestStore, planImport as planImportNode } from "@bitcoinerrorlog/pubky-shop/node";
```

## 证书所有权

```ts
import { PubkyShopClient } from "@bitcoinerrorlog/pubky-shop";

const client = new PubkyShopClient({
  session: process.env.PUBKY_MARKETPLACE_SESSION!,
  serviceUrl: "https://marketplace.example/",
});
```

`serviceUrl` 市场服务来源(生产: `https://marketplace-service-production-ce23.up.railway.app`) (中文(简体) ). 每一种方法 返回一个 `SdkResult<T>`, (中文(简体) ), `{ ok: true, value }` 或者说 `{ ok: false, error }`, (中文(简体) ), 并且不为服务或运输故障投放:

```ts
const result = await client.listings(sellerPubky, { limit: 50 });
if (!result.ok) {
  console.error(result.error.code); // for example "session_rejected"
} else {
  console.log(result.value);
}
```

主持人得到了不透明 服务员出带, 拥有坚持, 期满政策,办理续签,撤销,账务约束,签收清理等手续. 这个 SDK: (英语)

-   发送 `Authorization: Bearer` 仅用于验证的HTTPS服务源;
-   拒绝用户信息、查询、碎片、非根路由和非HTTPS服务 URL;
-   绝不循规蹈矩,绝不隐匿地更新被否决的会话;
-   返回静态 `session_rejected` hTTP 401 错误;
-   永不记录、串行、坚持、返回或拖延携带者;
-   绝不接受销售者的秘密密钥、种子、根键或密钥.

`ServiceAuthTokenSigner` 是一个只有接口的未来主机边界。 它回来了 主机批准的 AuthToken 明信片字节和预期的阴暗字节 。 这个包 不执行 Ring, 密钥存储, 主服务器会话薄荷, AuthToken 交换或自动无记名更新。 服务 AuthToken/ 持有者是分开的 任何家庭服务员的证书.

## 库存客户

`getInventoryProjection(aggregateId)` 财务报告和审定财务报表 `adjustInventory(request)` 返回时 `SdkResult<T>`。它们解码生成的"一波"合同,同时保留 前进相容性未知响应字段。 客户端绑定 `fetch` 改为 全球对象 因此铬 `Window.fetch` 不被援引为一种方法。 波浪3a卖家HTTP开机 同一类: `listings`, (中文(简体) ), `orders`, (中文(简体) ), `events`, (中文(简体) ), `getListing`, (中文(简体) ), `syncMany` (满分100分),网络呼和会. `createSession` POSTs Authtoken 字节 作为 `application/octet-stream` 并且不附载任何携带者。 第1波粗点 `i64` 字段 (单位:千美元)`server_revision` 和每批库存数量) `bigint`,包括普通小值。 JSON代号被俘获 在 Java 脚本之前 `Number` 转换, 已签名的64位区域以外的值 和非整数符号失败 `invalid_response`,和未知的整数字段 也作为无损失保留 `bigint`。 。 。 .

`InventoryAdjustRequest.expected_revision` 财务报告和审定财务报表 `delta` 为: `bigint`. SDK 软件 序列化它们为精确的未引用的 JSON 整数符号; 例如 `expected_revision: 9007199254740992n` 发送 `"expected_revision":9007199254740992`反应机构仍受约束, 服务器消息从不反映,只允许列出服务错误代码 被暴露出来.

预测 `stock.authority` 实值 `listing_total`。在变体跟踪上 列出投影带 `variants`,每个大小一行 (单位:千美元)`variant_id`选项 `sku`, (中文(简体) ), `enabled`, (中文(简体) ), `total`, (中文(简体) ), `available`, (中文(简体) ), `reserved`, (中文(简体) ), `sold`, (中文(简体) ), `sold_out`),解码并验证.

`InventoryAdjustRequest.variant` (单位:千美元)`{ id?, sku? }`)选择一个大小并是 (d) 服务要求列入有变式的列表。 它的答案带有 `stock.authority: "variant"` (单位:千美元)`VariantStockView`:大小的计数器外加 列出总数 `listing_total`); 单变量列表仍然答案 `listing_total`缩小 `stock.authority` 读取前 `variant_id`。 。 。 .

| 方法 | 服务路线 |
| --- | --- |
| `getInventoryProjection(aggregateId)` | `GET /v1/inventory/listings/{aggregateId}` |
| `adjustInventory(request)` | `POST /v1/inventory/adjust` |
| `listings(pubky, query?)` | `GET /v1/sellers/{pubky}/listings` |
| `orders(pubky, query?)` | `GET /v1/sellers/{pubky}/orders` |
| `events(pubky, query?)` | `GET /v1/sellers/{pubky}/events` |
| `getListing(seller, listingId)` | `GET /v1/listings/{seller}/{listingId}` |
| `syncMany(listings)` | `POST /v1/listings/sync-many` (满分100分) |
| `addWebhook(url)` | `POST /v1/webhooks` |
| `rotateWebhook(id)` | `POST /v1/webhooks/{id}/rotate` |
| `deleteWebhook(id)` | `DELETE /v1/webhooks/{id}` |
| `listSessions()` | `GET /v1/auth/sessions` |
| `createSession(authToken)` | `POST /v1/auth/sessions` |
| `updateSession(id, patch)` | `PATCH /v1/auth/sessions/{id}` |
| `revokeSession(id)` | `DELETE /v1/auth/sessions/{id}` |

被绑定的可执行合同是 `test/fixtures/service/inventory.json`字节 `pubky/pubky-marketplace-service` 订正 `4d5c07c0f273616c4fba06697f90d4baef5a7722`迁移 `0034`见 源代码和SHA-256的详细信息.

## 决断 JSON

-   `canonicalJson` 执行 RFC 8785 JCS 文本.
-   `encodeCanonicalJson` 发射UTF-8 正好有一个LF.
-   `parseBoundedJson` 拒绝无效的 UTF-8, 重复对象名称, 过多 字节/深度/节点/字符串大小,和不支持的Unicode.
-   `decodeExportEnvelope` 编号 : `encodeExportEnvelope` 保存未知的信封, 在保留服务投影的同时,列表-收发器和投影字段 字段出自卖方授权的记录.
-   `captureSignedRecord` 保留精确的签名记录字节和一个SHA-256 侧车. `emitSignedRecord(capture)` 用于未修改记录的字节相同. 更改记录需要主机注入生产计划验证器,并且是 然后JCS连载。 拒绝验证不执行写入 .

JSON编解码器从未将服务预测合并为已签名的记录.

## RFC 4180 CSV 标准

`exportCanonicalCsv(rows, { excelBom?: boolean })` 写一个强制性标题, 引用的 UTF-8 单元格、 CRLF 记录、 确定性列 和排队命令, 和Canonic JSON巢穴细胞。 正常输出没有BOM; 清晰的 Excel 选项发出一个。 危险的电子表格前缀 (单位:千美元)`=`, (中文(简体) ), `+`, (中文(简体) ), `-`, (中文(简体) ), `@`)和领先的负极点使用可逆的负极点 逃脱.

`parseCanonicalCsvStream(source, onRow, limits)` 是未绑定目录字节 API (英语). `source` 也许是 `AsyncIterable<Uint8Array>`页:1 `ReadableStream<Uint8Array>`,或同步流动。 递增 hashes source字节,解码UTF-8,即使其三个字节也承认 BOM 分别到达,并保留 RFC 4180 状态 跨块分块 CRLF, 逃脱了引用, 和多字节字符。 它只保留当前界限 行/单元格和报告测量了峰值解析器拥有的字节。 跨行复制和 列表组验证由 `planImportStream` 承诺之前.

`parseCanonicalCsv(bytes)` 是受约束的、可实现的便利编码器。 这个 接受 BOM 或 没有 BOM 并拒绝单独 LF/CR 、 简略引用、 重复 头/行/变位代号,模棱两可的 SKU, 相互冲突的列表字段, 原始 公式有效载荷、无效身份/映射、不安全整数和超限 输入。 未知的额外列被保留在 `extraFields` 并导出 决了.

条形柱为:

`record_uri`, (中文(简体) ), `seller_pubky`, (中文(简体) ), `listing_id`, (中文(简体) ), `source_listing_key`, (中文(简体) ), `record_revision`, (中文(简体) ), `variant_id`, (中文(简体) ), `sku`, (中文(简体) ), `state`, (中文(简体) ), `title`, (中文(简体) ), `description`, (中文(简体) ), `taxonomy_json`, (中文(简体) ), `category`, (中文(简体) ), `condition`, (中文(简体) ), `tags_json`, (中文(简体) ), `amount_minor`, (中文(简体) ), `currency`, (中文(简体) ), `exponent`, (中文(简体) ), `variant_quantity`, (中文(简体) ), `variant_enabled`, (中文(简体) ), `options_json`, (中文(简体) ), `media_json`, (中文(简体) ), `shipping_options_json`, (中文(简体) ), `return_policy_json`, (中文(简体) ), `sale_json`,以及 `external_refs_json`。 。 。 .

身份只来自 `record_uri`, (中文(简体) ), `(seller_pubky, listing_id)`,或一个 明确 `source_listing_key` 为了新的记录。 标题永远不是身份. 流出输入没有固定的总字节或总行上限. 行字节, 单元格 字节、列、嵌入式 JSON 深度和剖析器/平面工作套集被限制 失败时输入安全观测值。 字节组合方便解析器 出口者还保留了明确的总字节/行盖.

## 持久的进口规划

浏览器主机针对内存的计划 `ManifestStore` (Shop供应德克西):

```ts
import {
  MemoryManifestStore,
  browserFileSource,
  planImportStream,
  resumeTasks,
} from "@bitcoinerrorlog/pubky-shop";

const store = new MemoryManifestStore();
const planned = await planImportStream(browserFileSource(file), { store });
```

`planImport` 编号 : `planImportStream` 打开 `.` 带有 Web API 的流派, 绑定 工作集(64个 MiB 便利/ 分析平面字节),并调用 `store.create` 仅在EOF、UTF-8/CSV/JSON/映射验证、身份索引核对和 来源 SHA-256 完成. 解析失败会留下零行. JSON是一个界限 便利路径( e)`[{…}]` 或者说 `{rows:[…]}`; CSV 为流. 同上,注: 是来自SHA-256的UUID v5相式的图案,显式标识,行名,以及 常态散列——与节点规划器相同的字节. `chunkSyncManyListings` 拆分发布批次100. `classifySyncManyItem` 读取 207 个结果.

节点主机保留磁盘集合规划器 :

```ts
import {
  FileManifestStore,
  planImportStream,
  replayImport,
  resumeTasks,
} from "@bitcoinerrorlog/pubky-shop/node";

const store = new FileManifestStore("/secure/host-owned/import-manifests");
const planned = await planImportStream(fileReadable, { store });
```

计划递增地写一个模式0600 spoll和外部分组索引 在主机提供的列表目录中。 外部结合类型 验证重复行、变体身份、 SKU 和列表级别的事实 不保留已解码源或进程内存中的所有行。 第一个 已承诺的表写只发生在EOF,UTF-8/CSV/映射验证之后, 外部分组、生成-ID碰撞检查和源SHA-256 已完成。 错误的后期输入会去掉规划的集合并留无 显出.

一份清单可以修正其编号 准确来源 SHA-256和十进制源字节数, 解析器/映射/schema 版本, 完整的不可移动行身份, 正常化 排行式散列、动作、生成列表标识和确定性同位素 键。 JSONL 运单被流到一个 fsynced 临时文件和 在解剖学上更名为. `loadSummary` 财务报告和审定财务报表 `streamRows` 避免实现; `load` 财务报告和审定财务报表 `planImport(bytes, ...)` 明确设定便利 API. `streamRows` 验证完整的文件并跟踪行数 输出任何权威行. `checkpointImportRow` 执行边框 流体原子重写,以及 `streamResumeTasks` 恢复任意行的目录 计数不调用 `load`. 生成的标识在将来仍然存在 出版社可以采取行动.

`FileManifestStore` 是包含在此中的生产主机提供适配器 软件包。 它能将配置的根一次化, 把它的装置,inode, 和模式,并验证该身份 锁前后,显示,集合, 检疫和清理行动。 最后打开时使用节点所在的无跟随旗 曝光它们; 文件为模式 0600, root 和规划目录为模式 0700, 并写入进程间排除、 fsync 和原子重命名或 附录.

这不是故意的 `openat` 监禁要求: 节点没有 目录 - 相对无后 API 。 主机配置和动画 root 的父重命名不能被同时重命名 攻击者。 检测到的根替换失败, 但有一个特权 无法避免的检查/打开缺口位于 适配器的威胁模型. 信任的母体中的符号链接是可读的; a symlink 作为已配置的最终根或管理的最后文件被拒绝 . 废弃的死活程序 `.planning` 财务报告和审定财务报表 `.tmp` 文物只有在以后才能收获 配置年龄,同时使用 live-PID, 年轻, 更改身份, 以及未知文件 页:1.

每行检查站 `planned`, (中文(简体) ), `publishing`, (中文(简体) ), `published_unsynced`, (中文(简体) ), `complete`, (中文(简体) ), `conflict`,以及 `failed`重新绘制不确定的地图 `publishing` 行改为 `reconcile_publish`绝不是盲目的; `published_unsynced` 恢复 只能是服务同步腿.

`replayImport` 返回同一行身份的现有显示,并 胡说八道 更改的内容记录在一个单独的不可改变的 `pubky-shop-replay-quarantine` JSONL 日志本身的单调版本和一个 与表单版本进行比较和补充检查。 身份为 `SHA-256(manifest schema/version, replay source SHA-256, canonical conflict hash)`: 相继、相并和重现后重复播放返回 现有持久记录,但不添加版本。 元数据记录被绑定 并附随 `O_APPEND`冲突排居其中, 内容验证 JSONL 侧车,并随读 `streamReplayConflicts`。 。 。 . 既不附加也不读取重写或实现以前的历史.

D6.19 保留为主机操作:保留显示/结果和隔离文件 至少30天,然后打电话 `compactReplayQuarantines` 保留 断取. 接合是明确界限的流体维护操作; 3; 在身份年限过后,后期重播可能会产生新的审计记录. 因此存储以主机保留回放音量为界,而不是以 不安全的进程封顶 。 断接的隔离尾巴在主机关闭前失效 电话 `repairReplayQuarantineTail`,验证每一个完整的记录 只去除不完整的最后碎片. `discardManifest` 这是 版本 CAS 丢弃控制; 它首先使显示的不可用, 然后 移除其保留的隔离/冲突文件。 重放永不改变 `complete`, (中文(简体) ), `conflict`, (中文(简体) ), `failed`,或任何其他行检查站。 检疫 报告存活了一个新的 `FileManifestStore` 举个例子 CSV 格式错误或截断 创造任何迹象。 策划者自己没有做家庭服务员 PUT,假的 比较和扫描,或服务出版物;CLI `listings import` 命令 上面还有Shofify Bridge 驱动出版物.

外部分组只保留一个固定的扇入分批. 生成运行使用 定型生成/索引名称而非内相路径目录. 每个输入的字节预算费用固定为64个KiB流/读取行/解码器 高通、行头、路由器、路径名和输出元数据;扇入是 预算允许的最低限额和明确描述上限 (单位:千美元)`maxSortOpenFiles`,默认16。 报告的资源使用情况包括: 配置了上限和测量描述符/元数据/工作设定高水分标记. 无法支持双向合并的配置在之前被拒绝 读取输入.

## 安全错误和限制

`PubkyShopError` 使用静态消息。 细节中只包含被绑定的数字, 字段名称、允许列表的服务代码、显示身份和行身份. 接收器值、运输例外文本、服务器消息/机体和源 单元格文本除外.

错误代码 :

`invalid_configuration`, (中文(简体) ), `invalid_service_url`, (中文(简体) ), `invalid_session`, (中文(简体) ), `origin_violation`, (中文(简体) ), `session_rejected`, (中文(简体) ), `transport_error`, (中文(简体) ), `response_limit_exceeded`, (中文(简体) ), `invalid_response`, (中文(简体) ), `service_error`, (中文(简体) ), `invalid_json`, (中文(简体) ), `unsupported_json_value`, (中文(简体) ), `limit_exceeded`, (中文(简体) ), `malformed_csv`, (中文(简体) ), `invalid_csv_header`, (中文(简体) ), `duplicate_row`, (中文(简体) ), `duplicate_variant_id`, (中文(简体) ), `ambiguous_sku`, (中文(简体) ), `conflicting_listing_fields`, (中文(简体) ), `formula_payload`, (中文(简体) ), `invalid_identity`, (中文(简体) ), `invalid_mapping`, (中文(简体) ), `validation_failed`, (中文(简体) ), `unsupported_record_version_or_field`, (中文(简体) ), `manifest_conflict`, (中文(简体) ), `manifest_store_error`,以及 `changed_replay_quarantined`。 。 。 .

## 销售商CLI

`pubky-shop` 是卖方命令行客户端。 船舶违约就是生产 来源( e)`https://shop.pubky.app` 财务报告和审定财务报表 `https://marketplace-service-production-ce23.up.railway.app`) (中文(简体) ). 覆盖 `--bff-url` 编号 : `--service-url`, (中文(简体) ), `PUBKY_SHOP_BFF_URL` 编号 : `PUBKY_SHOP_SERVICE_URL`, (中文(简体) ), 或者说 `$XDG_CONFIG_HOME/pubky-shop/config.json` 密钥 `bff_url` 财务报告和审定财务报表 `service_url` (旗帜击败env击败文件).

市场登录使用商店BFF CLI赠款路线. CLI 生成 `result_cpk` 编号 : `result_delivery_id`,以 一个家用服务器 PoP PUT, 并且从来没有持有商店饼干或 BFF 签名密钥。 登录 将补助金绑定在主服务器的阴暗会话上。 无头证明( CI 和活 薄荷能装上弹道座椅,然后呼叫 `@synonymdev/pubky` 0.11 (简体中文) `Signer.approveAuthRequest` 编辑 `pubkyauth://signin_grant` URL 这样SDK 补助金申请. `@synonymdev/pubky` 0.8 将 AuthToken 张贴在该收件箱上 而受赠的劳动者 `grant_invalid`经批准后, `auth login --complete` 门票并申请服务员. `auth login` 装入存储 主服务器会话覆盖 `/pub/pubky.app/marketplace/:rw` 从密钥链 服务 `pubky-shop`账户 `{origin}|{pubky}|homeserver-session`,或从 模式 0600 文件在 `PUBKY_SHOP_CREDENTIAL_DIR` / 配置证书 目录。 有效载荷是 `{pubky,capabilities,secret}` 地点 `secret` 实值 `Session.exportLocalSecret()`。丢失的物品是出口2 `homeserver_session_missing`无法读取或无法操作的材料为出口2 `homeserver_session_invalid`市场持有人是一个单独的项目, 账户 `{origin}|{pubky}`索赔不退回会议编号; `auth logout` 需求 `--force-local` 除非有UUID会话 id .

```sh
PUBKY_SHOP_LIVE=1 npm test -- test/cli.live.test.ts
pubky-shop auth login --json --complete
pubky-shop auth status --json
pubky-shop listings export --format json --output listings.json
pubky-shop listings import --input listings.json
pubky-shop orders export --json
pubky-shop events tail --json
pubky-shop webhook add --url https://example.invalid/hook
pubky-shop webhook rotate --id <webhook-id>
pubky-shop webhook delete --id <webhook-id>
pubky-shop auth logout --force-local
```

`--json` 指纹 `{ok,data,error{code,message}}`退出时 `0` 成功吗, `1` 用途, `2` 授权/拒绝, `3` 远程/ 速率限制/ 无法使用.

## 网络呼号

以 `pubky-shop webhook add --url <https-url>` 或者说 `client.addWebhook(url)`· ; `rotateWebhook` 编号 : `webhook rotate` 发行新的 秘密和密钥标识,以及 `deleteWebhook` 编号 : `webhook delete` 删除 终点 服务用这些信头标出每一次交付:

| 页眉 | 数值 |
| --- | --- |
| `Pubky-Webhook-Version` | `1` |
| `Pubky-Webhook-Id` | 事件编号( UUID) |
| `Pubky-Webhook-Timestamp` | Unix 秒数 |
| `Pubky-Webhook-Key-Id` | 结尾当前密钥 ID( UUID) |
| `Pubky-Webhook-Signature` | `v1=` 外加小写 HMAC-SHA256 |

HMAC是计算出来的 `v1.{timestamp}.{event id}.{raw body}` 键入 秘密的SHA -256字节 其中的秘密是未加的基数64url 创建或旋转终点时返回字符串。 对照 生请求字节,不重序 JSON. `verifyPubkyWebhook` (只有节点, 从 Shopify 连接器条目中导出)检查密钥 ID, 时间戳 恒定时间 skew, 签名格式和签名 :

```ts
import { verifyPubkyWebhook } from "@bitcoinerrorlog/pubky-shop/connectors/shopify";

const verdict = verifyPubkyWebhook({
  raw: rawBodyBytes, // Uint8Array of the exact request body
  secretBase64Url: process.env.PUBKY_WEBHOOK_SECRET!,
  expectedKeyId: process.env.PUBKY_WEBHOOK_KEY_ID!,
  eventId: headers["pubky-webhook-id"],
  timestamp: headers["pubky-webhook-timestamp"],
  keyId: headers["pubky-webhook-key-id"],
  signature: headers["pubky-webhook-signature"],
  nowSeconds: Math.floor(Date.now() / 1000),
  maxSkewSeconds: 300,
});
if (!verdict.ok) {
  // verdict.reason: "malformed" | "stale" | "wrong_key" | "bad_signature"
}
```

重复交付 `Pubky-Webhook-Id`。 。 。 .

## 商店桥

`@bitcoinerrorlog/pubky-shop/connectors/shopify` 地图 购买产品 CSV 头和 `products/update` 编号 : `inventory_levels/update` {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}然后进入CSV线 驱动现有的客户端: homeserver PUT, `syncMany`, (中文(简体) ), `inventory.adjust` 与 `external_ref.channel` `shopify`卖方 `events`,和 pubky 网络hook 核查。 CSV数量栏记作损失. `map-csv` 已经 不要把它们写成 犬类股票。 管理 API 客户端会说 GraphQL `inventorySetQuantities` 与比较数量。 测试结果与 有记录的答复。 现场商店 纪念品 和网络商店的终点是 记录 `connectors/shopify-bridge/BOUNDARY.md`。 。 。 .

```sh
shopify-bridge map-csv --input products.csv --seller <pubky> --currency USD --exponent 2 --output canonical.csv --losses losses.json
shopify-bridge config-summary --secrets bridge-secrets.json
shopify-bridge webhook --secrets bridge-secrets.json --receipts ./receipts --topic products/update --shop-domain shop.myshopify.com --webhook-id <id> --event-id <id> --triggered-at <iso> --hmac <base64>
```

`webhook` 恢复存储的主服务器会话( r)`PUBKY_SHOP_PUBKY` 编辑 CLI 证书存储)并用 `storage.putBytes`。 。 。 . `--put-dir` 被拒绝。 秘密文件有行政令牌和普比 市场会议. `config-summary` 打印商店域和销售者 只有阴道。 这个 `.` 导出不导入此节点条目.

## 发展大门

运行时间依赖关系( E)`@noble/curves`, (中文(简体) ), `qrcode`)属于CLI. `@synonymdev/pubky` 是可选的对等点 `./node` 还有CLI 这个 `.` 导出不导入它们.

```sh
npm run format:check
npm run lint
npm run typecheck
npm test
npm run test:full
npm run build
npm run consumer:check
npm run browser:check
npm run pack:dry
npm run gate
npm run gate:full
```

`npm test` 编号 : `npm run gate` 保留仍会溢出到磁盘的 10k-row 目录 . `GATE_FULL=1 npm test` (或 `npm run test:full` 编号 : `npm run gate:full`添加 100001-row目录. `consumer:check` 财务报告和审定财务报表 `browser:check` 导入已建 包装消费者的方式. `npm run pack:dry` 验证包内容而不发布.

## 常见问题

### @bitcoinerrorlog/pubky-shop 是什么？

已打入的Pubky商店库存SDK、确定进口/出口编码以及销售商CLI

### 如何安装 @bitcoinerrorlog/pubky-shop？

在项目目录运行 npm install @bitcoinerrorlog/pubky-shop，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 pubky-shop、shopify-bridge，可以用 npx pubky-shop 直接运行。

### @bitcoinerrorlog/pubky-shop 支持 TypeScript 吗？

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

### @bitcoinerrorlog/pubky-shop 支持 ESM 还是 CommonJS？

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

### @bitcoinerrorlog/pubky-shop 需要什么版本的 Node\.js？

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

### @bitcoinerrorlog/pubky-shop 可以商用吗？

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

### @bitcoinerrorlog/pubky-shop 的下载量有多少？

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

### @bitcoinerrorlog/pubky-shop 还在维护吗？

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

