Skip to content

自定义 Schema

Schema 是 Velite 的核心。它定义了内容的结构和类型,并对其进行验证。

有关内置 schema 的更多信息,请参阅 Velite Schemas

Velite 支持自定义 schema。schema 是一个返回 Zod schema 对象的 JavaScript 函数。

通常,我将 schema 分为两类:一类用于数据验证,另一类用于数据转换。

定义验证 Schema

ts
import { defineSchema, s } from 'velite'

// `s` 是从 Zod 扩展而来,包含一些自定义 schema,
// `s` 也包含了 zod 的所有成员,因此你可以将 `s` 当作 `z` 来使用

// 用于验证标题
export const title = defineSchema(() => s.string().min(1).max(100))

// 用于验证邮箱
export const email = defineSchema(() => s.string().email({ message: '邮箱地址无效' }))

// 自定义验证逻辑
export const hello = defineSchema(() =>
  s.string().refine(value => {
    if (value !== 'hello') {
      return '值必须为 "hello"'
    }
    return true
  })
)

有关 Zod 的更多信息,请参阅 Zod 文档

定义转换 Schema

ts
import { defineSchema, s } from 'velite'

// 用于转换标题
export const title = defineSchema(() => s.string().transform(value => value.toUpperCase()))

// ...

示例

带有模糊数据 URL 的远程图片 Schema

ts
import { getImageMetadata, s } from 'velite'

import type { Image } from 'velite'

/**
 * 带有元数据的远程图片 schema
 */
export const remoteImage = () =>
  s.string().transform<Image>(async (value, { addIssue }) => {
    try {
      const response = await fetch(value)
      const blob = await response.blob()
      const buffer = await blob.arrayBuffer()
      const metadata = await getImageMetadata(Buffer.from(buffer))
      if (metadata == null) throw new Error(`获取图片元数据失败: ${value}`)
      return { src: value, ...metadata }
    } catch (err) {
      const message = err instanceof Error ? err.message : String(err)
      addIssue({ fatal: true, code: 'custom', message })
      return null as never
    }
  })

Schema 上下文

TIP

考虑到 Velite 的场景经常需要在 schema 中获取当前文件的元数据信息,Velite 没有使用原始的 Zod 包,而是使用了一个自定义的 Zod 包,它在 schema 上下文中提供了一个 meta 成员。

ts
import { defineSchema, s } from 'velite'

// 转换一个不存在的字段
export const path = defineSchema(() =>
  s.custom<string>().transform((value, ctx) => {
    if (ctx.meta.path) {
      return ctx.meta.path
    }
    return value
  })
)

参考

meta 的类型是 ZodMeta,它扩展了 VeliteFile

Distributed under the MIT License.