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

drizzle-http-driver

v0.1.3

Published

A transaction-capable PostgreSQL HTTP driver for Drizzle ORM

Readme

drizzle-http-driver

一个通过 HTTP 使用 PostgreSQL 的 Drizzle ORM driver。查询 API 与 Drizzle PostgreSQL 保持一致,并通过服务端绑定 transaction_id 的方式支持事务、嵌套事务和 savepoint。

安装

pnpm add drizzle-http-driver drizzle-orm

创建数据库实例

schema、logger 和 casing 等 Drizzle 配置仍然传给 drizzle

import { drizzle, DrizzleProxyClient } from 'drizzle-http-driver';

import * as schema from './schema';

const client = new DrizzleProxyClient({
  endpoint: process.env.DB_PROXY_ENDPOINT!,
  token: process.env.DB_PROXY_TOKEN!,
  key: process.env.DB_PROXY_KEY!,
});

export const db = drizzle(client, { schema });

配置按照 endpoint → token → key 的顺序定位数据库:

  1. endpoint:接收 Drizzle 查询请求的 HTTP 端点。
  2. token:租户级访问令牌,用于识别租户并验证该租户的访问权限。driver 会将它写入 x-db-token 请求头。
  3. key:当前租户下已经配置好的完整数据库连接标识,例如 devstagingprod。它代表一套完整数据库连接配置,而不只是数据库名称。

因此,同一个 endpoint 可以服务多个租户;一个租户通过 token 完成权限校验后,再使用 key 选择该租户下具体的数据库连接。

之后直接使用标准 Drizzle API:

import { eq } from 'drizzle-orm';

const rows = await db.select().from(schema.users);

await db
  .update(schema.users)
  .set({ name: 'new name' })
  .where(eq(schema.users.id, userId));

事务

顶层事务会生成一个 transaction_id。事务内的所有 HTTP 请求都会携带相同的 id, 服务端必须让这个 id 始终命中同一个 PostgreSQL connection。

await db.transaction(async (tx) => {
  const [user] = await tx
    .insert(schema.users)
    .values({ name: 'Ada' })
    .returning();

  await tx.insert(schema.profiles).values({ userId: user.id });

  await tx.transaction(async (nested) => {
    await nested.insert(schema.auditLogs).values({ userId: user.id });
  });
}, {
  accessMode: 'read write',
  isolationLevel: 'serializable',
});

成功时 driver 执行 commit;异常或 tx.rollback() 时调用 release 接口,由代理执行 rollback 并释放连接。嵌套事务使用 savepoint

HTTP 协议

endpoint 必须是完整的查询地址,例如 https://example.com/api/query。driver 先通过请求头中的 token 确认租户访问权限,再通过请求体中的 key 定位该租户下的数据库连接:

POST <endpoint>
content-type: application/json
x-db-token: <tenant-access-token>
{
  "key": "prod",
  "method": "all",
  "params": [1],
  "sql": "select * from users where id = $1",
  "transaction_id": "optional-transaction-id"
}
  • method: "all":服务端返回对象行。
  • method: "values":服务端必须按 SQL 列顺序返回数组行,供 Drizzle 完成字段解码。
  • 非事务请求不发送 transaction_id;事务请求使用 driver 生成的同一个 id。
  • x-db-token 携带租户访问令牌;key 只能在该 token 对应的租户范围内解析。

代理返回统一的成功响应,driver 会解包其中的 data 交给 Drizzle:

{
  "success": true,
  "data": {
    "command": "SELECT",
    "fields": [],
    "oid": 0,
    "rowCount": 1,
    "rows": [{ "id": 1 }],
    "timing": {
      "coldStart": false,
      "startedAt": 1792600000000,
      "tokenStartedAt": 1792600000001,
      "dbConfigStartedAt": 1792600000002,
      "connectionStartedAt": 1792600000004,
      "connectionEstablishedAt": 1792600000006,
      "endedAt": 1792600000012
    }
  }
}

任何非 2xx HTTP 状态码都会使整次请求失败。失败响应中的 error 会作为 DrizzleProxyError 的错误消息:

{
  "success": false,
  "error": "permission denied for table users"
}

事务未正常结束时,driver 向 ${endpoint}/release(即文档中的 /api/query/release)发送:

{
  "key": "prod",
  "transaction_id": "transaction-uuid"
}

release 请求继续使用同一个租户 token 和数据库 key。代理即使找不到对应事务,也会返回 { "success": true, "data": null };driver 会校验这份统一响应。commit 成功后代理已经 释放连接,driver 不再重复调用 release。

请求配置

DrizzleProxyConfig 支持额外 headers 和共享 requestInit。请求固定使用 JSON,序列化时 会把 bigint 转成十进制字符串。

const client = new DrizzleProxyClient({
  endpoint: 'https://example.com/api/query',
  token: process.env.DB_PROXY_TOKEN!,
  key: 'prod',
  headers: { 'x-client-name': 'admin-api' },
});

构建和发布

pnpm install
pnpm build
pnpm publish

Vite 会在 dist 中生成 ESM、CommonJS、类型声明。