@clickwire/api-client

中文文档
4.4.0发布于 2026/11/09MITTypeScriptES Module零依赖近 30 天下载 1859

点击线程 API 客户端

中文使用文档
文档目录6 节
  1. 用这个
  2. 全局查询参数
  3. 成员
  4. 本地测试
  5. 开发并发布
  6. 释放

@ clickwire/ api- 客户端

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

用这个

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 查询参数 网站的默认地址大多已经足够.

全局查询参数

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

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 饼干,永远不要交给浏览器.

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'), '[email protected]', MemberSource::Login, 'nl')->createToken('web', ['*'], now()->addDays(90))->plainTextToken

本地测试

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

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

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

开发并发布

从 packages/api-client数字 :

npm run typecheck
npm run build

释放

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

npm login

然后运行 :

npm run release -- <version>

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

版本与发布记录

@clickwire/api-client 共发布 89 个版本,首次发布于 2026/05/06;过去 12 个月发布了 89 个版本。

版本发布日期距今
4.4.0latest2026/11/09今天
4.3.02026/11/054 天前
4.2.02026/11/045 天前
4.1.02026/11/036 天前
4.0.12026/11/036 天前
4.0.02026/11/036 天前

关于 @clickwire/api-client 的常见问题

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