TSts-grm

SQL 拦截器(实体过滤器)

有些条件应该对某实体的所有查询生效——软删除(排除已删行)、多租户、行级权限。手写进每个查询容易漏;FilterManager 把它做成机制:注册一次,自动注入所有查询。

沙盒真实演示:软删除 task

示例数据中有 task 表(id/title/deleted_at,含一行已软删除),下面的完整示例可直接运行:

// ① 导入:model/prop/dto 建模型;FilterManager 从 @ts-grm/sql 导入;
//    createFilteredClient 是示例提供的 client 工厂(仅可带 filterManager)
import { model, prop, dto } from '@ts-grm/core'
import { FilterManager } from '@ts-grm/sql'
import { createFilteredClient, sqlClient } from './infra/sql-client'

// ② 模型:task 含 deletedAt(时间戳;非空 = 已软删除)
const Task = model("Task", "id", class {
    id = prop.i64()
    title = prop.str(50)
    deletedAt = prop.dt().nullable()
})

// ③ 注册软删除过滤器:谓词 = deleted_at is null
const filterManager = new FilterManager()
filterManager.add(Task, t => t.deletedAt.isNull())

// ④ 用带过滤器的 client 查询:所有 task 查询自动 AND deleted = false
const client = createFilteredClient({ filterManager })
const tasks = await client.createQuery(Task, (q, t) => {
    return q.select(t.fetch(dto.view(Task, c => [c.id, c.title])))
}).fetchList()

console.log('过滤器 client(自动排除已删):')
console.log(tasks)

// ⑤ 对照:默认 client 无过滤器,能看到全部(含已删行)
const all = await sqlClient.createQuery(Task, (q, t) => {
    return q.select(t.fetch(dto.view(Task, c => [c.id, c.title])))
}).fetchList()

console.log('默认 client(含已删行):', all)

运行结果:过滤器 client 只返回未删除的 2 行(“旧需求”被自动排除),默认 client 返回 3 行含已删——同一个模型,有无拦截器带来不同查询语义

机制

const filterManager = new FilterManager()
filterManager.add(MODEL, table => 谓词)     // Filter = (table) => Predicate | undefined
const client = newSqlClient(driver, { filterManager })   // 挂到 client 即全量生效
  • 谓词与查询内 q.where(...) AND 叠加,对 findMany/createQuery/子查询/计数全部生效;
  • 返回 undefined 表示该查询不附加约束(可选过滤);
  • 示例工作区提供了 createFilteredClient(仅透传 filterManager);真实项目直接用 newSqlClientfilterManager 选项。

典型场景

场景过滤器谓词
软删除row => row.deletedAt.isNull()
多租户行隔离row => row.tenantId.eq(currentTenant)
行级权限row => row.ownerId.in(currentUserVisibleIds)
默认数据范围row => row.status.ne("ARCHIVED")

把"惯例"沉淀成拦截器后,新写查询天然合规——少一个忘记过滤的坑。要临时放行(管理后台看已删数据)就注册时为"默认 client"与"管理 client"分别配置过滤器,而不是绕过规则。

下一步

SQL 后端七页收束:驱动 → 命名 → 事务 → 方言 → 日志 → 模式创建 → 拦截器。「API 参考」提供速查。