@client-compose/codegen

中文文档
0.12.1发布于 2026/11/04MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 1787

从客户端编译岛列表中生成Go和TypeScript的岛道具类型.

中文使用文档
文档目录10 节
  1. 安装
  2. 配置
  3. 你得到的东西
  4. 实体
  5. 共享类型
  6. 字符串
  7. 支持的计划子集
  8. 清单的兼容性规则
  9. 在CI里检查
  10. 测试

@ lient- compose/ 编码源

产生岛的道具类型 从岛的每个堆 清单,所以作曲家和 每个应用程序都通过建筑而不是手来商定每个岛屿的道具.

npx @client-compose/codegen client-compose.codegen.json            # write
npx @client-compose/codegen client-compose.codegen.json --check    # CI: exit 1 if out of date
npx @client-compose/codegen compat client-compose.codegen.json --base origin/main
                                                                   # CI: exit 1 on breaking changes
npx @client-compose/codegen strings client-compose.codegen.json    # CI: check the strings catalog

转到输出格式化 gofmt 如果你的路径。 (在此重播中, 运行 node codegen/cli.ts … 直接使用源。 )

安装

有节点20+: npx @client-compose/codegen …,或添加 @client-compose/codegen 是一个非常依赖.

没有节点 (去项目):单独下载 client-compose-codegen 用于您平台的可执行文件 代码释放数字 : linux-x64, (中文(简体) ), linux-arm64, (中文(简体) ), darwin-x64, (中文(简体) ), darwin-arm64 或者说 windows-x64,带有 SHA256SUMS 要校验的文件 这个 例如,通过GitHub CLI:

gh release download "@client-compose/[email protected]" -R client-compose/client-compose \
  -p "client-compose-codegen-darwin-arm64" -p SHA256SUMS
shasum -a 256 --check --ignore-missing SHA256SUMS
chmod +x client-compose-codegen-darwin-arm64 && mv client-compose-codegen-darwin-arm64 /usr/local/bin/client-compose-codegen

二进制与 npm 包的参数相同 。 他们没有公证,所以在macOS一个副本 通过浏览器需要下载 xattr -d com.apple.quarantine <file> 在它运行之前 (负载 gh 或者说 curl 别.

配置

client-compose.codegen.json (路径相对于此文件; 仅配置您使用的目标):

{
  "manifests": "islands",
  "actions": "actions",
  "targets": {
    "go": { "out": "composer-go/islands_gen.go", "package": "main" },
    "typescript": { "out": "web/islands.generated.ts", "protocolImport": "@client-compose/protocol" }
  }
}

actions 可选:为每个目标生成的行动清单(第5段)。 A 类 配置可能只包含 actions。 。 。 .

对于实体(第2.1项),添加 "entities": "entities",一个实体列表。 见 实体。 。 。 .

对于几种显示共享类型(第2.2段),添加 "types": "types",类型目录 名单 见 共享类型。 。 。 .

对于字符串(第4.7段),添加 "appStrings": "app-strings.json" (应用字符串显示), "screenStrings": "screen-strings.json" (每个屏幕自己的字符串,用于Go和TypeScript作曲), "catalog": "strings" (目录) <locale>.json 如果不是作曲家服务的文件) en, (中文(简体) ), "defaultLocale"。见 字符串。 。 。 .

在Go项目中,a //go:generate client-compose-codegen <config> (或 npx @client-compose/codegen <config>(行让) go generate 运行它 (见 examples/todo/composer-go/main.go) (中文(简体) ).

你得到的东西

对于 profile-header v2, 每个目标生成 a ProfileHeaderV2 了解自身类型 岛屿类型和版本,所以注册不能给岛屿取名错误:

堆栈已生成用作
走开struct + 键 IslandType() 编号 : IslandVersion() 方法cc.Define(func(ctx, r) (ProfileHeaderV2, error) { … })
类型脚本interface +描述符 const 名称相同registry.register(ProfileHeaderV2, (props) => …), (中文(简体) ), island(ProfileHeaderV2, resolve)

供采取行动 follow-user v1( 第5.1节) :

堆栈已生成用作
走开FollowUserV1Input (与其行动、版本、输入计划和结果类型挂钩), FollowUserV1Result,并且每个声明错误都有一个错误类型,例如:. FollowUserV1Blockedcc.DefineAction(func(ctx, call, in FollowUserV1Input) (FollowUserV1Result, cc.Effects, error) { … })返回时 FollowUserV1Blocked{} 作为错误
类型脚本FollowUserV1Input, (中文(简体) ), FollowUserV1Result,则 FollowUserV1Error 工会,以及 FollowUserV1 描述符action(FollowUserV1, perform) 在作曲家, callAction(…, FollowUserV1, input) 或者说 useAction(FollowUserV1) 在应用程序中

实体

一个实体命名一些岛屿, 所以一个动作可以说它有什么变化 (第2.1和5.3节)。 每一个都显示在 entities 目录和岛道具标记对象 显示一个与 entity数字 :

// entities/todo.json
{ "entity": "todo", "id": "id", "properties": { "id": { "type": "string" }, "title": { "type": "string" }, "done": { "type": "boolean" } } }

// in an island's props
"todos": { "type": "array", "items": { "type": "object", "entity": "todo", "required": ["id", "title"], "properties": { … } } }

代码源检查每个标记对象: 它有实体的ID, 需要, 以及每个实体的 它显示的属性有实体的设置。 它可能有自己的属性. compat 将标出或未标出对象视为断裂变化.

堆栈已生成用作
走开TodoEntity每一个财产,除了id,每一个可选的; IslandEntities() 在拥有实体的岛屿上cc.Set("3", TodoEntity{Done: &done}), (中文(简体) ), cc.Delete[TodoEntity]("3")
类型脚本TodoEntity 及其描述者; entities 岛上的描述changed(TodoEntity, "3", { done: true }), (中文(简体) ), deleted(TodoEntity, "3"); 客户端使用描述符应用更改' entities

共享类型

当若干岛屿、行动或实体拥有相同形状时(图像、个人徽章、a) ,定义一次并参考一次。 每一个都显示在 types 目录:对象,或 字符串语句,与其它语句相同。 类型可能指另一个类型,但不指 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}我们自己来.

// types/image.json
{ "type": "image", "description": "A picture.", "schema": { "type": "object", "required": ["url"], "properties": { "url": { "type": "string", "format": "uri" }, "width": { "type": "integer" } } } }

// anywhere a schema can be: an island's props, an action's input, result or error details, an
// entity's properties, or another shared type
"cover": { "$ref": "image", "description": "Shown at the top." }

仅说明( E)description, (中文(简体) ), title, (中文(简体) ), $comment, (中文(简体) ), examples可以坐在旁边 $ref类型 生成一次,以其自己的名字(Image,有巢类类似 ImageFocus和每个 引用使用它,所以一个帮助者或组件可以在它出现的地方带走它. 到处都有计划 嵌入或比较(作曲者用来验证的动作输入方案,实体检查), 参考书目被写出,所以参考书目完全指现存类型的写作会是什么. compat 判断每个岛屿改变为共同类型,并根据它们的规则采取行动: 给一个共享的enum添加一个值 是打破它使用的地方.

代码源生成 Go 和 TypeScript 。 斯威夫特和克特林的目标 与他们的客户 需要一个维护者回来.

字符串

每个应用节目的词出自作曲家(spec §4.7). 岛屿表宣布 由按键组成的字符串,每个参数都填入,以及 counted 对于一个言语依赖 count数字 :

"strings": {
  "heading": { "description": "Over the list." },
  "greeting": { "params": ["name"] },
  "articleCount": { "params": ["count"], "counted": true }
}

App string express 声明属于无岛的词(一个占地者"Loading","Loading"), a 验证信息),格式相同: { "strings": { … } }。每个目标生成一个类型 其成员是弦:为无正框者提供正文,为具有下列功能者提供功能:

堆栈已生成用作
类型脚本ArticleListV1Strings和描述器的 strings· ; AppStringsprops.t.articleCount({ count }) 在登记的组成部分中; useAppStrings(AppStrings).retry

单词是目录,每个语言一个文件,例如. strings/pl.json数字 :

{
  "app": { "retry": "Spróbuj ponownie" },
  "islands": {
    "article-list@1": {
      "heading": "Najnowsze",
      "greeting": "Cześć {name}",
      "articleCount": { "#0": "Brak artykułów", "#one": "{count} artykuł", "#few": "{count} artykuły", "#*": "{count} artykułów" }
    }
  }
}

屏幕的自有弦是其作曲家使用自己的词,例如其元标题. 屏幕 字符串显示通过屏幕标识来宣告, { "screens": { "author": { "title": { "params": ["author"] } } } },目录里有 screens开始 AuthorScreenStringsFor(r).Title(name); 类型脚本, lc.strings(AuthorScreenStrings).title({ author })。 。 。 .

已计数字符串的变体键入 #<number>, (中文(简体) ), #<category> (CLDR's zero, (中文(简体) ), one, (中文(简体) ), two, (中文(简体) ), few, (中文(简体) ), many, (中文(简体) ), other)或(或) #*,按此顺序选择. strings 检查目录与 显示:默认语言必须拥有每个字符串;缺少一个字符串的则得到警告 回到默认的。 未知的钥匙和岛屿,变体 #*,字符串上的变体 这不算,和 {slots} 而不是参数是错误.

支持的计划子集

化身使用JSON Schema的一个特意小分集. 外面的任何东西都会被拒绝 错误,所以一个表 永远不能指不同语言中不同的事物.

司马走开类型脚本
stringstringstring
string, (中文(简体) ), format: uristringstring
string, (中文(简体) ), enum: [...]名称 string 类型 + conss字符串结合
integerintnumber
integer, (中文(简体) ), format: int64int64number
numberfloat64number
booleanboolboolean
array 与 items[]TT[]
object 与 properties名称结构命名接口
object 与 additionalPropertiesmap[string]TRecord<string, T>
没有在 requireda. 指针,或为零; omitemptyprop?:

共享类型( E){ "$ref": "image" })成为它自己命名的类型:见 共享类型。 。 。 .

还允许: description (成为医生的评论), title (命名为巢型), $comment, (中文(简体) ), examples。不支持 : $ref 除了同一类人的名字之外, oneOf编号 :anyOf编号 :allOf类型工会, null, (中文(简体) ), pattern, (中文(简体) ), minimum 和其他校验关键词,格式 uri, (中文(简体) ), int32 财务报告和审定财务报表 int64。 。 。 .

取名问. 巢穴类型以其属性来命名(author → Author),或之后 title 如果设置。 没有标题的矩阵项目获得一个 Item 后缀和地图值a Value 后缀. Go 和 TypeScript 将它们平整(PostGridV1Post) (中文(简体) ). 共享类型以自身命名 (单位:千美元)image → Image)),其名称不可能是相形见绌的生成. 地产名称为骆驼卡塞德(去:PascalCased 有标准 初始化,例如:. avatarUrl → AvatarURL),保留了原JSON密钥.

清单的兼容性规则

Apps和作曲家独立部署,而旧的App版本长期被安装. 所以,一个岛屿版本的改变必须保持 两者 工作方向: 旧应用程序解码 新作曲家的有效载荷,以及新作曲家旧作曲(apps可先发作)的解码. 客户端跳过 道具不解码的岛屿(secret §4.4),所以一次突破性的改变悄悄地隐藏了该岛.

一岛版内的变化允许?
添加可选属性✅
删除可选属性qq 旧应用程序已经处理它 缺席
变动 description 或者说 title,重新排列enum值页:1 title 更改重命名生成的类型, 您的编译器将指出这些类型)
添加所需的属性新应用程序拒绝尚未发送的作曲家的有效载荷
删除所需的属性旧的应用程序需要它
选择或要求财产❌
更改类型, format,或整数大小❌
添加或去除 enum 值qq应用无法解码他们不知道的值
删除岛屿版本{\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}但是只支持这个版本的应用程序 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}停止接收这个岛

在 a 中进行分解更改 新岛版 (新设) profile-header.v3.json和保持旧的 已经发布的应用程序版本 .

在一个岛屿版的字符串和应用程序字符串可以添加,它们的描述和 词变了 删除一个, 改变其参数, 或使其计数或不计数, 正在打破: 已释放 应用程序仍然显示, 与他们建造的参数.

行动遵循同样的规则(第5.1节)。 已发布应用程序继续发送旧输入和解码 结果和错误细节,所以 input, (中文(简体) ), result 每个错误 details 遵循上表. 由于客户端将未知代码视为通用代码,可添加或删除已声明的错误代码 失败。 给出已有错误 details或者把他们带走 是破碎的 删除动作 版本只警告: 应用程序仍然称它得到 unsupported_action_version。 。 。 .

在CI里检查

compat 与先前的状态相比

client-compose-codegen compat client-compose.codegen.json --base origin/main   # a git ref
client-compose-codegen compat client-compose.codegen.json --base-dir ./old-islands
✖ profile-header v2 · props.badge: became required: new apps would reject payloads from a composer that omits it

1 breaking change(s) in client-compose.codegen.json compared with origin/main.
Put them in a new island version instead (profile-header v3), and keep the old version for apps already released.

在 GitHub 动作中,请查看 fetch-depth: 0 通过 --base "origin/$GITHUB_BASE_REF" 牵出 请求.

测试

codegen/test/fixtures/islands 覆盖每个支持 特性。 它所生成的输出通过Go和TypeScript的测试被编译并解码.

版本与发布记录

@client-compose/codegen 共发布 13 个版本,首次发布于 2026/10/19;过去 12 个月发布了 13 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.12.1latest2026/11/046 天前
0.11.02026/10/2911 天前
0.10.02026/10/2911 天前
0.9.02026/10/2911 天前
0.8.02026/10/2813 天前
0.7.02026/10/2713 天前

关于 @client-compose/codegen 的常见问题

@client-compose/codegen 是什么?

从客户端编译岛列表中生成Go和TypeScript的岛道具类型.

如何安装 @client-compose/codegen?

在项目目录运行 npm install @client-compose/codegen,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 client-compose-codegen,可以用 npx client-compose-codegen 直接运行。

@client-compose/codegen 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@client-compose/codegen 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@client-compose/codegen 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@client-compose/codegen 可以商用吗?

@client-compose/codegen 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@client-compose/codegen 的下载量有多少?

根据 npm 官方下载统计,@client-compose/codegen 在 2026/10/10 – 2026/11/08 这 30 天内被下载 1,787 次,日均约 60 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@client-compose/codegen 还在维护吗?

最新版本 0.12.1 发布于 2026/11/04(6 天前);至今共发布 13 个版本,其中过去 12 个月发布了 13 个;首次发布于 2026/10/19。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。