/** * schema-adapter.ts — schema-dsl 防腐层(Anti-Corruption Layer) * * 所有 vext 内部模块(validate 中间件、OpenAPI SchemaConverter、i18n-loader、 * default-throw 等)统一通过此模块访问 schema-dsl,禁止直接 import schema-dsl。 * * 设计目的: * 1. 隔离 schema-dsl 的 breaking change 风险 — 签名变更只需修改此文件 * 2. 统一版本锁定 — package.json 锁定 schema-dsl 版本,此处封装 API 调用 * 3. 集中类型适配 — schema-dsl 的类型在此处映射为 vext 内部类型 * 4. 可测试性 — 测试时可 mock 此模块替换 schema-dsl 实现 * * 使用规则: * ✅ import { schemaAdapter } from './schema-adapter.js' * ❌ import { dsl, validate, I18nError } from 'schema-dsl' // 禁止直接引用 * * @module lib/schema-adapter * @see IMPLEMENTATION-PLAN.md 任务 1.0 * @see 06b-error.md §1.1.1(schema-dsl 与 vext 的依赖方向) */ import { dsl, validate as schemaDslValidate, I18nError } from "schema-dsl"; import type { JSONSchema, ValidationResult, ValidateOptions, DslDefinition, DslBuilder, SchemaIOOptions, DslConfigOptions, ErrorMessages } from "schema-dsl"; export type { JSONSchema, ValidationResult, ValidateOptions, DslDefinition, DslBuilder, SchemaIOOptions, DslConfigOptions, ErrorMessages, }; export { I18nError }; /** * 编译 DSL 定义为 JSON Schema * * 封装 `dsl()` 主入口函数。 * * @param definition DSL 定义(字符串或对象) * @param options 编译选项(可选) * @returns JSON Schema 对象(对象定义)或 DslBuilder(字符串定义) * * @example * ```typescript * import { schemaAdapter } from './schema-adapter.js' * * // 对象定义 → JSON Schema * const schema = schemaAdapter.compile({ * username: 'string:3-32!', * email: 'email!', * }) * * // 字符串定义 → DslBuilder * const builder = schemaAdapter.compileField('email!') * ``` */ declare function compile(definition: Record, options?: SchemaIOOptions): JSONSchema; /** * 编译单个字段定义为 DslBuilder * * @param definition 字段 DSL 字符串(如 'string:3-32!'、'email!') * @returns DslBuilder 实例 */ declare function compileField(definition: string): DslBuilder; /** * 判断值是否为 schema-dsl DslBuilder。 * * OpenAPI 生成器需要识别 `"string!".description("...")` 这类字段级 builder, * 但不应直接依赖 schema-dsl 的私有字段结构。 */ declare function isDslBuilder(value: unknown): value is DslBuilder; /** * 将 DslBuilder 转为纯净 JSON Schema。 */ declare function toJsonSchema(builder: DslBuilder): JSONSchema; /** * 判断字段是否必填。 */ declare function isFieldRequired(builder: DslBuilder): boolean; /** * 判断字段是否显式使用 `?` 标记为 nullable。 */ declare function isFieldOptional(builder: DslBuilder): boolean; /** * 同步校验数据 * * 封装 `validate()` 顶层函数。 * * @param schema JSON Schema 或 DslBuilder * @param data 待校验数据 * @param options 校验选项(locale 等) * @returns 校验结果 { valid, data?, errors? } * * @example * ```typescript * const schema = schemaAdapter.compile({ email: 'email!' }) * const result = schemaAdapter.validate(schema, { email: 'test@example.com' }) * * if (!result.valid) { * console.log(result.errors) * } * ``` */ declare function validate(schema: JSONSchema | DslBuilder, data: unknown, options?: ValidateOptions): ValidationResult; /** * 创建 I18nError 实例(不抛出) * * 封装 `I18nError.create()` / `dsl.error.create()`。 * vext 的 defaultThrow 通过此方法获取翻译后的错误信息, * 然后自行构造 HttpError 并抛出。 * * @param code 错误代码(i18n key) * @param paramsOrLocale 插值参数对象 或 语言代码(智能识别) * @param statusCode HTTP 状态码(默认 400) * @param locale 语言环境(当第二参数为对象时有效) * @returns I18nError 实例 * * @example * ```typescript * // 简单用法 * const err = schemaAdapter.createI18nError('user.not_found', 'zh-CN', 404) * * // 带参数插值 * const err = schemaAdapter.createI18nError( * 'balance.insufficient', * { balance: 50, required: 100 }, * 400, * 'zh-CN', * ) * * // 提取翻译结果 * console.log(err.message) // 已翻译的消息 * console.log(err.code) // 业务错误码 * console.log(err.originalKey) // 原始 key * ``` */ declare function createI18nError(code: string, paramsOrLocale?: Record | string, statusCode?: number, locale?: string): I18nError; /** * 配置 schema-dsl 全局设置 * * 封装 `dsl.config()`。 * i18n-loader 通过此方法注册语言包到 schema-dsl。 * * @param options 配置选项(i18n / cache / patterns 等) * * @example * ```typescript * // 注册语言包 * schemaAdapter.configure({ * i18n: { * locales: { * 'zh-CN': { 'user.not_found': '用户不存在' }, * 'en-US': { 'user.not_found': 'User not found' }, * }, * }, * }) * ``` */ declare function configure(options: Parameters[0]): void; /** * schema-dsl 防腐层 * * vext 内部所有模块通过此对象访问 schema-dsl 功能。 * 集中管理 API 调用,隔离上游 breaking change。 * * @example * ```typescript * import { schemaAdapter } from './schema-adapter.js' * * // 编译 schema * const schema = schemaAdapter.compile({ name: 'string:1-50!' }) * * // 校验数据 * const result = schemaAdapter.validate(schema, { name: 'test' }) * * // 创建 i18n 错误 * const err = schemaAdapter.createI18nError('user.not_found', 'zh-CN', 404) * * // 配置语言包 * schemaAdapter.configure({ i18n: { locales: { 'zh-CN': {...} } } }) * ``` */ export declare const schemaAdapter: { /** 编译 DSL 对象定义为 JSON Schema */ readonly compile: typeof compile; /** 编译单个字段 DSL 字符串为 DslBuilder */ readonly compileField: typeof compileField; /** 判断值是否为 schema-dsl DslBuilder */ readonly isDslBuilder: typeof isDslBuilder; /** 将 DslBuilder 转为纯净 JSON Schema */ readonly toJsonSchema: typeof toJsonSchema; /** 判断 DslBuilder 字段是否必填 */ readonly isFieldRequired: typeof isFieldRequired; /** 判断 DslBuilder 字段是否显式使用 `?` 标记 */ readonly isFieldOptional: typeof isFieldOptional; /** 同步校验数据 */ readonly validate: typeof validate; /** 创建 I18nError 实例(不抛出,由调用方决定抛出时机) */ readonly createI18nError: typeof createI18nError; /** 配置 schema-dsl 全局设置(i18n 语言包 / 缓存 / 自定义规则) */ readonly configure: typeof configure; /** * 原始 dsl 函数引用(escape hatch) * * 仅在 schemaAdapter 封装不满足需求时使用。 * 使用前请先考虑是否应该在防腐层增加新的封装方法。 * * @internal */ readonly raw: { readonly dsl: { (def: string, options?: SchemaIOOptions): DslBuilder; (def: DslDefinition, options?: SchemaIOOptions): JSONSchema; config: (options?: Partial) => void; if: { (condition: string, thenSchema: unknown, elseSchema?: unknown): import("schema-dsl").DslConditionMarker; (condition: (data: unknown) => boolean): ReturnType; }; _if: { (condition: string, thenSchema: unknown, elseSchema?: unknown): import("schema-dsl").DslConditionMarker; (condition: (data: unknown) => boolean): ReturnType; }; match: (value: unknown, cases: Record) => import("schema-dsl").DslConditionMarker; error: { create: typeof I18nError.create; throw: typeof I18nError.throw; assert: typeof I18nError.assert; [key: string]: unknown; }; }; readonly validate: typeof schemaDslValidate; readonly I18nError: typeof I18nError; }; };