后端【免费下载链接】graffleSimple GraphQL Client for JavaScript. Minimal. Extensible. Type Safe. Runs everywhere.项目地址https://gitcode.com/gh_mirrors/gr/graffle点击查看免费下载本文以 Graffle 官方示例 Return Error Execution 为核心讲解如何通过output.errors配置把 GraphQL **执行错误execution与其他错误other**分别路由到返回或抛出两条通道实现同一客户端内部分错误返回、部分错误抛出的混合错误策略。读完本文你将掌握 Graffle 输出配置的完整参数语义、底层判定逻辑configuration.ts 与 handle.ts以及如何从类型层面获得与运行时完全一致的错误联合类型。场景与动机Graffle 默认采用传统 GraphQL 输出风格执行错误被包装在结果的errors字段中返回而网络错误、扩展抛出的异常等其他错误则会直接抛出。但在很多业务场景中这种一刀切的行为并不理想你想让执行错误如参数校验失败、字段解析失败以值的形式返回方便在数据流中统一处理同时又希望扩展错误、网络错误如 HTTP transport 中 fetch 抛出的异常继续以抛出异常的方式传播避免把基础设施故障和业务校验失败混为一谈。Graffle 的output.errors配置正是为此设计它把错误按类别拆分为execution与other并允许为每一类单独指定输出通道。配置总览errors 双类别与 default 解析规则在 configuration.ts 中错误类别与通道的类型定义如下export type OutputChannel throw | return export type OutputChannelConfig throw | return | default export type ErrorCategory execution | other配置键可选值含义output.errors.executionthrow/return/defaultGraphQL 执行结果中的错误传统上位于执行结果errors字段中output.errors.otherthrow/return/default其他错误HTTP transport 中 fetch 抛出的网络错误、扩展extension抛出的错误等output.defaults.errorChannelthrow/return当某个类别设为default时最终采用的通道默认值为throw两个核心语义需要明确default不是第三种通道它表示交给默认通道裁决。从 configuration.ts 的readErrorCategoryOutputChannel可以看到default会被解析为defaults.errorChannel的值export const readErrorCategoryOutputChannel ( output: Normalized, errorCategory: ErrorCategory, ): OutputChannel | false { if (output.errors[errorCategory] default) { return output.defaults.errorChannel } return output.errors[errorCategory] }execution与other的默认值都是default因此若不做任何设置二者都会落到defaults.errorChannel即throw上。默认配置的归一化结果在 configuration.tsconst default_ { defaults: { errorChannel: throw, }, envelope: { enabled: false, errors: { execution: true, other: false, }, }, errors: { execution: default, other: default, }, }完整示例execution 返回、other 抛出关联文档对应的可运行示例位于 output_return-error_return-error-execution__return-error-execution.tsimport { Graffle } from ../$/graffle/_.js const pokemon Graffle .create({ output: { envelope: false, errors: { execution: return, other: throw, }, }, }) // 1. 空 Pokemon 名称产生的 __execution__ 错误将被 ***返回***。 const result await pokemon.mutation.addPokemon({ $: { name: , hp: 1, defense: 0, attack: 0, $type: water }, // ^^ name: true, }) // 2. 内联扩展产生的 __other__ 错误将被 ***抛出***。 try { await pokemon .anyware(({ encode: _ }) { throw new Error(Something went wrong.) }) .query .pokemons({ name: true }) } catch (error) { console.log(error) }示例中的两个关键点envelope: false表示不使用信封输出即成功时直接返回data错误时按通道返回错误对象或抛出异常提交addPokemon时传入空字符串name服务端示例使用 zod 校验的 pokemon schema返回执行错误Pokemon name cannot be empty.因为execution: return这个错误不会抛出而是作为函数返回值出现。返回的执行错误长什么样示例运行后的第一个输出见 返回的执行错误输出是一个ContextualAggregateErrorContextualAggregateError errors: [ ContextualError: [ { code: too_small, minimum: 1, type: string, inclusive: true, exact: false, message: Pokemon name cannot be empty., path: [ name ] } ] context: { locations: [ { line: 2, column: 3 } ], path: [ addPokemon ] }, _tag: ContextualError ], context: {}, _tag: ContextualAggregateError,结构解读外层是ContextualAggregateError聚合了执行结果中的所有错误内层每个错误是ContextualError携带 zod 校验的原始细节code、minimum、type、path等以及 GraphQL 上下文错误所在的locations与字段路径path: [addPokemon]这两个错误类型来自wollybeard/kit的Err命名空间并在 handle.ts 中由执行结果的errors字段映射生成if (result.value.errors result.value.errors.length 0) { const error new Err.ContextualAggregateError({ message: One or more errors in the execution result., context: {}, errors: result.value.errors.map(e { if (e instanceof Error) return e const { message, ...context } e return new Err.ContextualError({ message, context }) }), }) if (isThrowExecution) throw error if (isReturnExecution) return error ... }由于本示例中execution: returnisReturnExecution为真这个聚合错误被直接返回await pokemon.mutation.addPokemon(...)得到的就是它。抛出的其他错误长什么样第二个输出是内联扩展anyware在encode钩子中抛出Error(Something went wrong.)后被包装的ContextualErrorContextualError: There was an error in the interceptor anonymous (use named functions to improve this error message) while running hook encode. context: { hookName: encode, source: extension, interceptorName: anonymous }, cause: Error: Something went wrong.解读错误消息提示在名为 anonymous 的拦截器运行encode钩子时出错并建议使用命名函数以改善错误消息context记录了出错位置的三要素hookNameencode、sourceextension、interceptorNameanonymouscause保留了你抛出的原始错误Error: Something went wrong.形成错误链便于追踪根因。因为配置为other: throw这条错误被handleOutput中的isThrowOther分支捕获并直接抛出handle.ts从而被示例中的try/catch捕获。底层判定逻辑handleOutput 的分支全景handleOutput 是理解这套配置的关键。它先读取归一化后的配置再按是否传统 GraphQL 输出 → 是否信封 → 按类别读取通道的顺序决策const isThrowOther readErrorCategoryOutputChannel(c, other) throw (!c.envelope.enabled || !c.envelope.errors.other) const isReturnOther readErrorCategoryOutputChannel(c, other) return (!c.envelope.enabled || !c.envelope.errors.other) const isThrowExecution readErrorCategoryOutputChannel(c, execution) throw (!c.envelope.enabled || !c.envelope.errors.execution) const isReturnExecution readErrorCategoryOutputChannel(c, execution) return (!c.envelope.enabled || !c.envelope.errors.execution)判定要点每个类别的throw/return判定都要求信封未启用或信封中对应错误类别未开启避免与信封内的错误字段行为冲突当result instanceof Error即其他错误如扩展异常时优先走other通道的 throw/return当执行结果带errors字段时先构建ContextualAggregateError再走execution通道的 throw/return若信封启用最终返回完整的信封data、errors、extensions否则只返回data。另外isOutputTraditionalGraphQLOutput 提供了一条快捷路径当envelope.enabled为真、envelope.errors.execution为真、envelope.errors.other为假时直接判定为传统 GraphQL 输出并原样返回执行结果——这正是Preset.traditionalGraphqlOutput的行为见 output_preset__standard-graphql.ts。类型层面返回的错误也进入返回值联合类型Graffle 的类型系统与运行时保持一致。在 handle.ts 中IfConfiguredGetOutputErrorReturns会根据配置把会返回的错误类型并入返回值type IfConfiguredGetOutputErrorReturns$OutputConfig extends Normalized | (ConfigGetOutputError$OutputConfig, execution extends return ? GraphqlKit.Request.GraphQLExecutionResultError : never) | (ConfigGetOutputError$OutputConfig, other extends return ? Ware.ResultFailure : never)也就是说当execution: return时执行错误类型GraphQLExecutionResultErrorContextualAggregateError会出现在调用返回值的联合类型中当other: return时Ware.ResultFailure如扩展错误包装也会加入。这种设计意味着你不需要try/catch就能从类型上感知这次调用可能返回错误值示例源码中的type _result typeof result正是用来在编辑器里确认这一点——result的类型是数据或执行错误的联合。更多输出错误策略同族示例对照仓库的 20_output 目录围绕同一主题提供了多个对照示例帮助你理解通道配置的全貌output_return-error.ts通过defaults: { errorChannel: return }让所有类别的错误都默认返回是全部返回的极简写法output_envelope_envelope-error__envelope-error.ts启用信封并开启envelope.errors.execution与envelope.errors.other把两类错误都嵌入信封的errors字段output_envelope_envelope_error-throw__envelope-error-throw.ts信封启用但两类错误都设为false此时即使启用信封错误仍抛出output_preset__standard-graphql.ts使用Preset.traditionalGraphqlOutput复刻传统 GraphQL 执行结果输出。对照关系可以总结为配置意图推荐写法传统输出errors 在结果里、其他错误抛出output: Preset.traditionalGraphqlOutput全部错误返回output: { defaults: { errorChannel: return } }执行错误返回、其他错误抛出output: { errors: { execution: return, other: throw } }本文主题全部错误抛入信封output: { envelope: { errors: { execution: false, other: false } } }注意事项default的解析时机errors.execution/errors.other设为default时实际通道取决于defaults.errorChannel默认throw理解这一点才能准确预测行为信封与通道的优先级信封内errors.execution/errors.other为true会接管对应类别的错误放入信封此时errors通道配置的 throw/return 判定被跳过命名拦截器从抛出的其他错误消息可见anyware内联扩展默认名为anonymous为便于排障建议在真实代码中使用命名函数作为拦截器示例运行前提示例依赖仓库中通过graffle.config.ts生成的 pokemon schema 客户端examples/$/graffle可直接在 examples 目录下运行pnpm工作区中对应的 vitest 示例任务查看输出已生成输出见outputs/20_output。赞分享后端【免费下载链接】graffleSimple GraphQL Client for JavaScript. Minimal. Extensible. Type Safe. Runs everywhere.项目地址https://gitcode.com/gh_mirrors/gr/graffle点击查看免费下载相关推荐Graffle 请求输出模式完全指南Envelope 信封与错误处理通道throw/return配置详解Graffle 请求输出模式完全指南Envelope 信封与错误处理通道throw/return配置详解 本文是 GraffleSimple Graph后端Graffle 配置指南在 Envelope 输出模式下抛出错误output.envelope.errors 详解Graffle 配置指南在 Envelope 输出模式下抛出错误output.envelope.errors 详解 本文讲解 Graffle GraphQ后端F´ Svc::StaticMemory 组件深度解析基于静态内存池的 Buffer 分配器实现与配置指南F´ Svc::StaticMemory 组件深度解析基于静态内存池的 Buffer 分配器实现与配置指南 StaticMemory 是 F´F Prime后端上一篇解放你的Steam游戏成就3步掌握成就管理神器下一篇AssetStudio终极指南5分钟掌握Unity资源提取的核心技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考