扩展概览

最后更新: 2026-06-18

当你想扩展 schema-dsl,但还不确定应该扩展自定义类型、s.xxx() 工厂、链式方法、校验关键字还是插件管理器时,先看本页。

扩展系统有多个层次。它们可以组合,但解决的问题不同。

我应该用哪种扩展?

目标推荐文档典型结果
复用 tenantId! 这样的 DSL 字面量自定义 DSL 类型s({ tenant: 'tenantId!' })
暴露可发现的 factory自定义 s.xxx() 工厂s.tenantId().require()
增加 builder 方法自定义链式方法s('string!').tenantId()
保留直接 String 链式源码自定义链式方法String 扩展transform 或显式 String 支持后的 'string!'.tenantId()
增加校验关键字自定义校验关键字{ type: 'number', isEven: true }
按 app、tenant、plugin 或 worker 隔离扩展框架集成与目录结构运行时隔离const runtime = createRuntime({ types })
协调插件安装、卸载与 hook插件管理器(高级)pluginManager.install(schemaDsl, 'plugin')
在一个扩展包里组合多种能力高级扩展组合指南type + factory + keyword + locale

三个 schema 编写层

自定义扩展最好按三个层次理解:

层次控制什么示例
DSL 类型被 DSL parser 解析的可复用字面量tenantId!
namespace factorys / dsl 上可点调用的方法s.tenantId()
链式方法已有 builder 上的新方法s('string!').tenantId()

registerExtension({ literal, factoryName, schema }) 可以用一份定义同时暴露前两个层次。自定义链式方法是另一件事,因为它还需要运行时 builder 方法和 TypeScript 接口增强。

全局扩展与 runtime 作用域扩展

如果应用启动期只加载一套扩展,使用 schema-dsl/pure 的全局入口:

import { s } from 'schema-dsl/pure';

s.registerExtension({
  literal: 'tenant-id',
  factoryName: 'tenantId',
  schema: { type: 'string', pattern: '^tenant_[a-z0-9]+$' }
});

如果框架、插件宿主、租户、测试套件或 worker 需要隔离扩展状态,使用 schema-dsl/runtime

import { createRuntime } from 'schema-dsl/runtime';

const runtime = createRuntime({
  types: {
    tenantId: { type: 'string', pattern: '^tenant_[a-z0-9]+$' }
  }
});

推荐阅读顺序

  1. 想复用字面量,先看 自定义 DSL 类型
  2. 想要编辑器可发现的 factory,看 自定义 s.xxx() 工厂
  3. 想增加 builder 方法,看 自定义链式方法
  4. 准备接入真实应用或框架前,看 框架集成与目录结构
  5. 只有需要插件生命周期和 hook 编排时,再看 插件管理器(高级)

对应示例文件

示例入口: extensions-overview.ts 说明: 并排展示自定义 DSL 类型、namespace factory、runtime 作用域类型和自定义校验关键字四条路径。