Skip to content

spec: 为剩余 16 个可编写域补全 defineX 工厂 / XInput,统一编写入口 #2035

Description

@os-zhuang

背景

源自 #2023 的排查:示例应用从根 @objectstack/spec 导入类型 → 解析成 any → 静默吞掉所有对象字面量的类型检查,掩盖了约 30 个真实类型错误。根因之一是这些域没有一个统一、类型安全的编写入口,作者(尤其是 AI)只能写裸 : X 字面量,而输出态(z.infer)会把 .default() 字段变必填、拒绝 CEL 字符串简写。

后续的 #2026 / #2029 已经堵上了 CI 闸门(示例 typecheck + ESLint 导入守卫)。本 issue 处理更上游的一致性问题。

问题:三种并存的编写惯用法

写法适用域输入态人体工学编写处类型安全运行期校验
defineX() 工厂view/flow/job/agent/app/portal/dataset/book… (19 个)✅ (.parse())
ObjectSchema.create() / Field.x() 构建器object / field
裸类型字面量 : X下列 16 个域⚠️

用哪种纯粹看历史,无规律。第三类正是 #2023 翻车的地方。

缺口清单(当前 main 实测)

16 个可编写域没有 defineX 工厂:
DatasourceConnectorPolicySharingRuleRolePermissionSetEmailTemplateDefinitionReportWebhookObjectExtensionCubeMappingThemeTranslationBundlePageAction

其中 6 个连 XInput 别名也没有(需一并补):PolicyCubeMappingThemeTranslationBundlePage

(已有 defineX 的 19 个域作为模板:defineView/defineForm/defineApp/defineFlow/defineJob/defineBook/defineAgent/defineTool/defineSkill/definePortal/defineDataset/defineStack/defineSeed/defineSolutionBlueprint/defineViewItem/defineActionDescriptor/defineFlowBuilderConfig/defineObjectDesignerConfig/defineStudioPlugin)

长期价值

  1. fix(examples): typecheck example apps clean + gate in CI #2023 那一类 bug 在结构上不可能再发生:defineX导入,坏掉会立刻硬报错,没有 any 可退化躲藏。
  2. AI 只需学一种写法(对齐"模板都是 AI 写的、避免 AI 犯错"的北极星):消灭"看着对其实错"的输出态字面量选项。
  3. 编写期错误信息好得多:.parse() 接已导出的错误映射(objectStackErrorMap / safeParsePretty),给出 webhook.timeoutMs 必须 ≥ 1000 这类就地、字段级提示,而非 TS 结构不匹配的墙。
  4. 隔离 schema 变动:给某 schema 加 .default() 不再静默打破生态里所有裸输出态字面量。

defineX(config: z.input<typeof XSchema>): X { return XSchema.parse(config); } 是唯一同时满足"输入态人体工学 + 编写处类型安全 + 运行期校验"三项的写法;裸 : XInput 只满足前两项。

建议落地方式(两个 PR)

  • PR 1 — spec:为上述 16 个域新增 defineX 工厂(每个约 3 行,与现有 19 个机械同构),并补齐 6 个缺失的 XInput 别名。根 index.ts 按现有约定 re-export。带 minor changeset(@objectstack/spec)。
  • PR 2 — 示例迁移:把 example apps(crm/showcase/todo)里相关域改用新工厂,作为参考示范。fix(examples): typecheck example apps clean + gate in CI #2023 的 typecheck + ESLint 闸门兜底。

成本 / 取舍

  • 公共 API 面增长(纯增量、零设计风险,照搬现有写法)。
  • 流入 defineStack 的域会双重 parse —— 开销可忽略,换来更早/就地校验。
  • 不动 object/field 的构建器路径(它们已有良好入口)。
  • TranslationBundlez.record,defineTranslationBundle 形态略特殊但仍成立。

验收标准

  • 16 个域均有 defineX 工厂并从根 re-export
  • 6 个缺失的 XInput 别名补齐
  • 示例应用相关域迁移到工厂写法
  • pnpm --filter './examples/*' typecheckpnpm lint 全绿
  • @objectstack/spec changeset 已添加

🤖 由本次 #2023/#2026/#2029 排查衍生,Claude Code 整理

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions