Dagger TypeScript SDK 的 DirectoryEntriesOpts 详解:Directory.entries() 目录列举选项
【免费下载链接】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
导读
DirectoryEntriesOpts是 Dagger TypeScript SDK 中用于Directory.entries()方法的选项对象,它通过可选的path参数指定"要列举哪个子目录",从而返回该目录下的文件和子目录名称列表。本文以 Dagger v0.21 TypeScript SDK 官方 API 参考文档(DirectoryEntriesOpts.md)为主线,结合 SDK 生成源码与引擎核心实现,完整讲解该选项的类型定义、调用方式、底层执行原理、路径语义与常见实战场景。
类型定义:只有一个可选属性的轻量选项
在 Dagger v0.21 TypeScript SDK 中,DirectoryEntriesOpts是一个仅包含一个可选属性的对象类型:
export type DirectoryEntriesOpts = { /** * Location of the directory to look at (e.g., "/src"). */ path?: string }该定义位于 sdk/typescript/src/api/client.gen.ts,由 Dagger 代码生成器根据引擎的 GraphQL schema 自动生成(client.gen.ts即为 SDK 的客户端生成产物)。其语义要点如下:
| 属性 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
path | string | 可选 | 要列举的目录位置,例如"/src"。省略时默认列举Directory根目录本身的内容 |
从类型结构看,该选项没有任何必填字段,这决定了entries()既可以"裸调"(列举根目录),也可以传入{ path: "/src" }深入任意子目录。在 TypeScript 的使用中,二者写法分别为:
// 列举目录根 const rootEntries = await dir.entries() // 列举 /src 子目录 const srcEntries = await dir.entries({ path: "/src" })消费方:Directory.entries() 方法签名与调用链
DirectoryEntriesOpts的唯一消费方是Directory类上的entries()异步方法。SDK 生成源码中的完整实现如下(sdk/typescript/src/api/client.gen.ts):
/** * Returns a list of files and directories at the given path. * @param opts.path Location of the directory to look at (e.g., "/src"). */ entries = async (opts?: DirectoryEntriesOpts): Promise<string[]> => { const ctx = this._ctx.select("entries", { ...opts }) const response: Awaited<string[]> = await ctx.execute() return response }方法签名的几个关键点:
- 返回类型为
Promise<string[]>:返回的是路径条目名称的字符串数组,而非File/Directory对象,因此它天然适合做"探测性"检查(如判断目录是否为空、列出某次构建产物清单); select("entries", { ...opts }):opts会被展开为 GraphQL 字段参数传给名为entries的引擎 API,构成一次惰性求值的查询节点,直到ctx.execute()时才真正下发执行;- 参数全部可选:
opts?: DirectoryEntriesOpts说明不传任何参数是合法的,此时查询不携带path参数,等价于列举Directory根目录。
值得注意的是,其他 SDK 同样存在该选项的等价物。例如 Go SDK 生成的类型定义(sdk/typescript/runtime/internal/dagger/dagger.gen.go)将path建模为DirectoryEntriesOpts.Path string,并在Entries(ctx, opts ...DirectoryEntriesOpts)中通过querybuilder.IsZeroValue判断path是否为空,仅在非空时才附加q.Arg("path", ...)参数——这与 TypeScript 侧{ ...opts }展开后引擎按缺省处理的语义完全一致。
引擎侧实现:entries 查询如何真正列出目录
entries查询最终由引擎的目录 schema 处理器承接。核心入口在 core/schema/directory.go(以dagql.NodeFunc("entries", s.entries)注册,并带有View(AllVersion)版本视图声明),参数结构定义为:
type entriesArgs struct { Path dagql.Optional[dagql.String] }处理器将参数透传给目录实体的Entries方法(core/schema/directory.go),最终由 core/directory.go 中的核心实现完成实际工作,其执行流程可概括为:
- 解析快照与目录路径:通过
dir.Snapshot.GetOrEval与dir.Dir.GetOrEval惰性求值出目录的内容快照与当前目录前缀; - 拼接目标路径:
src = path.Join(dirPath, src),将引擎内部的目录前缀与用户传入的path参数拼接,得到要列举的最终路径; - 只读挂载并读取:通过
MountRef(ctx, snapshot, ..., mountRefAsReadOnly)以只读方式挂载快照,再以containerdfs.RootPath(root, src)解析真实路径,最终调用os.ReadDir(resolvedDir)读取目录项; - 格式化输出:遍历每个目录项,把
entry.Name()追加到结果切片。从 core/directory.go 可以看到一个与版本相关的行为细节:
for _, entry := range entries { path := entry.Name() if useSlash && entry.IsDir() { path += "/" } paths = append(paths, path) }即子目录名称会以尾部斜杠/结尾(如"src/"),而普通文件不带斜杠。这一行为由SupportsDirSlash控制(core/directory.go),其实现为Supports(ctx, "v0.17.0"),意味着该斜杠后缀语义自引擎版本 v0.17.0 起生效——这对旧版本 SDK 的兼容性判断具有直接意义,在解析返回结果时(例如以endsWith("/")区分目录与文件)需结合运行引擎的版本谨慎处理。
此外,针对空目录(llb.Scratch()产生的空快照)引擎也有专门处理分支(core/directory.go 附近的errEmptyResultRef判断),保证空目录返回空数组而非报错。
path 参数的语义与最佳实践
path参数采用与 Dagger 其他目录类 API(如glob()、file()、directory())一致的绝对路径风格(相对Directory自身根目录),文档示例"/src"即表示"当前 Directory 的 src 子目录"。需要明确:
- 不以引擎宿主机的文件系统为基准:
path是相对该Directory抽象(可能来自host.directory()、容器内的目录、远程模块输出等)的路径,与宿主机路径无关; - 默认值语义:省略
path时,GraphQL 请求不携带该参数,引擎以目录根作为列举目标; - 与
glob()的区别:entries()只返回直接子项的名称列表(不递归、不支持通配符),而glob(pattern)支持递归与 glob 匹配;需要递归列举时应组合使用glob("**/*")或对子目录递归调用entries()。
实战示例:在 CI 流水线中列举构建产物
下面以 TypeScript SDK 在 Dagger 模块/CI 中的典型用法展示完整场景——列出容器内/output目录的产物清单并区分文件与子目录:
import { dag, Container, Directory } from "@dagger.io/dagger" async function listArtifacts(container: Container): Promise<string[]> { // 取出 /output 目录(也可以直接对 Directory 调用) const output: Directory = container.directory("/output") // 列举根目录 const rootItems: string[] = await output.entries() console.log("root:", rootItems) // 深入子目录列举 const nested: string[] = await output.entries({ path: "/dist" }) console.log("dist:", nested) // 区分目录与文件(依赖 v0.17.0+ 引擎的斜杠后缀行为) const dirs = rootItems.filter((name) => name.endsWith("/")) const files = rootItems.filter((name) => !name.endsWith("/")) return [...dirs, ...files] }配套能力
- 判断条目是否存在/类型:
Directory.exists(path, opts)及其DirectoryExistsOpts(支持expectedType与doNotFollowSymlinks,见 sdk/typescript/src/api/client.gen.ts)可与entries()配合做更精细的探测; - 获取文件内容:对列举出的文件名,可进一步调用
dir.file(name)得到File并读取内容; - 递归收集全部路径:
await dir.glob("**/*")可获取递归展开的完整路径列表。
版本适用性说明
本文所述 API 基于 Dagger v0.21 版本的 TypeScript SDK 文档(docs/versioned_docs/version-0.21/)。需要说明的版本相关前提:
entries查询在不同版本下返回结果存在差异(源码中以View(AllVersion)标注,见 core/schema/directory.go);- 子目录条目带尾部斜杠
/的行为自引擎 v0.17.0 起生效(见 core/directory.go 的SupportsDirSlash实现); - 实际使用时应以所绑定引擎/CLI 的版本为准,避免在旧引擎上依赖新语义。
小结
DirectoryEntriesOpts虽然只有一个path属性,却是 Dagger TypeScript SDK 中目录列举能力的关键入口参数:它决定了entries()列举目录根还是指定子目录,其可选性带来了"根目录默认值 + 子目录覆盖"的灵活调用模型。结合 DirectoryEntriesOpts.md、SDK 生成源码(sdk/typescript/src/api/client.gen.ts)与引擎实现(core/directory.go)三者对照,开发者可以准确预测 API 行为、正确处理版本差异,并将目录列举能力高效集成到自己的构建、测试与发布流水线中。
【免费下载链接】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),仅供参考