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

@xstools/sdk

v2.0.0-beta.1

Published

Readme

@xstools/sdk

第三方 HTTP API 的薄封装。按 vendor 分子路径发布;根入口导出异常类型和 logger。

pnpm add @xstools/sdk

ESM only。

子路径

| 导入 | Client | | --- | --- | | @xstools/sdk/alicloud | AlicloudClientDysmsapi20170525AlicloudClientOss20190517 | | @xstools/sdk/dingtalk | DingTalkClient | | @xstools/sdk/wechat-miniprogram | WechatMiniprogramClient | | @xstools/sdk/wechat-oplatform | WechatOplatformClient | | @xstools/sdk/wechat-pay | WechatPayClient | | @xstools/sdk/wechat-pay-partner | WechatPayPartnerClient | | @xstools/sdk/xcloud | XcloudClient | | @xstools/sdk/yzh | YzhClient | | @xstools/sdk | SdkException*SdkLogger / SdkLogEvent / SdkClientOptionssdkLoggerConsole / sdkLoggerNoop |

业务代码走 vendor 子路径,不要从根入口 import Client。各子路径导出 Client、业务类型和高级请求选项类型;不导出 Request 实现类。

HTTP 用 method;vendor 操作码用 action(ACS x-acs-action、微信 body action: 'set');SDK 调用身份用 operation。封装方法会带上与方法同名的 operation;直接 doRequest 时默认 'doRequest',也可自行传入。ACS 未传 operation 时回落到 RPC action

用法

import { WechatMiniprogramClient } from '@xstools/sdk/wechat-miniprogram';

const mini = new WechatMiniprogramClient({
  appid: process.env.WX_APPID!,
  appsecret: process.env.WX_APPSECRET!,
});

const session = await mini.code2Session({ js_code: code });

构造函数第二参是可选的 SdkClientOptionsfetch / timeout 交给 HTTP,logger 留在 Client。logger 只记成功 / 进度,失败走异常。默认静默;测试注入 fetch,需要输出时传入 sdkLoggerConsole 或自定义 logger:

import { sdkLoggerConsole } from '@xstools/sdk';

const mini = new WechatMiniprogramClient(config, {
  fetch: mockFetch,
  timeout: 10_000,
  logger: sdkLoggerConsole,
});

开放平台最低基础库版本

WechatOplatformClient.setSupportVersion 会先查询当前最低基础库版本。版本一致时不发送设置请求;传入 checkMode: true 时,版本不一致会抛出 SdkExceptionInternalError,不会修改远端配置。

import { WechatOplatformClient } from '@xstools/sdk/wechat-oplatform';

const client = new WechatOplatformClient(componentConfig);
await client.setSupportVersion({
  authorizer_access_token,
  version: '2.27.3',
  options: { checkMode: true },
});

开放平台隐私 key

setPrivacySettingkeys 是增量配置:SDK 会保留微信当前已有的隐私 key,并确保传入的 key 存在。传入较少的 key 不会删除远端已有项。

未封装的接口

每个 Client 都有泛型 doRequest,用来调用尚未封装的官方接口。各 vendor 子路径会导出对应的 *RequestOption 类型;鉴权、签名、错误码仍走该 vendor 自己的 Request:

const data = await mini.doRequest<{ url_link: string }>({
  method: 'POST',
  path: '/wxa/generate_urllink',
  body: { path: 'pages/index/index' },
});

例如 DingTalk 支持 GET / POST、query 和 JSON body:

import { DingTalkClient, type DingTalkRequestOption } from '@xstools/sdk/dingtalk';

const request: DingTalkRequestOption = {
  method: 'GET',
  path: '/v1.0/custom',
  params: { cursor: 10 },
};
const data = await new DingTalkClient().doRequest<{ errcode: number }>(request);

小程序 Client 的 stable token 缓存在单个 Client 实例内:并发调用共享同一次刷新,失败后下一次调用会重新获取,成功后按上游有效期提前 60 秒刷新。不同 Client 实例不共享 token。

微信支付通知

WechatPayClient.transactionNoticeWechatPayPartnerClient.transactionNotice 只解密并解析已通过 HTTP 接入层验证的通知 resource。它们不接收原始 body 或 Wechatpay-* 请求头,因此不负责回调签名验证、重放处理,也不校验通知中的订单号、商户号和金额是否属于本地订单。

接入层完成验证后再传入 resource;方法返回解密结果后,业务层根据本地订单完成归属、金额、状态和幂等处理。

错误处理

import { SdkException, SdkExceptionInternalError, SdkExceptionLogicRejected, SdkExceptionResponse } from '@xstools/sdk';

try {
  await mini.code2Session({ js_code: code });
} catch (error) {
  if (SdkExceptionResponse.is(error)) {
    // 第三方 HTTP / 业务码失败。error.source / error.operation 标识调用,error.message 是上游错误体
  } else if (SdkExceptionLogicRejected.is(error)) {
    // 可把 error.message 返回给用户,例如内容安全未通过
  } else if (SdkExceptionInternalError.is(error)) {
    // 超时、坏 JSON、本地解码、缺字段等,不要把细节返回给用户
  } else if (SdkException.is(error)) {
    // 其它 SDK 错误
  }
}

SdkExceptionResponse 来自第三方 HTTP 非 2xx 或业务码失败;SdkExceptionLogicRejected 来自本包的业务判断;SdkExceptionInternalError 只用于调试(含超时、网络失败、2xx 却解不开 body)。跨包识别请用静态 is(),不要只靠 instanceof,也不要依赖旧的 __XSTOOLS_SDKS_* tag。

构造异常时使用 source(客户端标识,例如 ALI-OSS,或内部工具 UTILS)和 operation(SDK 调用身份)。message 沿用 Error。原构造参数 client / method 与实例字段 log 已移除。

_tag__XSTOOLS_SDK__EXCEPTION / __XSTOOLS_SDK__EXCEPTION_RESPONSE / __XSTOOLS_SDK__EXCEPTION_LOGIC_REJECTED / __XSTOOLS_SDK__EXCEPTION_INTERNAL_ERROR

OSS 上传与文件错误

AlicloudClientOss20190517.objectPut 接受 BufferArrayBufferSharedArrayBuffer 或 Node 二进制 ReadablelimitSize 单位为 MB(1024 × 1024 字节),默认 1;SDK 会完整读取并识别文件,再按其最终字节数拒绝超限文件,因此不会发送上传请求。字符串 chunk 不属于支持的上传输入;此限制不约束读取过程的内存占用,也不提供读取超时。

文件读取失败和大小超限抛出 SdkExceptionInternalErrorsourceALI-OSSoperationobjectPut,原始错误保存在 cause 链。内部文件/XML 工具 sourceUTILS

objectCopyobjectDeleteobjectMove 接受 object key 或完整的 HTTP(S) URL。SDK 只规范化一次 key,并使用同一 RFC 3986 编码结果构造请求 URL、复制源 header 和签名路径;原始 key 内的空格、?#%! 会作为 key 的组成部分编码,路径分隔符 / 保持不变。

测试

pnpm --filter @xstools/sdk test

该命令运行 bun test --preload ./test/_setup.ts,收集包内测试;全部为离线测试,进入 PR CI(turbo test)。不需要环境变量、密钥或第三方账号。

test/_setup.ts 会在测试启动时预加载,默认禁止真实 fetch;HTTP 场景通过构造函数注入 mock fetch,意外网络调用会使测试失败。直接使用 Bun 时,请在 SDK 包目录运行:

bun test --preload ./test/_setup.ts

通知测试使用虚构数据及本地测试密钥;旧真实 API 场景已迁移到 src/,移除了专用脚本、环境配置及线上通知样例。离线测试验证请求参数、响应映射、签名和解密行为,不验证真实账号权限、外部网络或上游服务状态。ACS3 与 OSS V4 已有固定签名向量;仍不替代真实账号权限或服务端验签验证。

内部文档

维护约定见 docs/architecture.md;HTTP 响应管道见 docs/response.md