# @chromav/frizzle 中文文档

规范地址：https://npmcn.com/package/%40chromav/frizzle/

版本：0\.4\.6
npm 元数据更新时间：2026-10-23T00:09:56.044Z
中文译文更新时间：2026-11-09T15:14:12.798Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40chromav/frizzle
原文对照：https://npmcn.com/package/%40chromav/frizzle/?lang=original
项目主页：https://github.com/chroma-v/kindling/tree/main/packages/frizzle#readme
源码仓库：https://github.com/chroma-v/kindling

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：335 kB，100 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：drizzle-orm \>=0\.30\.0 \|\| \>=1\.0\.0-beta\.1
- 首次发布：2026-08-25T04:24:29.778Z
- 最新版本发布：2026-10-23T00:09:55.871Z
- 近 30 天下载量：7084（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：11（近 12 个月 11 个）

## 中文简介

一个有趣的,类型安全的查询编译器,带有解析器-组合器语法,可插接代码生成器,以及内置验证. 过滤、 排序和查询您的数据 .

## 安装

```sh
npm install @chromav/frizzle
```

也可以使用：`pnpm add @chromav/frizzle`、`yarn add @chromav/frizzle`、`bun add @chromav/frizzle`

## README

# 微风

一个类型安全查询编译器和服务层工具包. 解析URL-安全过滤字符串,编译为数据库查询(Drizzle ORM或生于SQL),并作曲截取器管道用于范围界定,软删除,以及审计线索——但投出零个例外.

```
?filter=status eq 'active' AND priority eq 'high'&sort=createdAt:desc&limit=50
```

## 安装

```bash
npm install @chromav/frizzle
```

Drizzle ORM是一种可选的对等依赖——只有在使用 Drizzle 代码生成器时才需要.

```bash
npm install drizzle-orm  # if using @chromav/frizzle/drizzle
```

对等范围是 `>=0.30.0 || >=1.0.0-beta.1`。 RQB `compileFilter` 需要细雨-orm 1.0(β/rc),因为它的输出使用v2关系-query对象过滤语法(`OR`, (中文(简体) ), `AND`, (中文(简体) ), `RAW`),而细雨-orm 0.x没有. `compileFilterToSQL` 财务报告和审定财务报表 `@chromav/frizzle/sql` 整个范围的工作.

## 快速启动

### 过滤查询

```typescript
import { isSuccess } from "@chromav/frizzle";
import { compileFilter } from "@chromav/frizzle/drizzle";

const result = await compileFilter(
  "status eq 'active' and priority eq 'high'",
  { status: "status", priority: "priority" }
);

if (isSuccess(result)) {
  const tasks = await db.query.tasks.findMany({
    where: result.data,
  });
}
```

`compileFilter` 目标 Drizzle 的关系查询(`db.query.*`)和需要细雨1.0(β/弧);见 [安装](https://npmcn.com/package/%40chromav/frizzle/#readme-install)。要添加您自己的条件,请将两者包入 `AND` —— 说 `{ AND: [{ workspaceId }, result.data] }` - 而不是传播 `result.data`,可以让用户过滤器替换您的密钥.

### 过滤器 + 排序并进行计划验证

```typescript
import { isSuccess } from "@chromav/frizzle";
import { compileFilter, compileSort } from "@chromav/frizzle/drizzle";
import type { Schema } from "@chromav/frizzle";

const schema: Schema = {
  status: { type: "enum", enumValues: ["active", "pending", "done"] },
  priority: { type: "enum", enumValues: ["low", "medium", "high"] },
  title: { type: "string" },
  createdAt: { type: "date" },
};

const columns = {
  status: "status",
  priority: "priority",
  title: "title",
  createdAt: "createdAt",
};

// Validates field names, operators, and value types before compiling
const filterResult = await compileFilter(
  "status eq 'active' and title contains 'deploy'",
  columns,
  { schema }
);

const sortResult = compileSort("createdAt:desc", columns);

if (isSuccess(filterResult) && isSuccess(sortResult)) {
  const tasks = await db.query.tasks.findMany({
    where: filterResult.data,
    orderBy: sortResult.data,
  });
}
```

### SQL 构建器替代品( Drizzle)

```typescript
import { isSuccess } from "@chromav/frizzle";
import { compileFilterToSQL } from "@chromav/frizzle/drizzle";

// Pass Drizzle column objects instead of strings
const result = compileFilterToSQL("status eq 'active'", {
  status: tasks.status,
  priority: tasks.priority,
});

if (isSuccess(result)) {
  const rows = await db.select().from(tasks).where(result.data);
}
```

### 在代码中构建过滤器, 验证一次

有两个层次可以结合,每个层次都有自己的 `and` 编号 : `or`数字 :

| 你有过 | 与 | 实例 |
| --- | --- | --- |
| **过滤树**在汇编之前: `parseFilter` 返回,或从 `f` 建设者 | `f.and`, (中文(简体) ), `f.or` | 然后用简略的参数输入用户过滤器 `validateFilter` |
| **对象**,在编译后: `compileFilter` 输出、范围、描述过滤器 | `andWhere`, (中文(简体) ), `orWhere` | 和一个编译的用户过滤器 `{ workspaceId }` |

当可以时,更倾向于将树组合在一起:结果通过一个过滤器来验证(限制,计划).

```typescript
import { f, isError, validateFilter } from "@chromav/frizzle";
import { generateDrizzleQuery } from "@chromav/frizzle/drizzle";

// f.and / f.or skip undefined, and group an or inside an and so the tree means what it says
const filter = f.and(
  userFilter,                                        // e.g. from parseFilter(params.filter)
  region ? f.in("region", region.split(",")) : undefined,
);

// Schema checks plus the limits (maxParameters etc.) on the combined tree.
// On an error, reject the request: running the query without the filter
// would also drop the region restriction.
const valid = filter ? validateFilter(filter, schema) : undefined;
if (valid && isError(valid)) {
  return badRequest(valid.error);
}

// One field map filters and sorts: `name` is filtered through a resolver, sorted by its column
const query = generateDrizzleQuery(
  { filter: valid?.data, sort: [{ field: "name", direction: "asc" }] },
  db.select().from(countries).$dynamic(),
  { region: countries.region, name: { column: countries.name, where: nameOrAlias } },
  { db }, // passed to resolvers as their third argument
);
```

见 [Schema 验证](https://npmcn.com/package/%40chromav/frizzle/docs/schema-validation.md#validating-filters-built-in-code) 财务报告和审定财务报表 [Drizzle 整合](https://npmcn.com/package/%40chromav/frizzle/docs/drizzle-integration.md#one-map-for-filtering-and-sorting)。 。 。 .

### 原始 SQL 目标

对于数据库 Drizzle 不覆盖(例如:Trino, Spark, Iceberg):

```typescript
import { compileSelect } from "@chromav/frizzle/sql";
import { sqliteDialect } from "@chromav/frizzle/sql";

const columns = { status: "status", priority: "priority", createdAt: "created_at" };

const { sql, parameters } = compileSelect("tasks", {
  filter: { status: "active", priority: { gte: 3 } },
  sort: { createdAt: "desc" },
  take: 20,
}, columns, sqliteDialect);

// sql: SELECT * FROM "tasks" WHERE "status" = ? AND "priority" >= ? ORDER BY "created_at" DESC LIMIT ?
// parameters: ["active", 3, 20]
```

### 拦截管道

将贯穿各领域的关切编为可重复使用的拦截器:

```typescript
import {
  scopeQueryInterceptor,
  softDeleteQueryInterceptor,
  scopeWriteInterceptor,
  softDeleteWriteInterceptor,
  injectWriteInterceptor,
} from "@chromav/frizzle";

// Read pipeline: every query is scoped to workspace + excludes deleted
const queryInterceptors = [
  scopeQueryInterceptor({ workspaceId: "ws-123" }),
  softDeleteQueryInterceptor(),
];

// Write pipeline: scope + audit + soft-delete transform
const writeInterceptors = [
  scopeWriteInterceptor({ workspaceId: "ws-123" }),
  injectWriteInterceptor("user-456"),
  softDeleteWriteInterceptor("user-456"),
];
```

## 查询语法

### 过滤操作符

| 运算符 | 类别 | 示例 |
| --- | --- | --- |
| `eq`, (中文(简体) ), `ne` | 比较 | `status eq 'active'` |
| `gt`, (中文(简体) ), `gte`, (中文(简体) ), `lt`, (中文(简体) ), `lte` | 比较 | `age gte 18` |
| `like`, (中文(简体) ), `ilike` | 字符串( 子字符串) | `name like 'john'` |
| `contains`, (中文(简体) ), `starts_with`, (中文(简体) ), `ends_with` | 字符串 | `title contains 'deploy'` |
| `in`, (中文(简体) ), `not_in` | 阵列 | `status in ['active', 'pending']` |
| `between` | 范围 | `age between [18, 65]` |
| `is_null`, (中文(简体) ), `is_not_null` | 无效检查 | `assignedTo is_null` |

符号别名也起作用 : `=`, (中文(简体) ), `!=`, (中文(简体) ), `>`, (中文(简体) ), `>=`, (中文(简体) ), `<`, (中文(简体) ), `<=`。 。 。 .

字符串运算符字面匹配值 : `%` 财务报告和审定财务报表 `_` 普通字符,而不是通配符(`title contains '50%'` 找到文本 `50%`) (中文(简体) ).

### 逻辑操作符

```
status eq 'active' and priority eq 'high'
status eq 'active' or status eq 'pending'
(status eq 'active' or status eq 'pending') and priority eq 'high'
```

`AND` 绑定比 `OR`。父体优先.

### 排序和标记

```
sort=name:asc,createdAt:desc
limit=50
offset=100
```

排序方向必须是 `asc` 或者说 `desc`· ; `limit` 必须是从 1 到 1 的整数 `maxLimit` (默认 1000)和 `offset` 非负整数。 其他的都是个 `INVALID_VALUE` 错误.

### 限制

滤波器被封顶在32个等高的括号内(`maxDepth`),100个值(`maxParameters`,匹配 Cloudflare D1 的有限参数上限),和 1000 个比较(`maxConditions`) (中文(简体) ). 超越者返回 a `LIMIT_EXCEEDED` 错误。 超过每个电话,例如. `compileFilter(expr, columns, { maxParameters: 50 })`。见 [限制](https://npmcn.com/package/%40chromav/frizzle/docs/query-language.md#limits)。 。 。 .

## 处理错误

所有行动返回 `Result<T>` -没有例外.

```typescript
import { isSuccess, isError } from "@chromav/frizzle";

const result = await compileFilter("bad ?? syntax", columns);

if (isError(result)) {
  result.error.message;     // "Expected operator, got '?'"
  result.error.position;    // 4
  result.error.code;        // "SYNTAX_ERROR"
  result.error.suggestions; // Possible fixes (e.g. close field names, for UNKNOWN_FIELD)
}
```

## 条目点

| 导入 | 目录 |
| --- | --- |
| `@chromav/frizzle` | 核心:编译器,解析器,AST类型,结果类型,计划类型,查询字符串解析器,描述器,截取器 |
| `@chromav/frizzle/drizzle` | 滴入 ORM : `compileFilter`, (中文(简体) ), `compileFilterToSQL`, (中文(简体) ), `compileSort`, (中文(简体) ), `DrizzleCodeGenerator` |
| `@chromav/frizzle/sql` | 原始 SQL : `compileSelect`, (中文(简体) ), `compileFilter`, (中文(简体) ), `compileFilterNode`, (中文(简体) ), `compileInsert`, (中文(简体) ), `compileUpdate`, (中文(简体) ), `compileDelete`, (中文(简体) ), `Dialect`, (中文(简体) ), `sqliteDialect` |

核心包的依赖性为零. `@chromav/frizzle/drizzle` 需求 `drizzle-orm` 作为同伴的依赖. `@chromav/frizzle/sql` 没有依赖关系.

## 说明

Frizzle在到达数据库适配器之前,使用通过拦截管流出的数据库不可知中间表示.

**`QueryDescriptor`** 描述读取操作:

```typescript
import { mergeDescriptors } from "@chromav/frizzle";
import type { QueryDescriptor } from "@chromav/frizzle";

// A QueryDescriptor is a plain object; mergeDescriptors combines two
const base: QueryDescriptor = { filter: { workspaceId: "ws-1" } };
const descriptor = mergeDescriptors(base, {
  filter: { status: "active" },
  sort: { createdAt: "desc" },
  take: 20,
  skip: 0,
  select: { id: true, title: true, status: true },
  include: { assignee: true },
});
```

**`WriteDescriptor`** 描述一个写入操作:

```typescript
import { createWriteDescriptor, mergeWriteDescriptor } from "@chromav/frizzle";

// Insert
const insert = createWriteDescriptor("insert", { title: "New task", status: "backlog" });

// Update
const update = mergeWriteDescriptor(
  createWriteDescriptor("update", { status: "done" }),
  { targetIds: ["task-1", "task-2"] },
);

// Delete
const remove = mergeWriteDescriptor(
  createWriteDescriptor("delete"),
  { targetIds: ["task-3"] },
);
```

## 参考截取器

共同事务层模式的可再使用实施。 全部从主出口 `@chromav/frizzle` 进入点.

### 查询拦截器

| 截取器 | 说明 |
| --- | --- |
| `scopeQueryInterceptor(fields)` | 在每个查询中添加租户/工作空间过滤器 |
| `softDeleteQueryInterceptor(config?)` | 不包括被软删除的行`isDeleted: false`(中文(简体) ) |
| `defaultIncludesInterceptor(defaults)` | 深层默认关系包括 |
| `extraScopeInterceptor(scopeFn)` | 从工厂中添加特定实体过滤条件 |

### 写入截取器

| 截取器 | 说明 |
| --- | --- |
| `scopeWriteInterceptor(fields)` | 将范围值输入到每个写入中 |
| `softDeleteWriteInterceptor(userId, config?)` | 变换删除 更新方式 `isDeleted: true` |
| `injectWriteInterceptor(userId, config?)` | 喷出 `createdById` 插入时, `updatedById` 更新 |
| `extraScopeWriteInterceptor(scopeFn)` | 插入额外范围字段 |

所有截取器都是通用的(可配置的列名,通用范围字段)并只使用frizzle自己的类型——0外在依赖.

## SQL 目标

这个 `@chromav/frizzle/sql` 出入口编译了参数化的SQL字符串的描述符. 它支持任何 SQL 数据库通过 `Dialect` 接口.

### 对话框接口

```typescript
import type { Dialect } from "@chromav/frizzle/sql";

const trinoDialect: Dialect = {
  name: "trino",
  quoteIdentifier: (name) => `"${name}"`,
  parameter: (index) => `$${index + 1}`,
  booleanLiteral: (v) => v ? "TRUE" : "FALSE",
  supportsILike: true,
  escapeLikePattern: (p) => p.replace(/[%_\\]/g, "\\$&"),
};
```

### 写入操作

```typescript
import { compileInsert, compileUpdate, compileDelete } from "@chromav/frizzle/sql";
import { createWriteDescriptor, mergeWriteDescriptor } from "@chromav/frizzle";
import { sqliteDialect } from "@chromav/frizzle/sql";

const insert = createWriteDescriptor("insert", { title: "Task", status: "backlog" });
const { sql, parameters } = compileInsert("tasks", insert, sqliteDialect);
// sql: INSERT INTO "tasks" ("title", "status") VALUES (?, ?)

const update = mergeWriteDescriptor(
  createWriteDescriptor("update", { status: "done" }),
  { targetIds: ["t-1"] },
);
const { sql, parameters } = compileUpdate("tasks", update, sqliteDialect);
// sql: UPDATE "tasks" SET "status" = ? WHERE "id" = ?
```

## 建筑

```
URL query string
    ↓ parseQueryString()
QueryDescriptor (database-agnostic IR)
    ↓ interceptor pipeline (scope, soft-delete, inject, ...)
QueryDescriptor (enriched)
    ↓ adapter
    ├── @chromav/frizzle/drizzle → Drizzle RQB findMany/findFirst
    └── @chromav/frizzle/sql     → parameterized SQL string
```

## 文档

### 核心

-   **[开始](https://npmcn.com/package/%40chromav/frizzle/docs/getting-started.md)** ——两种方法,结构概述,每个步骤产生什么
-   **[说明](https://npmcn.com/package/%40chromav/frizzle/docs/descriptors.md)** – 查询描述器和写入描述器作为数据库不可知的IRs
-   **[截取器](https://npmcn.com/package/%40chromav/frizzle/docs/interceptors.md)** ——管道概念,参考实施,自写
-   **[查询语言](https://npmcn.com/package/%40chromav/frizzle/docs/query-language.md)** – 完整的语法参考,每个操作符都有示例
-   **[Schema 验证](https://npmcn.com/package/%40chromav/frizzle/docs/schema-validation.md)** – 字段类型,操作员相容性,运行时谜题
-   **[处理错误](https://npmcn.com/package/%40chromav/frizzle/docs/error-handling.md)** - 结果类型、错误代码、弹性模式
-   **[查询谱 (EBNF)](https://npmcn.com/package/%40chromav/frizzle/docs/query-spec.md)** - 正式语法

### 数据库目标

-   **[Drizzle 整合](https://npmcn.com/package/%40chromav/frizzle/docs/drizzle-integration.md)** ——RQB vs SQL,列映射,嵌入路径,解析器
-   **[Drizzle 代码生成器](https://npmcn.com/package/%40chromav/frizzle/docs/drizzle-code-generator.md)** ——审定规则,增加运算符,测试覆盖范围
-   **[SQL 目标](https://npmcn.com/package/%40chromav/frizzle/docs/sql-target.md)** —— Raw SQL 编译器,方言界面,所有编译器和操作器

### 指南

-   **[食谱](https://npmcn.com/package/%40chromav/frizzle/docs/recipes.md)** – Express, Hono, Next.js, React Router 例 + filter UI 模式
-   **[URL 示例](https://npmcn.com/package/%40chromav/frizzle/docs/url-examples.md)** — 50+ 真实世界 URL 查询模式

## 许可证

麻省理工学院

## 常见问题

### @chromav/frizzle 是什么？

一个有趣的,类型安全的查询编译器,带有解析器-组合器语法,可插接代码生成器,以及内置验证\. 过滤、 排序和查询您的数据 \.

### 如何安装 @chromav/frizzle？

在项目目录运行 npm install @chromav/frizzle，或使用 pnpm add / yarn add / bun add。

### @chromav/frizzle 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @chromav/frizzle 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @chromav/frizzle 可以商用吗？

@chromav/frizzle 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @chromav/frizzle 的下载量有多少？

根据 npm 官方下载统计，@chromav/frizzle 在 2026/10/10 – 2026/11/08 这 30 天内被下载 7,084 次，日均约 236 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @chromav/frizzle 还在维护吗？

最新版本 0\.4\.6 发布于 2026/10/23（17 天前）；至今共发布 11 个版本，其中过去 12 个月发布了 11 个；首次发布于 2026/08/25。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

