
Dagger TypeScript SDK ErrorValue 类完全指南结构化错误附加值的读取与类型体系【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/dagger导读ErrorValue是 Dagger 核心 GraphQL API 中Error对象的一个组成单元用于以“名称 JSON 值”的形式为错误附加结构化上下文信息如错误码、失败文件路径、重试信息等。本文以dagger.io/daggerTypeScript SDK 生成的客户端类 ErrorValue 为主线完整讲解其构造方式、三个核心方法id、name、value的语义与调用链并结合仓库中 GraphQL Schema、Go 核心实现与测试用例深入剖析ErrorValue的底层数据模型帮助你准确掌握如何在 Dagger 管道中读取和使用结构化错误扩展信息。一、ErrorValue 是什么错误扩展的结构化载体在 Dagger 中错误并不只是“一条字符串”。当模块或引擎在执行过程中抛出错误时可以携带一组结构化的扩展信息extensions。从仓库核心实现看Error对象包含两个字段core/error.gotype Error struct { Message string field:true doc:A description of the error. Values []*ErrorValue field:true doc:The extensions of the error. }其中Values是[]*ErrorValue即一组错误附加值ErrorValue本身的结构同样定义在 core/error.gotype ErrorValue struct { Name string field:true doc:The name of the value. Value JSON field:true doc:The value. }也就是说每个ErrorValue由两个字段构成name值的名称是扩展信息的键value任意 JSON 编码的值是扩展信息的载荷。ErrorValue与Error一样实现了dagql.PersistedObject与dagql.PersistedObjectDecoder接口core/error.go因此它可以像 Dagger 中其他核心对象一样被持久化、编码与解码——这也解释了为什么 TypeScript 客户端中它会拥有id方法。二、TypeScript 客户端中的类签名总览ErrorValue类在生成的 TypeScript SDK 中位于 sdk/typescript/src/api/client.gen.ts完整的声明结构如下成员签名说明继承extends BaseClient所有 Dagger API 客户端对象的公共基类构造器new ErrorValue(ctx?, _id?, _name?, _value?)仅供内部使用不要直接new创建对象id()PromiseErrorValueID返回该对象的唯一标识符name()Promisestring返回错误附加值的名称value()PromiseJSON返回错误附加值的 JSON 载荷1. 类继承关系BaseClientErrorValue直接继承自BaseClient。从生成的源码可见其私有字段与构造器sdk/typescript/src/api/client.gen.tsexport class ErrorValue extends BaseClient { private readonly _id?: ID undefined private readonly _name?: string undefined private readonly _value?: JSON undefined /** * Constructor is used for internal usage only, do not create object from it. */ constructor(ctx?: Context, _id?: ID, _name?: string, _value?: JSON) { super(ctx) this._id _id this._name _name this._value _value } ... }三个私有字段_id、_name、_value分别对应底层 GraphQL 对象的id、name、value字段构造器接收这四个参数用于缓存已知值。这种“字段缓存 惰性查询”的模式是 Dagger 生成客户端的通用风格如果客户端已经持有该字段的值就直接返回避免额外的 GraphQL 请求。2. 构造器仅供内部使用官方文档明确指出Constructor is used for internal usage only, do not create object from it.构造器参数ctxContext、_idErrorValueID、_namestring、_valueJSON均为可选。日常开发中你不需要也不应该直接实例化ErrorValue——它是通过查询Error.values字段或加载其 ID由 SDK 自动构造的。三、三个核心方法详解1.id()获取唯一标识符id async (): PromiseID { if (this._id) { return this._id } const ctx this._ctx.select(id) const response: AwaitedID await ctx.execute() return response }返回类型为PromiseErrorValueID若客户端已持有_id则直接返回否则通过 GraphQL 选择集select(id)惰性查询。ErrorValueID是 Dagger 的标量类型之一对应 GraphQL Schema 中的scalar ErrorValueID。其 TypeScript 类型别名定义在 type-aliases/ErrorValueID.mdtype ErrorValueID string { __ErrorValueID: never }即它是一个带 branded 标记的字符串用于在类型层面区分普通字符串与 Dagger 对象标识符。在 GraphQL Schema 中core/schema/testdata/base_schema.graphqlstype ErrorValue implements Node { A unique identifier for this ErrorValue. id: ID! The name of the value. name: String! The value. value: JSON! } A unique identifier for an object. scalar ErrorValueID注意ErrorValue实现了Node接口这与id()方法的存在直接对应。2.name()读取附加值的名称name async (): Promisestring { if (this._name) { return this._name } const ctx this._ctx.select(name) const response: Awaitedstring await ctx.execute() return response }返回类型为Promisestring对应核心 Go 结构体中Name string字段core/error.go文档描述为 “The name of the value”。name是扩展信息的键。例如错误扩展{code: 42}中键code就会成为一个ErrorValue.name。3.value()读取 JSON 载荷value async (): PromiseJSON { if (this._value) { return this._value } const ctx this._ctx.select(value) const response: AwaitedJSON await ctx.execute() return response }返回类型为PromiseJSON对应核心 Go 结构体中Value JSON字段core/error.go文档描述为 “The value”。JSON是 Dagger 的另一个 branded 标量定义在 type-aliases/JSON.mdtype JSON string { __JSON: never }其文档描述为 “An arbitrary JSON-encoded value”即任意 JSON 编码的字符串。在 Go 端它对应core.JSON类型底层就是json.RawMessage语义。四、从 GraphQL 到 TypeScriptErrorValue 的完整数据链路1. Schema 层Error.values 与 ErrorValue在 Dagger 的基础 GraphQL Schema 中core/schema/testdata/base_schema.graphqlsError类型声明了type Error implements Node { id: ID! message: String! The extensions of the error. values: [ErrorValue!]! withValue(name: String!, value: JSON!): Error! }即Error.values返回一个[ErrorValue!]!列表——这是获取ErrorValue对象的唯一入口Error.withValue(name, value)用于向错误追加一个新的附加值返回值是新的Error对应的scalar ErrorID、scalar ErrorValueID分别作为两个对象类型的标识符。2. 解析器层withValue 如何产生 ErrorValueSchema 注册位于 core/schema/error.godagql.Fields[*core.Error]{ dagql.Func(withValue, s.withValue). Doc(Add a value to the error.), }.Install(dag) dagql.Fields[*core.ErrorValue]{}.Install(dag)withValue的实现core/schema/error.gofunc (s *errorSchema) withValue(ctx context.Context, self *core.Error, args struct { Name string doc:The name of the value. Value core.JSON doc:The value to store on the error. }) (*core.Error, error) { return self.WithValue(args.Name, args.Value), nil }底层Error.WithValue采用不可变风格克隆当前错误后追加一个ErrorValue并返回新错误对象core/error.gofunc (e *Error) WithValue(name string, value JSON) *Error { cp : e.Clone() cp.Values append(cp.Values, ErrorValue{ Name: name, Value: value, }) return cp }3. 扩展信息如何最终暴露ErrorValue在内部服务于错误扩展extensions机制。Error.Extensions()会把Values中每个ErrorValue反序列化为键值对core/error.gofunc (e *Error) Extensions() map[string]any { ext : map[string]any{} for _, v : range e.Values { var val any json.Unmarshal(v.Value, val) ext[v.Name] val } return ext }此外当引擎需要把普通 Go error 包装为 DaggerError对象时NewErrorFromErrcore/error.go会检查错误是否实现了dagql.ExtendedError接口若实现了就把其Extensions()中的每个键值对通过withValue选择器逐条写入ErrorValue最终组合成一个 Dagger 查询序列。从这些源码可以推断ErrorValue既是 Dagger 内部错误扩展的持久化载体也是用户通过 GraphQL/客户端查询错误附加信息的结构化入口。五、JSON 载荷的取值语义与测试验证value()返回的 JSON 可以承载任意 JSON 数据类型。仓库中的测试用例 core/error_test.go 系统验证了ErrorValue.Value对各种 JSON 类型的处理测试场景ErrorValue.Value反序列化结果简单字符串hello worldhello world数字42float64(42)布尔值truetruenullnullnil对象{file: test.go, line: 123}map[string]any{...}数组[a, b, c][]any{a,b,c}多值组合多个 ErrorValue合并后的 map特别地测试TestError_Extensions_PreventDoubleEncodingcore/error_test.go确保Value中的 JSON 被正确反序列化为结构化对象而不会以原始 JSON 字符串的形式再次编码避免双重/三重编码问题。这些测试说明当你在 TypeScript 端调用value()拿到JSON字符串后可以安全地JSON.parse出原始结构当你在 Go/引擎侧看到扩展信息时它们已经是反序列化后的map[string]any。六、典型使用方式遍历 Error.values虽然ErrorValue类本身不建议直接构造但它是消费 Dagger 错误扩展信息的关键类型。典型的使用模式是从Error对象出发import { connect } from dagger.io/dagger const result await connect(async (client) { // ... 执行可能失败的操作捕获 dagger.Error 类型错误 try { await client.container() .from(alpine:3.20) .withExec([sh, -c, exit 1]) .stdout() } catch (e) { // 假设 e 是带有 values 扩展的 Dagger 错误 const err e as any // values 为 ErrorValue[]每个元素可调用 id() / name() / value() for (const ev of err.values ?? []) { const name await ev.name() const value await ev.value() // JSON 字符串可 JSON.parse console.log(extension[${name}] , JSON.parse(value)) } } })几点实践提示Error.values在 Schema 中是非空数组[ErrorValue!]!但具体某个错误是否携带扩展取决于产生错误的一方是否调用过withValue每个ErrorValue都可以独立调用id()获取标识符之后可通过 Schema 中的loadErrorValueFromID(id: ErrorValueID!): ErrorValue!见 core/schema/testdata/base_schema.graphqls从 ID 重新加载对象value()返回的JSON是 branded string 类型取值后需要自行JSON.parse还原为运行时对象。七、SDK 代码生成ErrorValue 从何而来ErrorValue类并非手写代码而是由 Dagger 的 SDK 代码生成器从 GraphQL Schema 自动生成。TypeScript 客户端源文件 sdk/typescript/src/api/client.gen.ts 即产物之一官方 API 参考文档含本文所讲的 ErrorValue.md也是基于同一 Schema 生成的。因此若上游 Schema 中ErrorValue类型发生变更生成的类与文档会同步更新你看到的方法签名id/name/value与 Schema 字段id: ID!/name: String!/value: JSON!一一对应一一映射不存在额外的隐藏行为。八、总结ErrorValue虽然只是Error对象的一个小组件但它承载着 Dagger 结构化错误扩展的核心设计数据模型namevalue(JSON)两个字段定义于 core/error.go实现持久化对象接口Schema 契约ErrorValue implements Node包含id、name、value三字段通过Error.values与withValue与Error关联base_schema.graphqls客户端体验TypeScript 端ErrorValue类继承BaseClient以惰性查询方式暴露id()、name()、value()三个异步方法构造器仅供内部使用client.gen.ts取值语义value是任意 JSON 编码的字符串底层在 Go 端反序列化为map[string]any测试用例完整覆盖了字符串、数字、布尔、null、对象、数组等场景error_test.go。掌握ErrorValue就掌握了在 Dagger 中读取结构化错误上下文的标准方式——无论是调试模块故障、透传自定义错误码还是在引擎层面消费扩展信息都能做到心中有数。【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/dagger创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考