TSts-grm

自定义数据类型

前置:模型的属性声明请先看 「属性与类型」(本页是其「自定义数据类型」专述)。

内置标量(i64/str/num/…)覆盖多数列。当列的真实语义是“更高级的类型”时(二进制、特定编码、图片对象、自定义枚举存储),用 ScalarProvider 定义自定义数据类型

结构:值类型 + SQL 类型 + 双向转换

import { ScalarProvider, ScalarType, prop, scalars } from '@ts-grm/core'
import { z } from 'zod'

const binaryProvider = ScalarProvider.of({
    valueType: z.instanceof(Uint8Array),   // 值的 TypeScript 语义(StandardSchemaV1)
    sqlType: ScalarType.binary(1024),      // 底层 SQL 类型(BINARY(1024))
    toValue: (sqlValue) => sqlValue,       // 数据库值 → 应用值
    toSql: (value) => value,               // 应用值 → 数据库值
})

// 挂到模型属性
image = prop.scalar(binaryProvider)

三个要求:

  • valueType 必须不含 null/undefined(可空用 .nullable() 表达);
  • toValue / toSql 负责数据库 ↔ 应用的形状转换;
  • 结果:属性在 TS 里是 z.instanceof(...) 推导出的类型,库里仍按 sqlType 存取。

json / jsonb 就是它的实例

prop.json(schema) / prop.jsonb(schema) 的实现就是 ScalarProvidervalueType 是传入的 zod(StandardSchemaV1),sqlType 是 JSON/JSONB,toValue/toSql 做序列化。内置提供 scalars.jsonProvider(valueType) / scalars.jsonbProvider(valueType) 可直接用:

// ① 模型(完整可运行版见工作区)
import { model, prop, dto, scalars } from '@ts-grm/core'
import { z } from 'zod'
import { sqlClient } from './infra/sql-client'

const Book = model("Book", "id", class {
    id = prop.i64()
    name = prop.str(50)
    edition = prop.i32()
    price = prop.num(10, 2)
    // 自定义数据类型:JSONB 存结构化内容(zod 描述形状)
    meta = prop.json(scalars.jsonProvider(z.object({
        isbn: z.string(),
        rating: z.number().min(1).max(5),
    })))
})

// ② 查询普通列(meta 列在沙盒种子中不存在,不放进视图即可)
const rows = await sqlClient.createQuery(Book, (q, b) => {
    return q.select(b.fetch(dto.view(Book, c => [c.id, c.name])))
}).fetchList()

console.log(rows)

ts-grm 自带的 StandardSchemaV1

prop.enum / prop.enumSet 内部会构造 vendor: 'ts-grm' 的 StandardSchemaV1 实现,把"值必须 ∈ 集合"表达成 schema 校验——框架的 Nullity 判断等逻辑也会消费它。含义:

  • 值类型体系与生态互通(zod、valibot 等 StandardSchema 兼容库都能作 valueType);
  • 自定义 provider 不必自己实现校验,用现成 zod 即可。

应用场景示例

  • 数据库 BINARY → 应用端 Uint8Array / base64 字符串:转换集中在 provider,业务层拿到的就是理想类型;
  • 位掩码/枚举编码列number 存、位运算后解成"特性集合";
  • JSONB 与嵌套结构:zod 定义结构,库侧 JSONB,读写自动转换。

边界与提醒

  • provider 参与 $allScalars、排序与取形——形状转换以 toValue 为准;
  • 列宽/类型必须与 sqlType 匹配(createSchema 的 DDL 也按它生成);
  • 性能敏感列(大字段)避免过重转换逻辑。