拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Dagger TypeScript 客户端 SourceMap 类详解:模块源码位置信息的创建与读取

Dagger TypeScript 客户端 SourceMap 类详解模块源码位置信息的创建与读取【免费下载链接】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导读SourceMap是 Dagger 引擎为模块系统设计的源码位置信息对象用于记录 Dagger 模块中函数、参数、对象、字段、接口、枚举等类型声明在源代码中的精确位置文件、行号、列号并支持携带可跳转到浏览器源码页面的 URL。本文以 TypeScript SDK 中生成的 SourceMap 类 文档为骨架结合 Dagger 仓库的 Go 核心实现与 TypeScript SDK 运行时源码完整讲解SourceMap的字段语义、dag.sourceMap()创建入口、id()唯一标识、各访问器方法以及它在模块类型定义元数据中的应用链路帮助你理解并实际使用这一 API。SourceMap 是什么模块声明位置的第一手元数据在 Dagger 的模块体系中用户编写的模块Go、TypeScript、Python 等会被动态加载并暴露为 GraphQL API。为了支持 IDE 跳转、错误定位、工具链生成和模块自省引擎需要知道这段类型定义来自哪个源文件的哪一行。SourceMap就是承载这一信息的核心数据类型。其定义位于 core/typedef.go结构体字段与文档描述一一对应type SourceMap struct { Module string field:true doc:The module dependency this was declared in. Filename string field:true doc:The filename from the module source. Line int field:true doc:The line number within the filename. Column int field:true doc:The column number within the line. URL string field:true doc:The URL to the file, if any. This can be used to link to the source map in the browser. }TypeScript 端的类同样由代码生成器产出位于 sdk/typescript/src/api/client.gen.ts类注释为 Source location information.源码位置信息与文档头部的描述一致。该类继承自BaseClient是 Dagger 客户端 SDK 中以查询选择器selector方式构建 GraphQL 调用的典型对象每个方法并不立即发起请求而是先在内部上下文_ctx上记录一次字段选择真正执行时才一次性提交查询。构造与创建入口不要直接 new用 dag.sourceMap()构造器签名与内部缓存字段根据文档SourceMap的构造器签名为new SourceMap(ctx?, _id?, _column?, _filename?, _line?, _module?, _url?)其中ctx为Context其余参数为可选的缓存字段SourceMapID、number、string等。生成代码中这些私有字段用于短路返回例如id()方法在_id已存在时直接返回避免重复查询见 client.gen.tscolumn()、filename()、line()、module_()、url()同理。文档明确提示Constructor is used for internal usage only, do not create object from it.构造函数仅供内部使用请勿直接创建对象。正确做法是调用客户端根对象上的工厂方法dag.sourceMap()它才是面向 SDK 使用者的公开入口。dag.sourceMap() 工厂方法在 client.gen.ts 中可以看到其签名与实现/** * Creates source map metadata. * param filename The filename from the module source. * param line The line number within the filename. * param column The column number within the line. */ sourceMap (filename: string, line: number, column: number): SourceMap { const ctx this._ctx.select(sourceMap, { filename, line, column }) return new SourceMap(ctx) }它接受三个必填参数——filename模块源文件名、line文件内行号、column行内列号——在查询上下文中记录一次sourceMap字段选择并返回一个新的SourceMap对象。注意module与url在此处未作为公开参数暴露它们由内部调用注入。底层 GraphQL 字段定义在 core/schema/module.go 中实现了对应的 GraphQL 解析器可以看到module与url均被标记为internal:truefunc (s *moduleSchema) sourceMap(ctx context.Context, _ *core.Query, args struct { Module dagql.Optional[dagql.String] internal:true Filename string Line int Column int URL dagql.Optional[dagql.String] internal:true }) (*core.SourceMap, error) { // 将 args.Module / args.URL 的 Valid 值转换为 string空则保持 return core.SourceMap{ Module: module, Filename: args.Filename, Line: args.Line, Column: args.Column, URL: url, }, nil }即在 GraphQL schema 中sourceMap字段的完整签名为见 base_schema.graphqlssourceMap(filename: String!, line: Int!, column: Int!, module: String, url: String): SourceMap!。作为模块开发者你只需要提供前三个必填参数。六个核心方法逐个掌握字段读取SourceMap暴露了 6 个方法全部返回Promise与 GraphQL 的异步执行模型一致。以下为每个方法的语义、返回类型与底层实现要点。id()获取唯一标识签名id(): PromiseSourceMapID语义该SourceMap的唯一标识符。说明SourceMapID是专为SourceMap生成的 GraphQL 标量类型SourceMap类型实现了Node接口见 base_schema.graphqls因此可以被持久化、跨查询引用。引擎侧通过PersistedObject机制对SourceMap进行编解码core/typedef.go字段以 JSON 形式持久化module、filename、line、column、url生成代码中id()在_id已缓存时直接返回否则执行select(id)查询。filename()模块源文件名签名filename(): Promisestring语义模块源码中的文件名The filename from the module source.。line()文件内行号签名line(): Promisenumber语义文件名内部的行号The line number within the filename.。column()行内列号签名column(): Promisenumber语义行内的列号The column number within the line.。行号与列号通常从 1 开始计数与主流编辑器和编译器一致可直接用于 IDE 跳转。module_()所属模块依赖签名module_(): Promisestring语义该声明所在的模块依赖The module dependency this was declared in.。说明TypeScript 中module是保留关键字因此生成代码将方法名改写为module_()对应的 GraphQL 字段仍为module见 client.gen.ts 中this._ctx.select(module)。该字段在模块自省introspection与依赖分析场景下非常有用当某个类型来自被引用的第三方模块依赖时通过它即可追溯到声明来源。url()可点击的源码链接签名url(): Promisestring语义指向该文件的 URL如果有可用于在浏览器中链接到源码位置The URL to the file, if any. This can be used to link to the source map in the browser.。说明这是文档中唯一明确提到浏览器用途的字段——引擎可以为远程模块生成指向源码托管页面的 URL从而在 Web 界面如 Dagger 引擎的调试 UI中实现点击跳转到源码行的能力。该字段通常与module一样由内部机制填充普通创建路径下为空字符串。源码级原理SourceMap 如何挂接到类型定义上理解SourceMap不能只停留在能读哪些字段还要明白它在整个模块元数据体系中的位置——它是几乎所有类型定义TypeDef的位置注解。通过 withSourceMap 系列方法附着在 GraphQL schema 中SourceMap被以参数形式注入到各类 TypeDef 的构建方法中见 core/schema/module.go 与 base_schema.graphqlswithSourceMap(sourceMap: ID!): Function_—— 函数定义function__withSourceMap—— 函数参数argument、对象object、接口interface、字段field、枚举enum、枚举成员enum member / enum value在引擎核心数据结构中Function、FunctionArg、ObjectTypeDef、FieldTypeDef、InterfaceTypeDef、EnumTypeDef、EnumMemberTypeDef均声明了SourceMap字段例如// core/typedef.go SourceMap dagql.Nullable[dagql.ObjectResult[*SourceMap]] field:true doc:The location of this function declaration.对应的WithSourceMap方法如 core/typedef.go 的Function.WithSourceMap将传入的SourceMap对象挂载到类型定义上并参与持久化编码每个 TypeDef 的持久化 payload 中都包含SourceMapResultID见 core/typedef.go 等。生成 sourceMap 指令当模块的类型定义被序列化为 GraphQL schema 时SourceMap还会被转换为sourceMap指令。TypeDirective()方法core/typedef.go按非空字段生成指令参数directive : ast.Directive{Name: sourceMap, Arguments: ast.ArgumentList{}} // module / filename / line / column / url 按非空条件追加为字符串或整型参数schema 侧对应指令定义见 base_schema.graphqlsdirective sourceMap(module: String!, filename: String!, line: Int!, column: Int!, url: String!) on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT这意味着最终暴露的 GraphQL schema 中每个带源码位置的类型/字段/枚举值都会携带sourceMap指令下游工具IDE 插件、代码生成器、文档站点可以直接从 schema 中读取位置信息而无需额外的查找请求。TypeScript 模块运行时如何自动填充在 TypeScript SDK 的模块运行时中注册函数、参数、对象、字段、枚举及枚举值时都会自动附带sourceMap。核心逻辑在 sdk/typescript/src/module/entrypoint/register.tsfunction addSourceMap(object: Locatable): SourceMap { const { filepath, line, column } object.getLocation() return dag.sourceMap(filepath, line, column) }每个可定位Locatable的对象都实现了getLocation()返回其声明处的filepath、line、column随后通过dag.sourceMap(...)创建SourceMap并随 TypeDef 一起注册例如函数注册路径中fct通过.withSourceMap(addSourceMap(fct))附着见 register.ts。这意味着 TypeScript 模块开发者无需手动调用sourceMap()——当你编写模块并用func等装饰器声明函数时SDK 已经自动把你代码的位置信息作为元数据注册到引擎中供自省与调试使用。实际使用场景与查询示例场景一模块自省与调试在 Dagger 中可通过 GraphQL 查询遍历模块的类型定义并读取其SourceMap例如query { currentModule { functions { name sourceMap { filename line column module url } } } }从源码结构可以推断该查询将返回每个函数声明的源码位置在排查这个函数到底定义在哪个模块文件的哪一行时非常直接也是引擎 UI、诊断工具实现源码跳转的数据基础。场景二定位来自依赖模块的声明module_()字段用于标识声明所属的模块依赖。当你在自己的模块中使用来自github.com/foo/bar依赖提供的类型时通过读取该类型的SourceMap.module即可区分本模块声明与依赖声明从而在文档生成、依赖图分析中准确归因。场景三为自定义工具提供位置信息如果你正在构建基于 Dagger 模块元数据的工具如自省 CLI、自定义文档生成器、LSP 服务可以遍历TypeDef树并读取每个节点的sourceMap字段将其与模块的sourceDirectory结合把 GraphQL 类型定义映射回源码中的具体位置进而实现类型 → 源码的逆向导航。常见注意事项不要直接 newSourceMap的构造函数仅供 SDK 内部使用公开入口是dag.sourceMap(filename, line, column)作为模块作者通常连它都不需要手动调用TypeScript 运行时已自动注入。方法返回 Promise所有读取方法均为异步async调用时需await生成代码中的_column、_filename等私有字段只是缓存不代表调用是同步的。line/column 语义行号与列号按源码位置原样记录不经过 0/1 索引转换与编译器/编辑器约定一致。module_与url的填充时机这两个字段在公开的dag.sourceMap()签名中不可直接传入由引擎内部如模块加载、远程源码解析流程填充未填充时对应字段返回空字符串属预期行为。版本对应本文描述的 API 与 Dagger v0.20 的 TypeScript SDK 生成代码对应其他版本可能略有差异以你实际使用版本的 api/client.gen.ts 与 core/typedef.go 为准。参考资料类型文档SourceMap 类参考核心实现core/typedef.go 中 SourceMap 结构体与持久化GraphQL 注册与解析core/schema/module.go 中 sourceMap 与 withSourceMap 系列Schema 指令与类型定义core/schema/testdata/base_schema.graphqlsTypeScript SDK 生成代码sdk/typescript/src/api/client.gen.ts 中 SourceMap 类TypeScript 模块运行时自动注入sdk/typescript/src/module/entrypoint/register.ts 中 addSourceMap【免费下载链接】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),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门