# @clickwire/api-client 中文文档

规范地址：https://npmcn.com/package/%40clickwire/api-client/

版本：4\.4\.0
npm 元数据更新时间：2026-11-09T11:12:21.189Z
中文译文更新时间：2026-11-10T09:26:28.984Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：302 kB，187 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=20\.19\.0
- 运行依赖：0 个
- 首次发布：2026-05-06T12:02:12.052Z
- 最新版本发布：2026-11-09T11:12:20.965Z
- 近 30 天下载量：1859（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：89（近 12 个月 89 个）

## 中文简介

点击线程 API 客户端

## 安装

```sh
npm install @clickwire/api-client
```

也可以使用：`pnpm add @clickwire/api-client`、`yarn add @clickwire/api-client`、`bun add @clickwire/api-client`

## README

# @ clickwire/ api- 客户端

我们的Laravel V2 API的TypeScript客户端. 节点18+,仅服务器侧-使用 `fetch` 读取 `CLICKWIRE_API_URL` + 键 `CLICKWIRE_TOKEN` 根据请求时间从环境(同 vars 与 monorepo / Next apps 相同). 除了这些设定之外,没有设置仪式.

## 用这个

```typescript
import { apiClient } from "@clickwire/api-client/v2";

const { data } = await apiClient.posts.list({ per_page: 20 });
const product = await apiClient.products.get("some-slug");
```

偏爱 `@clickwire/api-client/v2` 当您关心您正在使用的 API 版本时, 将根导出 。 方法如HTTP API(`authors`, (中文(简体) ), `posts`, (中文(简体) ), `products`(中文(简体) ). 类型为前缀 `V2*` ——用于查询参数和响应形状.

可选 : `apiClient.configure({ locale: "nl" })` 设置全局 `locale` v2 查询参数 网站的默认地址大多已经足够.

## 全局查询参数

配置查询参数一次, 而不是在每次通话中重复 :

```typescript
import { createV2ApiClient } from "@clickwire/api-client/v2";

const clickwire = createV2ApiClient({
    // Semantic: this website doesn't carry these product types.
    catalog: { excludeProductTypes: ["sneakers"] },

    // Generic: default query params per endpoint, keyed by `<group>.<method>`.
    defaultQuery: {
        "products.list": { per_page: 8 },
        "posts.list": { sticky: true },
    },
});

// `exclude_product_types[]=sneakers&per_page=8` sent automatically:
await clickwire.products.list({ sort: "newest" });
```

`catalog.excludeProductTypes` 发送 `exclude_product_types[]` 每个目录表面终点(`products.list`, (中文(简体) ), `products.related`, (中文(简体) ), `productAttributes.list`, (中文(简体) ), `productAttributes.popular`, (中文(简体) ), `productAttributes.get`:被排除在外的产品从点击量、方面和相关结果消失,属性 `products_count` 编号 : `has_products` 反映范围目录.

每个查询密钥的优先性:每个调用 > `defaultQuery` > 翻译: `catalog` > 翻译: `locale`,矩阵替换(从未合并),因此通过 `exclude_product_types: []` 仅此一次就解除了对这一要求的全球排斥。 成员端点从未收到默认值(per-user certain).

## 成员

成员登录电子邮件代码;成功核实返回 a **成员符号**。网站Bearer将保持原样;成员标志将在 `X-Member-Token` 标题,每个呼叫或每个客户实例。 服务器侧- Next.js 路由处理器将其保存在 `httpOnly` 饼干,永远不要交给浏览器.

```typescript
import { apiClient } from "@clickwire/api-client/v2";

// Login: request a code, then trade it (typed, or the mail link's token) for a token.
// redirect_to is your own absolute URL on the site; the mail link is that URL + link_token.
await apiClient.member.requestLoginCode(
    { email, redirect_to: "https://www.sneakerjagers.com/en/s/slug/123?action=follow", source: "follow" },
    { visitorIp, query: { locale: "en" } },
);
const session = await apiClient.member.verifyLoginCode({ email, code }); // session.redirect_to
const fromLink = await apiClient.member.verifyLoginCode({ link_token }); // from a client-side POST on the landing page, never on the GET (mail scanners)
// -> set session.token as an httpOnly cookie; session.member, session.is_new_member, session.redirect_to

// Per call …
const me = await apiClient.member.get({ memberToken });
const settings = await apiClient.member.settings(); // size systems, preference questions, reminder types, ...
const sneakers = settings.size_types.find((type) => type.slug === "sneakers")!;
await apiClient.member.update({ sizes: { [sneakers.id]: { eu: "42 2/3" } }, preferences: { shopper_types: ["sneakerhead"] }, marketing_emails_accepted_at: true }, { memberToken });
await apiClient.member.uploadAvatar(file, "me.jpg", { memberToken });

// … or per request-scoped client. visitorIp makes Clickwire's per-IP limits per visitor, not per BFF.
const asMember = apiClient.configure({ memberToken, visitorIp });
await asMember.member.followedProducts.follow(productId); // first follow: restock (member's size, else whole product), price, release (if upcoming)
await asMember.member.followedProducts.follow(productId, { price: false }); // one switch off
const { likes_count } = await asMember.member.likedProducts.like(productId);
await asMember.member.followedAttributes.follow(brandAttributeId);
await asMember.member.reminders.create({ type: "restock", product_id, product_size_ids: [sizeId, otherSizeId], url: pdpUrl });
await asMember.member.reminders.create({ type: "price", product_id }); // fires at the website's price_drop_percent
const state = await asMember.member.productState(productId); // is_followed, followed_attribute_ids, reminders
const search = await asMember.member.savedSearches.create({ name: "Nike in 44", filters: { brand_ids: [card.brand_ids[0]], sizes: ["44"] }, frequency: "daily", url: searchPageUrl });
await asMember.member.savedSearches.markSeen(search.id); // new_product_ids empties
const mySize = await asMember.member.productFeed("my_size", { per_page: 24 }); // same response as products.list
await asMember.member.update({ notification_preferences: { saved_searches: [] }, deals_emails_accepted_at: true }); // [] = off

// By e-mail (no token): switches it on for that address, which gets a confirmation; empty 202.
await apiClient.member.reminders.createByEmail({ type: "release", product_id, lead_minutes: 60, email, url: pdpUrl });
await apiClient.member.savedSearches.createByEmail({ email, name: "Nike in 44", filters: { brand_ids: [12] } });
await apiClient.member.unsubscribe(tokenFromMailLink); // any member mail's unsubscribe link (reminder, saved search, deals)
```

在路由处理器中每个请求构建一个客户端( E)`configure({ memberToken })`从来没有 `setConfig({ memberToken })` 在共同实例中,它将贯穿于同时提出的申请。 A 类 `401` 他们的身体 `code: "member_token_required" | "member_token_invalid"` 指访客的代币已去(过期,已登出,账户已删除):清除饼干. 401号没有 `code` 是网站 Bearer 失败 。 全额合同: `docs/api/members.md` 在 Clickwire 重播中.

已注销 : `if (isV2MemberAuthError(error)) { /* clear the cookie */ }`。每一次成功成员呼叫时刷新饼干的最大年龄;符号幻灯片使用90天.

本地开发: 还没有寄出邮件, 因此在 Clickwire Repo 中从 Tinker 中获取一个成员符号 : `Member::findOrCreateForEmail(Website::firstWhere('slug', 'sneakerjagers'), 'me@example.test', MemberSource::Login, 'nl')->createToken('web', ['*'], now()->addDays(90))->plainTextToken`

## 本地测试

在测试客户端中包含本地磁盘中的软件包 :

```json
 "dependencies": {
    "@clickwire/api-client": "file:path/to/vp/packages/api-client",
  },
```

本地端的 api 客户端软件包每次更改时, 您都应该构建软件包然后运行 `npm install` 在你的测试客户端.

## 开发并发布

从 `packages/api-client`数字 :

```bash
npm run typecheck
npm run build
```

### 释放

确保你得到国家预防机制的认可:

```bash
npm login
```

然后运行 :

```bash
npm run release -- <version>
```

替换 `<version>` 与两个 `major`, (中文(简体) ), `minor` 或者说 `patch` 或者设定自己的 `x.x.x`。 。 。 .

## 常见问题

### @clickwire/api-client 是什么？

点击线程 API 客户端

### 如何安装 @clickwire/api-client？

在项目目录运行 npm install @clickwire/api-client，或使用 pnpm add / yarn add / bun add。

### @clickwire/api-client 支持 TypeScript 吗？

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

### @clickwire/api-client 支持 ESM 还是 CommonJS？

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

### @clickwire/api-client 需要什么版本的 Node\.js？

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

### @clickwire/api-client 可以商用吗？

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

### @clickwire/api-client 的下载量有多少？

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

### @clickwire/api-client 还在维护吗？

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

