Dagger TypeScript SDK FunctionArg 类详解:模块函数参数元数据的定义与读取
发布时间:2026/9/16 11:41:23 锦皓数字建站

Dagger TypeScript SDK FunctionArg 类详解模块函数参数元数据的定义与读取【免费下载链接】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本文基于 Dagger 仓库 version-0.20 版的 TypeScript SDK API 参考文档深入讲解FunctionArg类的职责边界、构造方式与全部方法并结合 sdk/typescript/src/api/client.gen.ts 中的生成代码与 GraphQL Schema 说明其底层实现。读完后你将能够在 Dagger 模块元编程场景中使用FunctionArg读取函数参数定义名称、类型、默认值、弃用说明理解生成客户端的懒加载取值机制并区分定义时参数规格与调用时参数值这两个不同概念。一、FunctionArg 是什么定义时的参数规格而非调用时的参数值FunctionArg是 Dagger TypeScript SDKdagger.io/dagger包生成代码位于 api/client.gen中的一个 API 类官方定义如下An argument accepted by a function. This is aspecificationfor an argument at function definition time, not an argument passed at function call time.也就是说它描述的是某个模块函数在声明时接受什么样的参数而不是某次调用实际传入了什么值。这个类在模块元编程module metaprogramming中非常关键当你通过Module/Function对象做代码生成、文档生成、参数校验或 CLI 补全时需要枚举每个函数接受哪些参数、参数是什么类型、有没有默认值、是否已弃用——这些信息正是通过FunctionArg对象提供的。与之相关、但方向相反的概念是FunctionCallArgValue见 FunctionCallArgValue.md它表示调用时实际传入的参数值。两者一个是规格一个是取值不可混淆。二、类结构与构造函数FunctionArg继承自BaseClient这是所有 Dagger API 对象的公共基类负责持有 GraphQL 查询上下文Context。构造函数new FunctionArg( ctx?, // Context _id?, // FunctionArgID _defaultAddress?, // string _defaultPath?, // string _defaultValue?, // JSON _deprecated?, // string _description?, // string _name?, // string ): FunctionArg文档明确指出Constructor is used for internal usage only, do not create object from it.构造函数仅供 SDK 内部如Function.args()的响应映射使用开发者不应手动构造实例。所有参数都是可选的下划线前缀的私有字段用于已知值缓存若某字段在构造时已带值对应方法会直接返回该值不再发起查询。各构造参数与文档定义的对应关系如下构造参数类型对应方法含义ctx?Context—GraphQL 查询上下文内部使用_id?FunctionArgIDid()唯一标识符_defaultAddress?stringdefaultAddress()Container 类型参数的默认镜像地址_defaultPath?stringdefaultPath()File/Directory 类型参数的默认路径_defaultValue?JSONdefaultValue()通用默认值_deprecated?stringdeprecated()弃用原因_description?stringdescription()参数的 doc string_name?stringname()参数名lowerCamelCase三、生成代码的懒加载实现机制从源码结构看client.gen.ts 中 FunctionArg 类的完整实现位于 L9113-L9283每个标量方法都遵循统一的缓存优先 按需查询模式。以name()为例/** * The name of the argument in lowerCamelCase format. */ name async (): Promisestring { if (this._name) { return this._name } const ctx this._ctx.select(name) const response: Awaitedstring await ctx.execute() return response }见 client.gen.ts#L9250-L9260其工作机制缓存优先如果私有字段this._name在构造时已赋值例如父级对象拉取该节点时已经带回了这个值方法直接同步命中零网络开销按需查询否则通过this._ctx.select(name)在 GraphQL 查询树上挂载一个name字段选择ctx.execute()执行整个查询后取回结果组合查询因为选择是挂载到上下文查询树上多个方法连续调用最终会被合并进一次或少数几次GraphQL 执行这正是 Dagger 客户端惰性执行、组合查询设计的体现。有两个方法与其他方法略有不同值得注意ignore()没有对应的私有缓存字段每次都通过ctx.select(ignore)查询L9239-L9245typeDef()是同步方法直接返回一个TypeDef对象而非Promise因为它只是构造一个子查询节点真正的字段读取要等TypeDef自身的方法被 await 时才发生L9279-L9282。四、方法逐项详解4.1 id() — 唯一标识符id async (): PromiseFunctionArgID返回该FunctionArg的唯一标识FunctionArgID。在 GraphQL Schema 中FunctionArg实现了Node接口type FunctionArg implements Nodeid: ID!是其全局节点标识可用于跨查询引用定位。4.2 name() — 参数名name async (): Promisestring返回参数的 lowerCamelCase 名称。这是调用方在元数据中识别参数时最常用的字段例如用于生成 CLI 的--name标志或文档中的参数列表。4.3 defaultAddress() — Container 参数的默认地址defaultAddress async (): Promisestring仅适用于Container类型参数当调用方没有为该参数传值时引擎从给定地址加载默认容器例如alpine:latest。这对应模块函数中常见的模式func (m *Module) Hello( base dagger.Container, // 若未传入则回退到默认地址 ) ...Schema 中的声明为defaultAddress: String!非空无默认值时为空字符串见 base_schema.graphqls#L2666。4.4 defaultPath() — File/Directory 参数的默认路径defaultPath async (): Promisestring仅适用于File或Directory类型参数参数未设置时从上下文目录context directory即 SDK 会话绑定的本地工作目录中的给定路径加载。这让模块函数可以声明如果用户没传目录就用仓库里的某个固定路径。4.5 defaultValue() — 通用默认值defaultValue async (): PromiseJSON返回该参数未被调用方显式设置时应使用的默认值可为空。返回类型是JSON——在 SDK 中它是一个 branded string 类型/** * An arbitrary JSON-encoded value. */ export type JSON string { __JSON: never }见 client.gen.ts#L2222-L2224即底层是 JSON 编码字符串类型系统阻止与普通string混用。4.6 ignore() — Directory 参数的忽略模式ignore async (): Promisestring[]仅适用于Directory类型参数返回一组忽略ignore模式会应用到输入目录上匹配的文件/目录在入参时被过滤掉。Schema 文档特别强调这一过滤是以缓存高效cache-efficient的方式完成的——匹配项在内容寻址之前被剔除避免无关文件污染缓存键。4.7 deprecated() 与 description() — 弃用与文档字符串deprecated async (): Promisestring // 该参数被弃用的原因可为空 description async (): Promisestring // 参数的 doc string可为空这两个字段是生成 CLI 帮助、文档站点、IDE 提示的直接数据源。deprecated()非空时工具链应在帮助文本中标注弃用并给出迁移原因。4.8 sourceMap() — 声明位置sourceMap async (): PromiseSourceMap | null返回该参数声明在模块源码中的位置SourceMap可为null例如参数来自未携带源码位置信息的来源。其内部实现先查sourceMap.id判空非空时用ctx.copy().selectNode(response, SourceMap)构造子对象L9265-L9274是可空对象字段的标准生成模式。4.9 typeDef() — 参数类型typeDef (): TypeDef返回参数的类型定义TypeDef。TypeDef是联合接口根据实际类型可解析为标量ScalarTypeDef、枚举EnumTypeDef、对象/接口ObjectTypeDef/InterfaceTypeDef或列表ListTypeDef见同目录下的 ScalarTypeDef.md、ListTypeDef.md 等文档。这是做类型感知代码生成的关键入口先取typeDef()再向下解析具体类别。五、如何获得 FunctionArg 实例Function.args()FunctionArg从不孤立出现——它由Function对象的args()方法批量返回/** * Arguments accepted by the function, if any. */ args async (): PromiseFunctionArg[] { type args { id: ID } const ctx this._ctx.select(args).select(id) const response: Awaitedargs[] await ctx.execute() return response.map( (r) new FunctionArg(ctx.copy().selectNode(r.id, FunctionArg)), ) }见 client.gen.ts#L8901-L8912注意这里的实例化方式args()只先拉取每个参数的id然后用ctx.copy().selectNode(r.id, FunctionArg)为每个 id 构造一个FunctionArg。由于id已作为构造参数传入后续调用functionArg.id()会直接命中缓存其余字段则在你调用时按需挂载查询。这也再次印证了文档构造函数仅内部使用的说法——SDK 内部通过这条路径批量构造对象。一个典型的元编程用法骨架import { dag, Client } from dagger.io/dagger await dag.query(async (client) { const mod client.module(my-module) for (const fn of await mod.functions()) { for (const arg of await fn.args()) { console.log(await arg.name(), await (await arg.typeDef().type()), JSON.stringify(await arg.defaultValue())) } } return null }, { clientOpts: { project: [.] } })六、GraphQL Schema 与多语言 SDK 的一致性TypeScript 客户端是 Dagger 引擎 GraphQL API 的自动生成映射。Schema 中FunctionArg的完整定义base_schema.graphqls#L2661 起与文档字段一一对应type FunctionArg implements Node { Only applies to arguments of type Container. If the argument is not set, load it from the given address (e.g. alpine:latest) defaultAddress: String! Only applies to arguments of type File or Directory. If the argument is not set, load it from the given path in the context directory defaultPath: String! A default value to use for this argument when not explicitly set by the caller, if any. defaultValue: JSON! The reason this function is deprecated, if any. deprecated: String A doc string for the argument, if any. description: String! A unique identifier for this FunctionArg. id: ID! Only applies to arguments of type Directory. The ignore patterns are applied to the input directory, and matching entries are filtered out, in a cache-efficient manner. ignore: [String!]! The name of the argument in lowerCamelCase format. name: String! The location of this arg declaration. sourceMap: SourceMap The type of the argument. typeDef: TypeDef! }值得注意的是可空性的差异Schema 中defaultAddress、defaultPath、defaultValue、name、ignore、typeDef均为非空!而deprecated、description、sourceMap可为空——这与 TypeScript 侧方法返回值的语义一致前者在未设置时返回空值而非报错。Go SDK 中存在完全同构的FunctionArg结构例如模块生成的 dagger.gen.gotype FunctionArg struct { query *querybuilder.Selection defaultAddress *string defaultPath *string defaultValue *JSON deprecated *string description *string id *FunctionArgID name *string } // Only applies to arguments of type Container. If the argument is not set, load it from the given address (e.g. alpine:latest) func (r *FunctionArg) DefaultAddress(ctx context.Context) (string, error) { if r.defaultAddress ! nil { return *r.defaultAddress, nil } q : r.query.Select(defaultAddress) ... }同样采用指针缓存 查询构建器Select的惰性模式说明FunctionArg的字段语义在多语言 SDK 间是统一由代码生成器从同一 Schema 派生的。七、小结与使用注意FunctionArg描述定义时的参数规格调用时实际传值对应的是FunctionCallArgValue不要混用实例只能从Function.args()等 SDK 内部路径获得构造函数为内部保留defaultAddress()只针对Container参数、defaultPath()只针对File/Directory参数、ignore()只针对Directory参数调用前先通过typeDef()确认参数类型所有方法都是惰性的字段读取发生在await时多个方法的选择会被合并进同一 GraphQL 查询因此遍历参数元数据时的实际开销远低于每方法一查询的直觉估计本文适用前提是 version-0.20 参考文档对应的 SDK 快照字段清单以 FunctionArg.md 及 client.gen.ts 实际内容为准其他版本如 version-0.21 下的对应路径字段可能随 Schema 演进而变化。【免费下载链接】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),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。