SQLBraid Vibe 项目
在 TypeScript 里直接写 SQL,不引入任何查询构建器的抽象层,让数据库操作回归 SQL 本来面貌
项目简介
SQLBraid 是一个以 SQL 为核心的 TypeScript 数据访问工具包,核心理念是「写 SQL,留在 TypeScript 里,不妥协」。它不引入查询构建器(Query Builder)的抽象层,不要求你用链式方法拼接条件,而是让你直接在模板字符串里写标准 SQL,同时通过类型安全的方式处理参数绑定、动态 SQL、结果映射和数据库驱动隔离。
项目已发布 1.0.0 稳定版,支持 PostgreSQL、MySQL、MariaDB、Node.js 原生 SQLite、better-sqlite3、libsql、SQLite WASM、Cloudflare D1、Oracle、MS SQL Server 等十余种数据库驱动。
核心功能
SQL 模板标签(Tagged Template Literals):用带类型的模板标签写 SQL,内联参数用 $的内联语法自动做安全绑定,永远不是字符串拼接。
结构化动态 SQL:通过 @braid 指令(if、choose、when、otherwise、where、set、trim)构建动态查询,编译器在编译阶段处理条件分支,非活动分支保持惰性不参与渲染,输出结果始终是单一安全的 RenderedStatement。
多驱动适配:统一入口,按需引入具体驱动子包(pg、mysql2、better-sqlite3 等),不同数据库切换只需换子包路径,核心业务代码不变。
显式结果契约:查询结果通过 TypeScript 泛型约束映射到指定接口类型,编译器保证返回结构与代码声明一致,减少运行时类型错误。
Standard Schema 映射:支持 Standard Schema 规范的结果类型映射,便于在类型层面与外部生态对齐。
驱动自有传输层:占位符格式($1、?、:1、@p1)是传输层细节,不是逻辑层面身份,同一个逻辑 SQL 在不同驱动下渲染为对应数据库的占位符语法。
技术实现
SQLBraid 的架构设计理念是把「语法层」和「传输层」完全解耦。模板标签接收用户书写的 SQL 片段和参数值,经过渲染器输出一个不可变的逻辑 RenderedStatement 对象,其 segments 数组长度始终等于 parameters 数组长度加一,保证参数永远不会以 SQL 片段、标识符、嵌套查询或驱动特有片段的形式出现。
动态 SQL 指令(@braid if、@braid choose 等)在编译时由编译器处理,而非运行时拼接,这意味着即使条件不满足,相关 SQL 片段也不会进入渲染管线,杜绝了传统字符串拼接式 SQL 动态构建的安全隐患。
项目采用分层包结构:根包本身不绑定任何数据库引擎,仅导出公共运行时契约;具体数据库支持分散在独立的子包中,例如 sqlbraid/node-sqlite 依赖 Node.js 22.18+ 内置的 node:sqlite 模块,而 sqlbraid/better-sqlite3 则依赖第三方同步驱动,调用方式一致但物理层实现各异。
支持的 Node.js 运行时包括 Node 22.18 及以上版本,Deno 场景下流式查询(streaming)会被主动拒绝并报错 BRAID_STREAM_UNSUPPORTED,而非静默截断数据,这是针对 Deno 2.9.3 特殊行为的显式适配。
快速上手
第一步:安装依赖
运行 pnpm add sqlbraid 安装核心包,再安装目标驱动包,如使用 Node.js 内置 SQLite:npm install @types/node@22
第二步:初始化数据库连接
以 Node.js 内置 SQLite 为例,创建内存数据库并初始化连接:
import { DatabaseSync } from 'node:sqlite'; import { createNodeSqliteDatabase, sql } from 'sqlbraid/node-sqlite'; const native = new DatabaseSync(':memory:'); const db = createNodeSqliteDatabase(native);
第三步:执行带类型约束的查询
定义 TypeScript 接口约束返回类型,用模板标签执行查询:
interface UserRow { id: string; name: string; }
const users = await db.all(sql.rowsSELECT id, name FROM users WHERE id = ${requestedId});
第四步:构建动态查询
使用 @braid 指令处理可选过滤条件,编译阶段完成分支处理,不会引入运行时 SQL 注入风险:
const query = sql.rowsSELECT id, name FROM users /*@braid where*//*@braid if ${teamId != null}*/ AND team_id = ${teamId}/*@braid end*//*@braid end*/;
适用人群
熟悉 SQL 且在 TypeScript/Node.js 生态下做后端开发的工程师,尤其是对查询构建器抽象层有抵触、想要直接掌控 SQL 行为的团队。不适合完全不想写 SQL 的全栈工程师。
评论与建议
登录 后参与评论或提建议