ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

TypeGraphQL 输出 Schema SDL 文件全指南:从 `emitSchemaFile` 到程序化导出与自定义指令

TypeGraphQL 输出 Schema SDL 文件全指南:从 `emitSchemaFile` 到程序化导出与自定义指令 后端GraphQLAPI设计【免费下载链接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!项目地址https://gitcode.com/gh_mirrors/ty/type-graphql点击查看免费下载导读TypeGraphQL 的核心特性是只用 TypeScript 类与装饰器即可构建 GraphQL Schema但生产项目中往往还需要把 Schema 以 SDLSchema Definition Language形式打印成schema.graphql文件供前端代码生成、Schema 快照回归检测、团队阅读 API 等场景使用。本文以 TypeGraphQL 官方文档《Emitting the schema SDL》为主体结合当前仓库源码与测试系统讲解buildSchema的emitSchemaFile选项、emitSchemaDefinitionFile/emitSchemaDefinitionFileSync两个导出函数以及自定义指令缺失时的解决方案帮助读者按需把内存中的 GraphQLSchema 稳定地输出为磁盘文件。为什么需要把 Schema 打印成 SDL 文件TypeGraphQL 通过装饰器收集元数据并程序化地构建 SchemaSchema 本身是内存中的GraphQLSchema对象而不是手写的 SDL 文本。但很多场景要求一份看得见、可复用的 SDL 文件客户端工具链GraphQL 生态中大量工具需要 SDL 文件来做客户端查询的自动补全与校验例如 codegen、lint 等工具基于 SDL 生成类型与校验规则Schema 快照回归检测把每次生成的 SDL 与快照对比可以在测试中自动发现 Schema 的意外变更breaking change团队阅读与探索 API相比阅读基于装饰器、分散在多个类文件中的 TypeGraphQL 代码直接阅读 SDL 文件更直观也避免了反复在 GraphiQL / GraphQL Playground 中交互式探索。为此TypeGraphQL 提供了两种输出 Schema 定义文件的方式构建时自动输出emitSchemaFile选项与程序化主动输出emitSchemaDefinitionFile系列函数。方式一构建 Schema 时自动输出 SDL 文件最简单的方式是在调用buildSchema时传入emitSchemaFile选项。它支持三种取值形态对应BuildSchemaOptions中的emitSchemaFile?: string | boolean | EmitSchemaFileOptions见 src/utils/buildSchema.tsconst schema await buildSchema({ resolvers: [ExampleResolver], // ① 自动在当前工作目录生成 schema.graphql 文件 emitSchemaFile: true, // ② 指定输出路径含文件名目录不存在时会被自动创建 emitSchemaFile: path.resolve(__dirname, __snapshots__/schema/schema.graphql), // ③ 传入配置对象精细控制输出格式 emitSchemaFile: { path: __dirname /schema.graphql, sortedSchema: false, // 默认会按字母顺序排序输出 }, });三种取值形态的语义取值输出位置说明trueprocess.cwd()/schema.graphql在项目当前工作目录生成默认文件名的 SDL字符串该字符串作为完整文件路径可精确控制输出到任意目录、任意文件名配置对象path字段指定的路径path缺省时回退到process.cwd()/schema.graphql其余字段控制打印格式注意一个版本差异本文对应的早期文档website/versioned_docs/version-0.17.1/emit-schema.md写作时默认文件名为schema.gql而当前仓库实现中默认路径为path.resolve(process.cwd(), schema.graphql)见 src/utils/buildSchema.ts官方示例仓库也统一输出为schema.graphql。若沿用旧版文档写法请留意版本间的文件名差异。buildSchema内部如何处理emitSchemaFile在 src/utils/buildSchema.ts 中buildSchema先调用SchemaGenerator.generateFromMetadata生成内存 Schema随后若options.emitSchemaFile为真值则通过getEmitSchemaDefinitionFileOptions解析出目标文件名与打印选项最终调用emitSchemaDefinitionFile写出文件当emitSchemaFile为字符串时直接把它当作完整文件路径当emitSchemaFile为对象时取path缺省回退到process.cwd()/schema.graphql并把{ sortedSchema: true }默认值与对象其余字段合并作为打印选项buildSchemaSync同步版本则调用emitSchemaDefinitionFileSync走同一套逻辑src/utils/buildSchema.ts。方式二程序化调用导出函数如果不想把导出逻辑绑定在buildSchema上例如 Schema 由第三方工具构建、或需要挂在文件监听器/测试脚本里可以使用 TypeGraphQL 导出的emitSchemaDefinitionFile与emitSchemaDefinitionFileSync均从type-graphql顶层导出见 src/utils/index.ts。两者签名一致仅同步/异步不同import { emitSchemaDefinitionFile } from type-graphql; // ... hypotheticalFileWatcher.watch(./src/**/*.{resolver,type,input,arg}.ts, async () { const schema getSchemaNotFromBuildSchemaFunction(); await emitSchemaDefinitionFile(/path/to/folder/schema.graphql, schema); });典型应用场景包括测试脚本快照校验每次生成 SDL 与既有快照对比捕获 Schema 意外变化本地开发文件监听如上例监听resolver/type/input/arg等源码文件变更自动重新生成 SDL配合 codegen 类工具实现前端类型实时同步非buildSchema来源的 Schema例如 examples/apollo-federation/index.ts 中Apollo Gateway 组合子图后得到gateway.schema再调用emitSchemaDefinitionFile输出联邦 Schema// Create schema.graphql file with schema definition in current directory await emitSchemaDefinitionFile(path.resolve(__dirname, schema.graphql), gateway.schema!);函数签名与PrintSchemaOptions在 src/utils/emitSchemaDefinitionFile.ts 中定义了PrintSchemaOptionsexport interface PrintSchemaOptions { sortedSchema: boolean; } export const defaultPrintSchemaOptions: PrintSchemaOptions { sortedSchema: true, };两个导出函数的签名src/utils/emitSchemaDefinitionFile.ts为emitSchemaDefinitionFileSync(schemaFilePath, schema, options defaultPrintSchemaOptions) emitSchemaDefinitionFile(schemaFilePath, schema, options defaultPrintSchemaOptions)schemaFilePath目标文件完整路径schemaGraphQLSchema实例options.sortedSchema默认true表示输出前先调用graphql的lexicographicSortSchema按字典序排序保证同一 Schema 每次生成的 SDL 文本顺序稳定设为false则按类型/字段的声明顺序输出。输出文件的实际内容警告头与自动建目录导出的文件并非裸 SDL其内容由 src/utils/emitSchemaDefinitionFile.ts 中的getSchemaFileContent拼接而成# ----------------------------------------------- # !!! THIS FILE WAS GENERATED BY TYPE-GRAPHQL !!! # !!! DO NOT MODIFY THIS FILE BY YOURSELF !!! # ----------------------------------------------- type Query { ... }即生成告警注释块 printSchema的结果。告警头用于提醒团队成员该文件是产物而非手写源码避免被直接修改后与代码元数据脱节。另外输出函数内部使用 src/helpers/filesystem.ts 的outputFile/outputFileSync工具写入时若目录不存在ENOENT会自动递归创建目录后再写文件。因此emitSchemaFile: path.resolve(__dirname, __snapshots__/schema/schema.graphql)这类深层路径无需预先建目录即可一次成功仅当遇到非ENOENT的未知错误如权限问题时才会抛出异常。测试验证排序、告警头与错误路径仓库在 tests/functional/emit-schema-sdl.ts 中对该功能做了完整的行为验证可直接作为理解实现语义的依据内容与告警头checkSchemaSDL断言输出包含THIS FILE WAS GENERATED与对象类型名MyObjecttests/functional/emit-schema-sdl.ts排序行为当sortedSchema: true默认时descriptionProperty会排在normalProperty之前按字母序设为false时保持声明顺序——测试同时断言了两种方向的顺序tests/functional/emit-schema-sdl.tsbuildSchema三种形态分别验证了字符串路径、true落到process.cwd()、配置对象含pathsortedSchema: false三种写法均能正确落盘tests/functional/emit-schema-sdl.ts错误处理mock 掉writeFile/mkdir抛错后断言异常会向外传播且不会留下残留文件tests/functional/emit-schema-sdl.ts印证了仅 ENOENT 才自动建目录、其余错误直接抛出的实现。进阶自定义指令如何出现在 SDL 中TypeGraphQL 通过Directive装饰器支持在类型、字段、参数等位置声明指令用法见 docs/directives.md但有一个已知限制docs/directives.md 有专门说明指令不会出现在生成的 Schema 定义文件中。原因是graphql-js不提供在代码中设置指令的能力其内置printSchema在打印时会省略指令。若要生成包含自定义指令的 SDL需要绕过内置printSchema借助第三方实现例如graphql-tools/utils的printSchemaWithDirectives。下述示例来自当前文档树的 docs/emit-schema.mdimport { GraphQLSchema, lexicographicSortSchema } from graphql; import { printSchemaWithDirectives } from graphql-tools/utils; import fs from node:fs/promises; export async function emitSchemaDefinitionWithDirectivesFile( schemaFilePath: string, schema: GraphQLSchema, ): Promisevoid { const schemaFileContent printSchemaWithDirectives(lexicographicSortSchema(schema)); await fs.writeFile(schemaFilePath, schemaFileContent); }该自定义函数的使用方式与标准emitSchemaDefinitionFile完全一致const schema await buildSchema(/*...*/); await emitSchemaDefinitionWithDirectivesFile(/path/to/folder/schema.graphql, schema);注意这里的lexicographicSortSchema保留了排序输出的既有约定与默认sortedSchema: true行为保持一致。若项目大量依赖Directive如 Apollo Federation 的key、自定义权限指令等建议统一封装这样一个自定义导出函数替换所有emitSchemaDefinitionFile调用点。小结TypeGraphQL 为把内存 Schema 落盘为 SDL提供了两条互补路径构建期自动输出emitSchemaFile的布尔/字符串/配置对象三种形态与运行期程序化导出emitSchemaDefinitionFile/emitSchemaDefinitionFileSync配合PrintSchemaOptions.sortedSchema控制输出顺序。底层实现src/utils/emitSchemaDefinitionFile.ts、src/utils/buildSchema.ts自动附带生成告警头并递归创建目标目录功能行为有完整测试覆盖tests/functional/emit-schema-sdl.ts。对于需要保留自定义指令的 Schema则按本文方案基于graphql-tools/utils自定义打印函数即可示例参见 docs/emit-schema.md。赞分享后端GraphQLAPI设计【免费下载链接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!项目地址https://gitcode.com/gh_mirrors/ty/type-graphql点击查看免费下载相关推荐TypeGraphQL 输出 Schema SDL从 buildSchema 自动生成到程序化导出与自定义指令TypeGraphQL 输出 Schema SDL从 buildSchema 自动生成到程序化导出与自定义指令 TypeGraphQL 的核心特性是仅凭 Ty后端GraphQLAPI设计TypeGraphQL 输出 Schema SDL 文件全指南emitSchemaFile 与 emitSchemaDefinitionFile 实战详解TypeGraphQL 输出 Schema SDL 文件全指南emitSchemaFile 与 emitSchemaDefinitionFile 实战详解 T后端GraphQLAPI设计ART Backend-First Training API从 model.train() 到 backend.train() 的后端优先训练接口设计ART Backend First Training API从 model.train 到 backend.train 的后端优先训练接口设计 导读 本文以后端GraphQLAPI设计上一篇WaveTools鸣潮工具箱如何彻底解决PC游戏性能限制与数据管理难题下一篇txtai 可观测性Observability实战用 MLflow Tracing 透视 Textractor、Embeddings、RAG、Workflow 与 Agent 全流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表