DSH 插件开发 · 第 5 章:配置与校验
/ 4 min read
本文对应官方教程第 5 章:配置,示例代码在其基础上改编。
学习目标:给插件加配置项,理解“校验失败即加载失败”的设计与 YAML 里的计算值。
配置从哪来
cordis.yml 里的每个插件条目都可以携带一个 config 块:
- ./greeter.ts: config: greeting: 你好 times: 3插件侧用对象形态,把 config 属性声明成 Schemastery schema,apply 的第二个参数就会拿到校验后的值:
import { Schema } from 'schemastery'
export default { name: 'greeter', config: Schema.object({ greeting: Schema.string().default('hello'), times: Schema.number().min(1).max(10).default(1), }), apply(ctx, config) { for (let i = 0; i < config.times; i++) ctx.log(config.greeting) },}Schemastery 的价值不止类型:每个字段都能带默认值、约束(min/max)、描述,同一个 schema 既能校验 YAML,也能在需要时生成配置界面——声明一次,处处可用。
校验失败 = 加载失败
这是本章最重要的设计决策:配置校验发生在 apply 之前,校验不过插件直接进入 FAILED 状态,抛出带精确位置信息的 ValidationError,根本不会执行你的逻辑。
对比一下另一种世界:配置错误悄悄溜进 apply,运行到一半用 undefined 去除——问题离病根十万八千里。“宁可加载失败”把配置错误拦截在最早的时刻,配合第 6 章的 PENDING 诊断,出错位置一目了然。
副作用是:改配置 = 重载插件。校验通过则插件带着新配置重载,失败则停在 FAILED,旧实例已卸载。所以别在配置里放“运行时可变”的状态,那是服务的职责。
!!js:YAML 里的计算值
cordis.yml 支持有限的 !!js 标签,让某些字段写表达式而不是字面量——只有 config 和 disabled 两个字段支持:
- ./listener.ts: disabled: !!js "process.env.CI === 'true'" config: endpoint: !!js "`http://localhost:${process.env.PORT ?? 3000}`"适用面刻意收得很窄:它只是免掉“为了一个环境变量写两个 yml”的胶水,不是让你在配置里写业务逻辑。滥用 !!js 会让组合文件变成第二份源码,排查配置问题时mental model 直接翻倍。
踩坑提示
config忘了声明 schema,YAML 里写的配置原样透传——看起来“能用”,实际上没有任何校验和默认值,字段名拼错了也不会有人提醒。Schema.number()对 YAML 里的"3"(字符串)不妥协:要么改 schema 用Schema.natural()系列做转换,要么把 YAML 写对。- 默认值写在 schema 里,别写在
apply里用config.x ?? default补——两处默认值迟早漂移。
练习
- 给第 1 章的 hello 插件加
name(要问候谁)和upper(是否转大写)两个配置项,含默认值。 - 故意把
times配成 0,观察 ValidationError 的输出格式与 FAILED 状态。 - 用
!!js让一个配置项读取环境变量,分别在有/无该变量时启动验证。