mcpField
T
type-definition-creator

type-definition-creator

github.com/datex开发92 次安装
代码仓库

关于 type-definition-creator

type-definition-creator 用于编写 Datex Studio 自定义接口和枚举,帮助开发者选择可复用或内联结构、定义字段并验证平台配置变更。

主要功能

  1. 01创建接口和枚举定义
  2. 02建模内联嵌套对象
  3. 03引用其他自定义类型
  4. 04验证并更新类型配置

适用场景

  1. 01为组件参数定义共享结构
  2. 02创建固定的命名值集合
  3. 03表示单个父类型使用的嵌套对象

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/datex/skills --skill type-definition-creator

安装后在 Claude Code 中输入/type-definition-creator确认已加载。

附带文件evals/evals.jsonreferences/type-definitions.md

详细介绍

类型定义创建器

在分支上编写或修改 Datex Studio 类型定义(configurationTypeId=22)——即声明接口(i_<name>)或枚举(e_<name>)的 -customType.json 文件。两种结构属于同一种组件类型,且使用相同后缀,但内部结构差异很大。类型定义会在整个平台中使用:包括 flow inParams / outParams、数据源 objectTypeDef、其他类型定义,以及(有一项重要限制的)UI 组件参数。

参考资料

依赖项

  • requirements-gathering 技能 — 如果当前对话上下文中尚无需求概要,则调用此技能生成概要
  • impact-analysis 技能 — 修改现有且已被使用的类型时,任何收紧变更之前都要调用此技能:添加必填字段、移除可选字段、将属性从通用 object 收窄为特定结构、将 objectTypeDef 从 null 改写为严格定义、重命名属性,或完全移除该类型。该类型的 FQN(<Package>.<referenceName>)是追踪目标;所有引用了宽松结构、并访问新结构未声明属性的消费者,都会在平台的严格检查中出错。全新类型无需执行此步骤

CLI 生命周期

类型定义编写通过 dxs configuration 完成——这是适用于平台所有配置类型的通用 CRUD 基元。没有 dxs customtype 子命令,也不支持字段级修补;需要构建(或获取并提取)整个 JSON 正文,编辑后再整体推送回去。CLI 中的类型标识符是 customtype(小写,与 ConfigurationEndpoints.normalize_type 的输出一致),对应 configurationTypeId: 22。接口(i_<name>)和枚举(e_<name>)共用此组件类型——由内部的 type 字段("interface" 与 "enum")加以区分。

创建新的类型定义:

# 1. Build body.json from scratch (see references/type-definitions.md → Interfaces / Enums)
# 2. Validate — gates the push. Exit 1 = errors found (read validation_errors, fix, re-run), not a broken CLI
dxs configuration validate customtype -b <branchId> -D body.json
# 3. Create
dxs configuration upsert customtype -b <branchId> -D body.json

编辑现有类型定义:

# 1. Fetch — note the envelope wrapper
dxs configuration get customtype <configId> -b <branchId> -O envelope.json
# 2. EXTRACT THE INNER BODY (round-trip footgun guard — see "Round-trip rule" below)
jq .json envelope.json > body.json
# 3. Edit body.json
# 4. Validate — gates the push. Exit 1 = errors found (read validation_errors, fix, re-run), not a broken CLI
dxs configuration validate customtype -b <branchId> -D body.json
# 5. Push
dxs configuration upsert customtype -b <branchId> -D body.json
往返规则(关键)

编辑现有配置时,绝不能将 envelope.json 直接传入 dxs configuration upsert——这会悄无声息地破坏配置内容。上述修正后的流程(先用 jq 提取内部的 .json,再进行编辑)是所有往返操作的必要步骤。有关标准往返流程和底层错误,请参阅 ../datex-studio-shared/configuration-roundtrip.md。

与其他配置类型相比,类型定义的主体异常精简——没有 inParams / outParams / vars / events / flows 内容槽位(这些都保持为 null)。主体本质上是组件身份信封,加上 objectTypeDef[](接口)或 enumTypeDef[](枚举)之一。往返规范(获取 → 用 jq 提取 → 编辑 → 验证 → 推送)仍然适用——无论主体大小如何,平台的导入路径都会执行完整的信封感知更新。类型定义文件在磁盘上也采用单行压缩 JSON 格式(与其他组件文件不同,请勿美化格式)。

工作流

[Phase 1: Setup + Requirements]
Follow branch-setup.md for branch/connection selection
        |
[requirements brief in context?]
  +-----+-----+
  |            |
 YES          NO -> invoke `requirements-gathering`
  |            |
  +-----+------+
        |
[Phase 2: Decide interface vs enum vs nested]
Consult references/type-definitions.md:
  - shared shape that multiple components reference
    -> interface (i_<name>) — objectTypeDef[] with property
       descriptors; type:"interface"; enumTypeDef:null;
       isStringValue:null
  - fixed set of named values (string-valued kebab-case or
    number-valued stringified integer)
    -> enum (e_<name>) — enumTypeDef[] with value descriptors;
       type:"enum"; objectTypeDef:[] (empty array, NOT null);
       isStringValue:true (string) OR null (number)
  - anonymous nested structure used only inside one parent
    type, no separate FQN
    -> nested inline object on the parent's objectTypeDef[]
       (no separate -customType.json file)
        |
[Phase 3: Author type body]
Build body.json (single-line minified):
  - File basics: suffix -customType.json, configurationTypeId 22,
    referenceName and title both equal filename stem, description
    <= 100 chars, accessModifier set (confirmed with user)
  - Interface body: objectTypeDef[] array of property descriptors,
    each carrying id / type / isCollection / required / objectType /
    isSecured; the six property shapes (scalar, array of primitives,
    inline object, FQN reference, union, object collection)
  - Enum body: enumTypeDef[] array of value descriptors; ProperCase
    ids, kebab-case values by default for string-valued; number-valued
    entries carry description:null
  - References use FQN ("<Package>.<referenceName>") — never the
    referenceName alone
  - Self-reference prohibition: custom types cannot reference
    themselves by FQN — inline to a fixed maximum depth matching
    the producing engine's recursion cap; maintain via a generator
    script alongside the file
  - UI-component enum FQN constraint: if this type (or an enum from
    this package) will be used inside vars/inParams/outParams of an
    editor/form/selector/hub/grid, do NOT declare it as
    objectType:"<Package>.e_<enum>" in those param descriptors —
    declare as the underlying primitive and cast at use time;
    flow-tier components and other custom-type files can reference
    enums via FQN freely
  - Sibling slots stay null: inParams, outParams, vars, events all
    null — type definitions have no code strings of their own
        |
[Phase 4: Validate + push]
dxs configuration validate customtype -b <branchId> -D body.json
        |
   +----+----+
   |         |
  CREATE   MODIFY-EXISTING
   |         |
   |         use the corrected round-trip
   |         (get -O envelope -> jq .json -> body)
   |         |
   +----+----+
        |
        v
dxs configuration upsert customtype -b <branchId> -D body.json
   (upsert creates or updates by referenceName — one command for both)
        |
[Phase 5: (Optional) Impact analysis if tightening or removing]
For tightening edits on an existing type (adding required fields,
removing optionals, narrowing object -> specific shape, rewriting
objectTypeDef null -> strict, renames, removal), invoke the
`impact-analysis` skill with target <Package>.<referenceName>
to enumerate every reference site and audit each one against the
new shape. Net-new types skip this step.
        |
[invoke `post-edit-verification`; then `component-validator`]

阶段详情

阶段 1:设置 + 需求
  1. 按照 ../datex-studio-shared/branch-setup.md 选择分支和连接。切勿假设分支 ID——请向用户确认。
  2. 检查对话上下文中是否已有需求简述(由 requirements-gathering 或其他调用技能生成)。
    • 已有简述——使用它。简述应明确该类型的用途(多个组件间共享的数据结构、固定值集合,或某个父类型中的匿名嵌套结构)、会引用它的使用方(流程参数、数据源结构、UI 组件),以及 accessModifier 应为 public 还是 private。
    • 没有简述——先调用 requirements-gathering 技能。事先正确决定使用接口、枚举还是嵌套结构,可避免使用方接入后再重构类型。
阶段 2:决定使用接口、枚举还是嵌套结构

编写前请参阅 references/type-definitions.md。此决定会影响主体结构:

接口(i_<name>)——供多个组件引用的共享结构。type: "interface",主体为包含属性描述符的 objectTypeDef[]。当相同结构出现在两个或更多位置(某个流程的 inParams、某个数据源的 outParams[].objectTypeDef、另一个接口的嵌套引用)时,集中定义可避免结构不一致。

枚举(e_<name>)——一组固定的命名值。type: "enum",主体为包含值描述符的 enumTypeDef[]。字符串枚举使用 isStringValue: true(默认采用 kebab-case 格式的 value);数字枚举使用 isStringValue: null(不能是 false),每个条目的 value 为字符串形式的整数,且 description: null。当调用方需要一组可通过引用常量识别的固定值时使用。

匿名嵌套内联对象——当结构只存在于某个父类型内部且没有独立身份时,将其内联为父类型 objectTypeDef[] 中 type: "object" 的属性描述符,并包含由子描述符构成的嵌套 objectTypeDef[]。无需单独的 -customType.json 文件。当结构不共享,且为其命名并无实际收益时使用。

如有疑问,请问:“是否会有多个组件按名称引用这个完全相同的结构?”如果是 → 接口。“这个结构是否只是一组固定选项?”如果是 → 枚举。否则 → 内联嵌套结构。请参阅 references/type-definitions.md → 接口、references/type-definitions.md → 枚举。

阶段 3:编写类型主体

根据 references/type-definitions.md → Interfaces 和 → Enums 中的骨架构建 body.json(单行压缩 JSON——不要美化输出)。要点:

  1. 文件基础信息。 关于 -customType.json 文件的格式,请遵循下方的 预检清单以及 ../datex-studio-conventions/universal-checklist.md。构建时的类型特定要求:accessModifier 为 "public" 或 "private"——从零开始创建时,请向用户确认选择(通用清单默认使用 public;自定义类型通常需要 private)。

  2. 接口主体。 顶层常量:type: "interface"、baseTypes: null(暂不支持继承)、enumTypeDef: null、isStringValue: null、inParams: null、outParams: null、vars: null、events: null。主体为 objectTypeDef[]——一个属性描述符数组。每个属性(包括顶层属性和内联对象中的嵌套属性)都包含 id / type / isCollection / required / objectType / isSecured: false。六种属性形状(标量基本类型、基本类型数组、内联对象、对另一个接口或枚举的 FQN 引用、带有 oneOf[] 的联合类型、对象集合)详见 references/type-definitions.md → Interfaces。

  3. 枚举主体。 顶层常量:type: "enum"、objectTypeDef: [](空数组,不是 null)、baseTypes: null、inParams: null、outParams: null、vars: null、events: null。每个文件的设置:字符串值枚举使用 isStringValue: true;数字值枚举使用 isStringValue: null(不是 false)。enumTypeDef[]——一个值描述符数组。值描述符命名规则:id(引用键)使用 PascalCase,不带空格(例如 RoyalBlue、ForestGreen);字符串值枚举的 value 默认使用 kebab-case(例如 royal-blue、forest-green),除非用户另有指定。数字值条目的整数以字符串形式存储(例如 "value":"0"),且 description: null。

  4. 引用使用 FQN。 objectType 的格式为 "<Package>.<referenceName>"——不能只有 referenceName。接口引用("Allocations.i_preallocation_action")和枚举引用("Allocations.e_allocation_replenishment_context")都遵循此格式。在接口中,枚举引用采用与接口引用相同的 {type:"object", objectType:"<Package>.<enum_referenceName>", ...} 形状(枚举的运行时值为字符串或数字类型,但架构层面的引用通过 type:"object" 实现)。

  5. 不允许自引用。 自定义类型不能递归引用自身——不存在 objectType: "<Package>.<this_type>" 这样的递归路径。如果类型需要包含自身的嵌套子项(例如具有任意深度 children 的树),请将结构内联到固定的最大深度——在每个层级重复完整的属性描述符集。如果生成树的引擎具有硬性递归上限,请让类型的内联深度与该上限一致,以确保类型能容纳引擎可生成的所有值。请使用与文件一同维护的生成器脚本来维护内联副本;只手动编辑某一层而不更新其他层属于缺陷。请参阅 references/type-definitions.md → Custom Types Cannot Self-Reference。

  6. UI 组件的枚举 FQN 限制。 在 UI 组件(编辑器、表单、选择器、Hub、网格)的 vars、inParams 和 outParams 中,属性描述符不能使用 objectType: "<Package>.e_<enum>" 引用。平台对 UI 组件参数声明进行 TS 验证时,不会解析自定义 $types.* 命名空间,并会产生 Cannot find namespace '_types'. Did you mean 'Type'?(_types 是平台将 $types 重写为 _types 后留下的产物)。解决方法:将字段声明为底层原始类型(字符串值枚举使用 string,数值枚举使用 number),然后在流程代码的使用处进行类型转换(const v = $form.fields.x.control.value as $types.<Package>.e_<enum>;)。此限制仅适用于 UI 组件——流程层组件(操作、函数、流程数据源)和自定义类型文件均可自由声明 objectType: "<Package>.e_<enum>" 引用。请参阅 references/type-definitions.md → UI Components Cannot Reference Custom Enums in vars / inParams / outParams。

  7. 同级槽位保持为 null。 类型定义主体中的 inParams、outParams、vars、events 始终为 null——类型定义自身没有代码字符串。不要臆造代码槽位;请遵循惯例。

第 4 阶段:验证并推送
# Validate the body locally against the branch. Exit 1 = validation found errors
# (read validation_errors, fix body.json, re-run) — not a broken CLI. Do not push on exit 1.
dxs configuration validate customtype -b <branchId> -D body.json

# For a new type definition
dxs configuration upsert customtype -b <branchId> -D body.json

# For modify-existing (round-trip — never skip the jq extract)
dxs configuration get customtype <configId> -b <branchId> -O envelope.json
jq .json envelope.json > body.json
# ... edit body.json ...
dxs configuration upsert customtype -b <branchId> -D body.json

验证会在推送前发现缺少必填字段、属性描述符或值描述符结构不正确,以及结构错误。它不会捕获自引用限制(该问题会在使用方编译时表现为类型加载器失败)、UI 组件的枚举 FQN 限制(该问题会在使用方 UI 组件上表现为 Cannot find namespace '_types'),或收紧类型导致影响使用方的问题(该问题会在每个此前隐式获得 any 的引用位置表现为严格检查类型错误)。推送前,请阅读 references/type-definitions.md 中介绍这些问题的各个部分。

第 5 阶段:(可选)收紧或移除时进行影响分析

对于全新类型,跳过此阶段——目前还没有任何内容引用该类型。

对于已在使用中的现有类型,以下任一项都属于会影响使用方的收紧编辑:

  • 添加之前的补丁中未包含的必填字段。
  • 移除使用方可能仍在读取的可选字段。
  • 将属性从通用的 type: "object" 收窄为特定的 FQN 引用或严格的内联结构。
  • 将 objectTypeDef 从 null(开放结构)改写为严格的描述符数组。
  • 重命名属性——所有访问旧名称的使用方都会出错。
  • 完全移除该类型——所有 FQN 引用位置都会出错。

对于以上任一情况,请在推送前调用 impact-analysis 技能,目标设为 <Package>.<referenceName>(该类型的 FQN)。该技能会枚举整个代码库中的所有引用位置——流程 inParams / outParams、数据源 objectTypeDef、其他类型定义,以及使用 objectType 引用的 UI 组件参数——以便在同一次编辑中根据新结构审查每个位置。此前隐式获得 any 并读取新类型未声明字段的代码,会在平台的严格检查阶段出错。不要在父 Agent 中内联 grep 调用方——多文件扫描是专用技能的工作。请参阅 references/type-definitions.md → Tightening a Previously-Loose Type Ripples to Consumers。

推送前检查清单

推送前,请完整阅读 references/type-definitions.md 中的内容。快速版:

  1. 文件基础信息。 后缀为 -customType.json,configurationTypeId: 22;新文件的 accessModifier 已与用户确认——另请完成通用检查(../datex-studio-conventions/universal-checklist.md)。
  2. 类型区分正确。 接口使用 type: "interface"、enumTypeDef: null、isStringValue: null、objectTypeDef: [...]。枚举使用 type: "enum"、objectTypeDef: [](空数组,不是 null)、enumTypeDef: [...]、isStringValue: true 或 null(绝不能是 false)。
  3. 属性描述符完整。 objectTypeDef 中的每个条目(顶层和嵌套)都有 id、type、isCollection、required、objectType、isSecured。内联对象包含 objectTypeDef;FQN 引用包含 objectType;联合类型包含 oneOf[]。
  4. 枚举的 id 使用 ProperCase,且不含空格。 value 遵循指定的大小写格式(字符串值默认使用 kebab-case)。数值条目使用字符串形式的整数,并设置 description: null。
  5. 引用使用 FQN。 objectType 格式为 "<Package>.<referenceName>",而不只是 referenceName。
  6. id 占位值。 编写时使用 id: 0;实际值由用户或导入过程分配。
  7. 不得自引用。 如果类型需要嵌套自身的子项,则将其内联到与生成引擎递归上限相符的固定最大深度;通过生成器脚本维护。
  8. 遵循 UI 组件枚举 FQN 限制。 如果此类型(或此软件包中的枚举)将用于编辑器、表单、选择器、hub 或网格的 vars、inParams 或 outParams 中,请勿在这些声明中写入 objectType: "<Package>.e_<enum>"——应声明为底层基元类型,并在使用时转换。
  9. 同级字段设为 null。 inParams、outParams、vars、events 均保持为 null——类型定义本身没有代码字符串。
  10. 收紧类型的修改须先进行影响分析。 对正在使用的类型进行任何会添加必填字段、移除可选字段、缩窄属性范围、将 objectTypeDef 从 null 改为严格定义、重命名属性或移除类型的修改,都必须在推送前针对该类型的 FQN 使用 impact-analysis 技能。新增类型无需执行此步骤。

常见错误

错误修正
数值枚举的 isStringValue 被设为 false 而不是 null平台对 false 和 null 的处理不同——数值枚举必须使用 null(且条目带有 description: null 和字符串化整数 value)。请准确设置为 isStringValue: null。
枚举的 objectTypeDef 被设为 null 而不是 []枚举使用 objectTypeDef: [](空数组)——null 是接口的约定。平台的加载器通过此字段区分这两种结构;设为 null 会导致枚举结构错误。
枚举的 id 含有空格或不符合 ProperCase 的字符id 中不允许有空格。请使用 ProperCase(例如 RoyalBlue、ForestGreen)。
属性描述符缺少 isSecured: false每个属性(顶层和嵌套属性)都必须带有 isSecured。请在每个描述符中包含该字段;若不需要受保护属性变体,默认设为 false。
objectType 被设为裸 referenceName 而非 FQN引用应使用 "<Package>.<referenceName>",不能只写 i_thing 或 e_thing。平台通过 FQN 解析;裸名称无法解析。
尝试自引用(objectType: "<Package>.<this_type>" 递归)自定义类型不能引用自身。请内联嵌套结构,并将深度限制为与生成引擎的递归上限一致的固定最大深度。使用生成器脚本维护内联副本。参见 references/type-definitions.md → 自定义类型不能自引用。
UI 组件通过 vars / inParams / outParams 中的 objectType: "<Package>.e_<enum>" 引用枚举时出现 Cannot find namespace '_types' 错误UI 组件的参数声明不能使用枚举 FQN 引用。请声明为底层基元类型(字符串值枚举使用 string,数值枚举使用 number),并在流程代码的使用位置进行类型转换(as $types.<Package>.e_<enum>)。流程层组件和其他自定义类型文件可以自由引用枚举。
未运行影响分析就收紧正在使用的类型;现在使用方在严格检查阶段失败之前隐式获得 any 并读取新类型未声明字段的代码,会在平台的严格检查阶段出错。请撤销收紧操作,针对该类型的 FQN 调用 impact-analysis 技能,审查每个引用位置,并在收紧类型的同一次编辑中更新这些位置。
重命名正在使用的类型的属性,却未更新使用方每个引用旧名称的位置都会失败。请先针对 <Package>.<referenceName> 调用 impact-analysis 技能,然后在同一次编辑中更新所有命中位置。
对 JSON 文件进行了美化格式化磁盘上的类型定义文件是单行压缩 JSON,这与其他组件文件不同。不要美化格式;导入路径需要压缩格式。
根据其他类似 JSON 推断数值枚举的 isStringValue 应显式设为 false约定是字符串值枚举使用 true,数值枚举使用 null。false 是错误的。
误以为接口是开放结构,将其顶层 objectTypeDef 声明为 null接口使用 objectTypeDef: [...](描述符数组)。null 形式是接口的 enumTypeDef 槽位,不是其主体。
description 超过 100 个字符SQL 列有长度限制——推送将无法通过验证。请精简。
将 dxs configuration get -O envelope.json 的输出直接通过管道传给 dxs configuration upsert -D envelope.json这会静默破坏配置内容。编辑前务必先运行 jq .json envelope.json > body.json。参见上文“往返规则”。

编辑后,请调用 post-edit-verification,以发现描述、JSON 和架构违规。最终审查时,请调用 component-validator。

评论

支持 Markdown