ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Dagger TypeScript SDK 中的 CurrentModuleID:模块运行时标识符的类型体系与使用解析

2026/9/15 19:04:46 拓冰建站 浏览量
Dagger TypeScript SDK 中的 CurrentModuleID:模块运行时标识符的类型体系与使用解析 Dagger TypeScript SDK 中的 CurrentModuleID模块运行时标识符的类型体系与使用解析【免费下载链接】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 v0.19 TypeScript SDK 自动生成的 API 参考文档中CurrentModuleID类型别名为核心解析这一不透明 ID 标量的类型定义、结构化标记字段的编译期含义以及它如何在CurrentModule反射式模块 API 与loadCurrentModuleFromID之间流转。读完本文你将掌握CurrentModuleID的完整类型结构、它在 SDK 与核心引擎中的实现链路以及在 Dagger 模块函数运行时正确获取与消费该 ID 的实战方法。什么是 CurrentModuleID在 CurrentModuleID 类型别名文档 中该类型的定义如下type CurrentModuleID string object文档给出的语义说明只有一句话TheCurrentModuleIDscalar type represents an identifier for an object of type CurrentModule.翻译过来即CurrentModuleID是一个标量类型scalar type用于表示类型为CurrentModule的对象的标识符。也就是说任何 Dagger 模块在运行时都可以通过它拿到当前正在被执行的模块这一实例的唯一句柄供后续跨调用、跨进程传递与还原。它隶属于dagger.io/dagger包中 api/client.gen 这一自动生成客户端模块client.gen前缀代表该文件由代码生成器产出。在该模块的 Type Aliases 清单里CurrentModuleID与ModuleID、ContainerID、DirectoryID等数十个 ID 类型并列共同构成 Dagger 面向对象 API 的标识符层。类型声明结构解析文档在Type Declaration一节中给出了该类型唯一的结构化成员interface CurrentModuleID { __CurrentModuleID: never }结合类型别名本体string object可以读出两层含义运行时层面CurrentModuleID的底层值就是一个普通字符串因此它可以像字符串一样被序列化、写入环境变量、作为函数参数在 GraphQL 查询中传输编译期层面通过与{ __CurrentModuleID: never }取交叉类型TypeScript 在类型系统层面为这个字符串打上烙印branding使其无法被赋给其他同样是string的类型如ModuleID、ContainerID从而在编译期就阻止了不同 ID 之间的混用。这一字符串 标记字段的建模方式并非CurrentModuleID独有而是 Dagger TypeScript SDK 生成代码中所有 ID 类型的统一模式。在 sdk/typescript/src/api/client.gen.ts 中可以找到最基础的ID类型定义/** * A unique identifier for an object. */ export type ID string { __ID: never }CurrentModuleID正是这一模式的实例化每种对象类型都拥有一个以自身命名、带独有标记字段的 ID 别名。从源码结构看这种做法既保证了 ID 在运行时与字符串完全兼容又让类型系统能够精确区分谁的 ID。CurrentModule 与 CurrentModuleID 的关系CurrentModuleID的载体是CurrentModule类。根据 CurrentModule 类文档其定位是Reflective module API provided to functions at runtime.即在函数运行时提供给 Dagger 函数的反射式模块 API。它是模块函数自省自身模块名、依赖、源码目录、工作目录、生成代码等的入口其构造器签名如下new CurrentModule(ctx?: Context, _id?: CurrentModuleID, _name?: string)文档明确说明构造器仅用于内部使用请勿直接创建对象Constructor is used for internal usage only, do not create object from it。也就是说开发者不应该也无法安全地手动new一个CurrentModule而应通过下文所述的查询入口获取。CurrentModuleID与CurrentModule的双向关系体现在产出方向CurrentModule.id()方法返回PromiseCurrentModuleID即当前模块的唯一标识符消费方向Client.loadCurrentModuleFromID(id: CurrentModuleID)接收一个CurrentModuleID并还原出对应的CurrentModule对象。id() 的 SDK 实现在 sdk/typescript/src/api/client.gen.ts 中CurrentModule类的id()实现体现了 Dagger ID 的惰性求值模式export class CurrentModule extends BaseClient { private readonly _id?: ID undefined id async (): PromiseID { if (this._id) { return this._id } const ctx this._ctx.select(id) const response: AwaitedID await ctx.execute() return response } }从实现可以看出如果对象创建时已携带 ID例如通过loadCurrentModuleFromID还原而来id()会直接返回缓存值而不再发起查询否则才向 Dagger 引擎发送select(id)的 GraphQL 查询获取。这是 Dagger 所有 ID 类型共有的先缓存、后查询设计。ID 的产生与消费两个关键查询入口CurrentModuleID只在两条 API 路径中流转均定义在Client类中见 Client 类文档。产生client.currentModule()currentModule(): CurrentModule从 client.gen.ts 的实现看该方法将查询选择器指向 GraphQL 的currentModule字段其文档注释为 The module currently being served in the session, if any即当前会话中正在被服务的模块如果存在。调用dag.currentModule()后配合.id()即可获得当前模块的CurrentModuleID。消费client.loadCurrentModuleFromID()loadCurrentModuleFromID(id: CurrentModuleID): CurrentModule文档描述为 Load a CurrentModule from its ID从 ID 加载一个 CurrentModule。这是将序列化后的 ID 字符串还原为可继续链式调用的对象的标准入口——典型场景是把 ID 作为参数传入另一个模块函数或另一个进程在那里重新加载出CurrentModule。底层实现链路从 TypeScript 到 Go 再到核心 Schema为了理解CurrentModuleID在引擎侧的真实形态可以顺着生成代码逐层下探。Go SDK 侧在 sdk/typescript/runtime/internal/dagger/dagger.gen.go 中同名的 ID 被建模为命名类型type CurrentModuleID stringGo 语言用命名类型named type实现字符串隔离而 TypeScript 用交叉类型 never标记字段——两种语言采用不同的机制表达同一概念ID 是不透明的字符串。同文件中还可见对应的加载函数// Load a CurrentModule from its ID. func (r *Query) LoadCurrentModuleFromID(id CurrentModuleID) *CurrentModule以及Query.CurrentModule()与Env.WithCurrentModule()对应 SDK 的withCurrentModule方法共同构成 ID 的产生与消费闭环。核心引擎侧Dagger 的核心 GraphQL Schema 在 core/schema/module.go 中注册了CurrentModule的全部字段dependencies、generatedContextDirectory、name、source、workdir、workdirFile、generators其中id字段由 dagql 框架自动提供。在 core/schema/module.go 中可以看到引擎内部通过parent.Self().CurrentModule(ctx)获取当前模块并将其 ID 注入到请求参数implementationScopedMod中——这解释了为什么模块函数执行期间能感知自己所在的模块。会话上下文CurrentModule的获取依赖当前会话正在服务的模块这一上下文因此currentModule()只在模块函数执行期间有意义在引擎侧core/schema/cache.go 中调用parent.Self().CurrentModule(ctx)后还会检查core.ErrNoCurrentModule错误表明当不存在当前模块上下文时会显式报错而非静默返回空值。实战在模块函数中获取并使用模块 ID下面是一个基于 SDK 公开 API 的典型使用模式展示了如何在 TypeScript 模块函数中获取CurrentModuleID并读取模块名称import { dag } from dagger.io/dagger // 1. 获取当前会话中的 CurrentModule const currentModule dag.currentModule() // 2. 获取模块的 CurrentModuleID const moduleId: CurrentModuleID await currentModule.id() // 3. 利用模块 API 自省模块名、源码目录、工作目录 const moduleName await currentModule.name() const source currentModule.source() // Directory const workdir currentModule.workdir(.) // Directory含执行期间改动这种模式在 Dagger SDK 自身的运行时中就有真实应用在 sdk/typescript/src/module/entrypoint/entrypoint.ts 中模块入口函数正是通过dag.currentModule().name()拿到正在执行的模块名再配合dag.currentFunctionCall()的父级名称来判断当前调用是注册还是调用export async function entrypoint(files: string[]) { await connection(async () { const fnCall dag.currentFunctionCall() const moduleName await dag.currentModule().name() const scanResult await scan(files, moduleName) const parentName await fnCall.parentName() // ... }) }此外官方文档的 Go SDK 参考 与 Java SDK 参考 也展示了各语言 SDK 中通过dag.CurrentModule()/dag().currentModule().source()触达模块自身源码与工作目录的同类用法如 Dagger 自带的ruff模块。使用注意事项结合文档与源码使用CurrentModuleID时有几点需要留意不要手动构造CurrentModule的构造器是内部用途CurrentModuleID是引擎产出的不透明标识应通过dag.currentModule().id()获取再通过dag.loadCurrentModuleFromID(id)还原不要在客户端自行拼装字符串上下文限定currentModule()返回的是当前会话中正在被服务的模块仅在模块函数执行期间可用脱离模块调用上下文会触发引擎侧的ErrNoCurrentModule错误见 core/schema/cache.go唯一性语义文档对id()的描述是 A unique identifier for this CurrentModule该 CurrentModule 的唯一标识符它保证的是对象身份的唯一映射适合作为对象引用在调用间传递但不应对其字符串格式、长度或跨会话持久性做任何假设——它是不透明的类型即文档string { __CurrentModuleID: never }的标记字段在运行时不存在never类型不会产生任何值它的全部作用发生在编译期用于防止不同 ID 类型之间相互赋值这一点可从 client.gen.ts 的ID基础定义得到印证。综上CurrentModuleID是 Dagger TypeScript SDK 中模块运行时标识符这一通用机制的一个具体实例它用最小的类型定义字符串 编译期标记支撑起模块函数对自身模块的自省与跨调用传递能力是理解 Dagger 面向对象 API 中 ID 标量体系的上佳切入点。【免费下载链接】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),仅供参考