- 文档
- 编程语言
【免费下载链接】cangjie_docs
仓颉编程语言开发者文档。
仓颉中心仓(Cangjie Central Repository)是仓颉语言的三方库托管平台,而cjpm(仓颉项目管理工具)内置的中心仓客户端正是通过与中心仓仓库的一整套 HTTP 接口完成制品包的上传、下载与索引同步。本文基于文档仓库中的中心仓通信规格,逐接口拆解cjpm publish、依赖下载与cjpm update背后实际发起的请求格式(方法、URL、Header、Body 的二进制布局),并结合元数据规格、客户端配置与cjpm命令手册补充触发时机与排错方法,帮助你在发布制品失败或依赖解析异常时快速定位通信层问题。
通信基地址与鉴权来源
所有通信接口都以用户在cangjie-repo.toml中配置的repository.home.registry为基地址。根据中心仓客户端配置文档,该配置文件的典型格式为:
[repository.cache] path = "/path/to/repository/cache" # 本地存放路径 [repository.home] registry = "https://pkg.cangjie-lang.cn/registry" # 中心仓 url token = "user-token" # 用户个人 token各字段与通信接口的关系如下:
repository.home.registry:中心仓仓库地址,上传/下载/索引三类请求的 URL 前缀。官方默认值为https://pkg.cangjie-lang.cn/registry;repository.home.token:用户个人 token,仅在上传制品包时通过Authorization请求头携带,用于用户认证(token 可在中心仓官网个人中心创建、刷新和删除,参见中心仓官网章节);repository.cache.path:本地缓存路径。若为相对路径则相对当前cangjie-repo.toml;留空时Linux/macOS下生效路径为$HOME/.cjpm,Windows下为%USERPROFILE%\.cjpm。假设最终生效路径为CACHE_PATH,则从中心仓下载的制品包源码会存放在${CACHE_PATH}/repository目录下。
cangjie-repo.toml有三个搜索位置,cjpm按以下顺序查找直到命中为止(与cjpm 使用手册中"项目管理配置文件说明"一节一致):
- 模块内与
cjpm.toml同级目录的cangjie-repo.toml; - 用户目录下
.cjpm目录内的cangjie-repo.toml($HOME/.cjpm/cangjie-repo.toml或%USERPROFILE%\.cjpm\cangjie-repo.toml); - 仓颉
SDK中tools/config目录下的cangjie-repo.toml(SDK 默认自带该文件,全部为默认值)。
读取到第一个有效文件后即使用该文件,忽略更低优先级的配置。理解这一点很重要:如果你在SDK默认配置之外没有显式配置token,上传制品包时就会得到认证失败(401)。
制品包上传接口(对应cjpm publish)
cjpm publish会将bundle打包的cjpm模块对应的制品包和元数据发布到中心仓。根据制品包发布文档,bundle成功后会在编译产物目录(默认target)中生成模块名-版本号.cjp的制品源码包(tar.gz格式)和元数据文件meta-data.json;执行publish时,若任一文件缺失、或元数据中的制品包校验码与制品包不匹配,cjpm会先重新执行默认bundle流程再上传。
对应的API规格为:
| 项目 | 规格 |
|---|---|
| 方法 | POST |
| URL(无组织模块) | /pkg/${module-name} |
| URL(组织内模块) | /pkg/${module-name}?organization=${org-name} |
| Header | 用户 token:Authorization=${token} |
| Body | 元数据 + 制品包两段二进制内容(见下) |
请求体是"元数据段 + 制品包段"的自定义二进制布局,而不是简单的multipart表单。具体字节排布为:
┌────────────────────────────────────────────────────────────────┐ │ 元数据段 │ │ 元数据版本 (1 byte) 对应元数据内的 meta-version │ │ 元数据长度 (4 byte) 对应元数据的字节长度 m │ │ 元数据内容 (m byte) 对应整个元数据字节流 │ ├────────────────────────────────────────────────────────────────┤ │ 制品包段 │ │ 制品包版本 (1 byte) 对应索引内的 index-version │ │ 制品包长度 (4 byte) 对应制品包的字节长度 n │ │ 制品包内容 (n byte) 对应整个制品包字节流 │ └────────────────────────────────────────────────────────────────┘几个关键点:
meta-version/index-version:分别对应元数据规格中meta-data.json顶层的meta-version字段(元数据规格版本号)和index索引内的index-version字段(索引规格版本号),当前文档示例中两者取值均为1。这种"1 字节版本 + 4 字节长度 + 内容"的自描述格式,使仓库端可以在不解析内容的情况下按规格版本做入库校验;- 版本号不体现在 URL 中:URL 只区分模块名(与所属组织),具体版本信息在元数据/索引内容中携带。例如上传无组织模块
demo1的1.0.0版本时,url = /pkg/demo1;上传组织org的模块demo2的2.0.0版本时,url = /pkg/demo2?organization=org。这也意味着同一制品的不同版本走的是同一个 URL,冲突检测由仓库端基于"组织名 + 制品名 + 版本号"唯一性完成; publish成功的隐含前提:cangjie-repo.toml中配置了有效 token;上传的制品包在仓库内唯一(不存在同组织名、制品名、版本号的已有制品);若制品属于某个组织,token 对应用户必须是该组织成员;制品包须通过中心仓安全扫描。
制品包下载接口(依赖解析 /install场景)
cjpm在成功进行依赖解析后,会基于最终确定的每个制品的版本,向中心仓发送下载对应制品包的请求。对应的API规格为:
| 项目 | 规格 |
|---|---|
| 方法 | GET |
| URL(无组织制品) | /pkg/${module-name}/version |
| URL(组织内制品) | /pkg/${module-name}/version?organization=${org-name} |
| 返回数据 | tar.gz格式的源码压缩包 |
与上传不同,下载 URL 中直接体现版本号,且不携带Authorization请求头(下载是公开读操作,不需要 token)。例如:
- 下载无组织制品
demo1的1.0.0版本制品包:url = /pkg/demo1/1.0.0; - 下载组织
org的制品demo2的2.0.0版本制品包:url = /pkg/demo2/2.0.0?organization=org。
这个接口的触发场景包括:
- 在本地项目的
cjpm.toml中以中心仓形式声明依赖(如dep1 = "1.0.0"、"org::dep4" = "4.0.0",格式详见制品包使用文档),执行cjpm build/run等命令时,依赖解析确定版本后按制品逐个下载,解压到CACHE_PATH下的本地缓存; - 使用
cjpm install [org::]name-version从中心仓安装可执行程序。根据 cjpm 手册install一节,例如cjpm install aoo-1.0.0会下载无组织制品aoo的1.0.0版本,cjpm install org::boo-2.0.0会下载组织org下制品boo的2.0.0版本,下载源码包后本地编译安装到${CACHE_PATH}/bin与${CACHE_PATH}/libs。
制品包本身与bundle产物结构一致(tar.gz源码包,文件名模块名-版本号.cjp),下载后可用tar直接解包。
索引下载接口(依赖解析 /cjpm update场景)
制品包下载之前,cjpm必须先知道某制品有哪些版本、每个版本的依赖约束与校验码——这些信息来自制品索引。cjpm在依赖解析过程中,或在执行cjpm update命令时,会向中心仓发送下载对应制品索引的请求。根据 cjpm 手册update一节:"update用于将cjpm.toml里的内容更新到cjpm.lock……如果配置了项目管理配置文件cangjie-repo.toml,cjpm update还将尝试更新本地的所有中心仓索引文件。"
对应的API规格为:
| 项目 | 规格 |
|---|---|
| 方法 | GET |
| URL(无组织制品) | /index/${mo}/${du}/${module-name} |
| URL(组织内制品) | /index/${mo}/${du}/${module-name}?organization=${org-name} |
| 返回数据 | 制品索引文件,其中每行均为一个json索引条目 |
URL 中的${mo}/${du}是由模块名派生的两级目录前缀。从文档给出的示例可以看出其拆分规则:
- 下载无组织制品
aabbcc的索引时,url = /index/aa/bb/aabbcc:${mo}取模块名前 2 个字符(aa),${du}取接下来 2 个字符(bb); - 下载组织
org的制品dep的索引时,url = /index/de/p/dep?organization=org:3 字符的模块名按"前 2 字符 + 其余"拆分,得到${mo}=de、${du}=p。
这种两级散列前缀(类似常见包仓库的 shard 设计)的目的是把索引文件打散到不同子路径下,避免单一目录下文件数爆炸。返回的索引文件是NDJSON(每行一个json索引条目)格式,每一行对应一个版本的索引条目。对照元数据规格,单条索引(index对象)的规格为:
{ "organization": "cangjie", // 组织名,为空则为无组织 "name": "demo", // 模块名 "version": "1.0.0", // 版本号 "cjc-version": "1.0.0", // 仓颉 SDK 版本号 "dependencies": [ { "name": "dep1", "require": "1.1.0", "target": null, // 平台隔离标识,null 表示不区分平台 "type": null, // 编译模式标识,null 表示不区分编译模式 "output-type": null // 编译产物类型标识,null 表示遵循对应源码模块的 package.output-type } ], "test-dependencies": [], // 测试依赖项,与源码依赖项格式一致 "script-dependencies": [], // 构建脚本依赖项,与源码依赖项格式一致 "sha256sum": "...", // 对应制品包的 SHA-256 校验码,用于验证制品包完整性 "yanked": false, // 制品包弃用标识,yanked == true 表示该制品包已被弃用 "index-version": 1 // 索引规格版本号 }由此可见,索引下载与制品包下载在客户端协作的方式是:先GET /index/...拿到各版本的依赖需求、cjc-version与sha256sum,完成依赖解析选出目标版本,再GET /pkg/name/version下载制品包,并用sha256sum验证下载内容完整性。依赖冲突(如两个模块分别要求dep1的1.0.0和2.0.0)会直接导致解析失败,此时可用cjpm update刷新本地索引缓存获取最新制品信息,或按制品包使用文档中的方法(调整版本区间、replace强制指定等)解决。
返回码规格与故障定位
三类接口共用同一套返回码规格,完整列表如下:
| 返回码 | 含义 | 典型触发场景与排查方向 |
|---|---|---|
200 | 成功 | — |
400 | 参数错误,可能是元数据或索引解析错误 | 上传场景多为meta-data.json格式不符合元数据规格(如缺字段、meta-version不匹配);下载/索引场景多为 URL 中的模块名、组织名、版本号不符合制品规格(名称须为 3~64 位字母、数字、下划线,版本号须为Major.Minor.Patch格式) |
401 | 用户认证失败 | cangjie-repo.toml中repository.home.token未配置、已失效或填错;token 需在中心仓官网个人中心创建/刷新 |
403 | 用户无权限或制品包名已被占用 | 制品包名不区分大小写,大小写不同的名称视为同一制品包;组织制品需 token 对应用户为该组织成员 |
404 | 文件不存在 | 请求的制品名、组织名或版本号在中心仓中不存在(拼写错误或该版本从未发布) |
409 | 上传的制品包与仓库已有制品包冲突 | 同组织名 + 制品名 + 版本号的制品已存在。制品包不可覆盖,应提升cjpm.toml中的version后重新bundle+publish |
429 | 请求频率超限 | 请求过于频繁,稍后重试 |
>=500 | 服务器故障 | 中心仓服务端异常,稍后重试 |
几点实践提示:
- 区分 401 与 403:
401是"你是谁"没通过(token 无效/缺失),403是"你能不能做这件事"没通过(非组织成员,或名字撞车)。二者都出现在上传路径上,但排查动作完全不同; 409不是版本升级通道:由于 URL 不携带版本号、且制品包以"组织名 + 制品名 + 版本号"保证唯一,重复发布同一版本必然得到409,正确的做法是修改版本后重新打包;- 名称大小写陷阱:制品包名在仓库端按不区分大小写处理,
Demo与demo是同一个制品名,命名时容易因此误判"名字可用"; 429的规避:批量操作(如连续publish多个版本、大范围update)时注意控制请求节奏。
通信规格小结
从cjpm客户端视角,一次完整的中心仓交互链路可以归纳为:
依赖解析阶段 cjpm update / build / run ├─ GET /index/${mo}/${du}/${name}[?organization=org] 拉取 NDJSON 索引(含依赖约束、sha256sum、yanked) └─ GET /pkg/${name}/${version}[?organization=org] 下载 tar.gz 制品包并做 SHA-256 校验 发布阶段 cjpm bundle && cjpm publish └─ POST /pkg/${name}[?organization=org] Header: Authorization=${token} Body: [meta-version(1B) + len(4B) + meta-data.json(mB)] + [index-version(1B) + len(4B) + 制品包(nB)]三组接口在 URL 命名上形成了清晰的对称关系:上传用/pkg/${name}(无版本,写入),下载用/pkg/${name}/${version}(带版本,读取),索引用/index/${mo}/${du}/${name}(两级散列前缀,读取);组织统一通过organization查询参数表达,无组织制品则省略该参数。掌握这套规格后,无论是调试publish的 401/403/409 错误、验证下载包完整性,还是理解cjpm update刷新索引缓存的机制,都有了可对照的协议层依据。
相关文档索引
- 中心仓概述:中心仓三大组件(官网、客户端、仓库)划分;
- 中心仓制品规格:制品包/制品/组织的定义与命名规则;
- 中心仓客户端配置:
cangjie-repo.toml字段与搜索顺序; - 制品包发布:
bundle打包范围规则与publish流程; - 制品包使用:中心仓依赖声明格式、版本区间与冲突解决;
- 中心仓元数据规格:
meta-data.json与索引条目字段详解; - 中心仓通信规格(原文,中文) / 英文版本:本文所基于的通信规格定义;
- cjpm 使用手册:
update、bundle、publish、install命令的完整参数说明。
- 文档
- 编程语言
【免费下载链接】cangjie_docs
仓颉编程语言开发者文档。
相关推荐
仓颉中心仓通信规格详解:cjpm 如何与中心仓交互上传/下载制品与索引
仓颉中心仓通信规格详解:cjpm 如何与中心仓交互上传/下载制品与索引 本文围绕仓颉中心仓(Cangjie Central Repository)的通信规格展开
文档编程语言仓颉中心仓制品包发布指南:cjpm bundle 与 publish 全解析
仓颉中心仓制品包发布指南:cjpm bundle 与 publish 全解析 本文基于仓颉开发者文档仓库(cangjie_docs)中的中心仓客户端文档,系统讲
文档编程语言仓颉中心仓制品规格详解:制品包、制品与组织的概念及命名规范
仓颉中心仓制品规格详解:制品包、制品与组织的概念及命名规范 仓颉中心仓(Cangjie Central Repository)以 制品 为单位统一管理三方库,本
文档编程语言
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考