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

@secret-momo/cf-bridge

v0.1.0

Published

TypeScript SDK for the cf-bridge Cloudflare Worker

Readme

@secret-momo/cf-bridge

这是 cf-bridge Worker 的 TypeScript SDK,用于访问 D1、R2 和 KV。 SDK 运行时需要 Node.js 20.3 或更高版本;仓库开发和测试使用 Node.js 26.12.1。 这是 SDK 选择的运行时支持范围,并非 AbortSignal.any 最早可用版本的声明。Node.js 18.17 虽已包含该 API,SDK 不承诺 Node.js 18 的兼容性。

安装

npm install @secret-momo/cf-bridge

创建客户端

import { createBridgeClient } from '@secret-momo/cf-bridge';

const bridge = createBridgeClient({
  baseUrl: 'https://cf-bridge.binarykang.workers.dev',
  apiToken: process.env.CF_BRIDGE_API_TOKEN!,
  timeoutMs: 30_000,
});

apiToken 会作为每次请求的 x-api-token 请求头发送。请将令牌保存在服务端环境中,不要放进浏览器代码。 SDK 拒绝所有 HTTP 重定向(包括同源重定向),请将 baseUrl 配置为最终接口地址;注入的自定义 fetch 也需要遵守 redirect: 'error' 选项。 请求默认在等待响应头超过 30 秒时取消;可通过 timeoutMs 调整,设为 0 则关闭。该计时包括上传请求体和等待服务端处理的时间;收到响应头后会清除计时器,后续下载或 JSON 响应体读取不受此超时限制。上传大对象或执行较慢的批量 SQL 时,请按需调整。 客户端的 signal 可统一取消请求,每个方法的最后一个参数也接受 { signal };两者均可中断后续响应体读取。传入依赖 this 的自定义 fetch 方法时,请先绑定所属对象,例如 fetch: api.fetch.bind(api)。

SDK 默认不为响应体读取设置截止时间。若需要限制包含下载在内的整个请求,请显式传入有截止时间的 signal;以下信号从创建起 5 分钟后取消,响应头仍受客户端 timeoutMs 约束:

const download = await bridge.r2.get('big.bin', {
  signal: AbortSignal.timeout(5 * 60_000),
});

D1

default、v2ex 和 nexus 是可选的数据库名称。使用 execute 执行单条建表、修改表或写入语句,使用 query 获取查询结果;动态值通过 params 绑定。

await bridge.d1.execute('default', {
  sql: 'CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, text TEXT)',
});

await bridge.d1.execute('default', {
  sql: 'INSERT INTO notes (text) VALUES (?)',
  params: ['你好'],
});

const { results, meta } = await bridge.d1.query<{ id: number; text: string }>('default', {
  sql: 'SELECT id, text FROM notes WHERE text = ?',
  params: ['你好'],
});

多条语句使用 batch。同一批次中的语句会按顺序在一个事务中执行,失败时回滚。

布尔参数写入 D1 时保存为整数 1 或 0,读取时返回数字。当前网关不支持通过 JSON 参数写入 BLOB。执行语句的 results 字段可能为 null;查询方法的 results 始终是数组。

const batchResults = await bridge.d1.batch('v2ex', [
  { sql: 'CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT)' },
  { sql: 'INSERT INTO items (name) VALUES (?)', params: ['示例'] },
]);

R2

put 直接上传二进制内容;第三个参数可设置对象的内容类型。get 返回标准 Response,可以读取响应头并按需消费字节流。

put 当前只写入对象内容和 Content-Type,不写入自定义元数据。list({ include: ['customMetadata'] }) 可读取同一存储桶中已有的自定义元数据,例如由其他工具写入的元数据。

await bridge.r2.put('docs/hello.txt', new Blob(['你好']), 'text/plain');

const response = await bridge.r2.get('docs/hello.txt');
const text = await response.text();
const contentType = response.headers.get('content-type');

const page = await bridge.r2.list({ prefix: 'docs/', limit: 100 });
const folders = await bridge.r2.list({
  prefix: 'docs/',
  delimiter: '/',
  include: ['httpMetadata'],
});
const nextPage = page.cursor
  ? await bridge.r2.list({ prefix: 'docs/', cursor: page.cursor, limit: 100 })
  : null;

await bridge.r2.delete('docs/hello.txt');

KV

KV 存储字符串。若要保存对象,请自行进行 JSON 序列化和解析。写入时可指定过期秒数 expirationTtl 和 JSON 元数据。KV 采用最终一致性,不适合依赖即时读取结果的协调逻辑。

await bridge.kv.put('settings:theme', JSON.stringify({ theme: 'dark' }), {
  expirationTtl: 3600,
  metadata: { owner: 'app' },
});

const entry = await bridge.kv.get('settings:theme');
const settings = JSON.parse(entry.value);
const metadata = entry.metadata;

const page = await bridge.kv.list({ prefix: 'settings:', limit: 100 });
const nextPage = page.cursor
  ? await bridge.kv.list({ prefix: 'settings:', cursor: page.cursor, limit: 100 })
  : null;

await bridge.kv.delete('settings:theme');

错误处理

除成功的 R2 下载外,SDK 会取出统一响应中的 data 并返回。请求失败时抛出 BridgeError,其中包含 HTTP 状态码 status、业务码 code 和错误信息 message。

import { BridgeError } from '@secret-momo/cf-bridge';

try {
  await bridge.kv.get('missing');
} catch (error) {
  if (error instanceof BridgeError && error.status === 404) {
    // 键不存在
  }
}