
后端GraphQLAPI設(shè)計【免費下載鏈接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!項目地址https://gitcode.com/gh_mirrors/ty/type-graphql點擊查看免費下載TypeGraphQL 的核心能力是通過 TypeScript 類和裝飾器直接生成 GraphQL schema而無需手寫 SDL。但在很多真實場景下我們?nèi)匀恍枰?schema 打印成schema.graphql舊版本為schema.gql文本文件——比如供 GraphQL 生態(tài)中的客戶端工具做查詢自動補全與校驗、作為回歸檢測的快照、或者讓團隊成員直接閱讀 SDL 來探索 API。本文以 TypeGraphQL 官方文檔為基礎(chǔ)結(jié)合倉庫源碼與測試用例系統(tǒng)講解兩種輸出 schema 定義文件的完整方案buildSchema的emitSchemaFile自動生成以及emitSchemaDefinitionFile/emitSchemaDefinitionFileSync的程序化生成并深入剖析底層實現(xiàn)細(xì)節(jié)。為什么要輸出 Schema SDL 文件TypeGraphQL 的主打特性是只用類與裝飾器建 schema因此生成的 schema 對象通常只存在于運行時內(nèi)存中。但以下場景需要它被持久化為 SDL 文本文件客戶端工具鏈GraphQL 生態(tài)中的很多工具需要 SDL 文件來完成客戶端查詢的自動補全與校驗Schema 回歸檢測把 SDL 文件當(dāng)作快照snapshot通過 diff 感知 schema 的意外變更API 探索相比閱讀復(fù)雜的 TypeGraphQL 應(yīng)用代碼、或在 GraphiQL / GraphQL Playground 中反復(fù)點擊直接閱讀 SDL 文件往往更直觀高效。TypeGraphQL 為此提供了兩種生成 schema 定義文件的方式下文分別展開。值得注意的是0.17.0 時代默認(rèn)輸出的文件名是schema.gql而當(dāng)前倉庫版本對應(yīng) docs/emit-schema.md中默認(rèn)文件名已統(tǒng)一為schema.graphql下文以當(dāng)前倉庫行為為準(zhǔn)。方式一通過 buildSchema 的 emitSchemaFile 選項自動生成最省事的方式是在調(diào)用buildSchema時傳入emitSchemaFile選項讓 TypeGraphQL 在每次構(gòu)建 schema 時自動把定義寫入文件。該選項支持三種形態(tài)布爾值、字符串路徑、以及配置對象。const schema await buildSchema({ resolvers: [ExampleResolver], // 自動在項目工作目錄下創(chuàng)建 schema.graphql 文件 emitSchemaFile: true, // 或者指定文件寫入路徑 emitSchemaFile: path.resolve(__dirname, __snapshots__/schema/schema.graphql), // 或者傳入配置對象精細(xì)化控制輸出 emitSchemaFile: { path: __dirname /schema.graphql, sortedSchema: false, // 默認(rèn)情況下輸出的 schema 會按字母序排序 }, });三種傳參形態(tài)的語義從 src/utils/buildSchema.ts 的getEmitSchemaDefinitionFileOptions實現(xiàn)可以精確還原三種形態(tài)的處理邏輯emitSchemaFile: true使用默認(rèn)路徑path.resolve(process.cwd(), schema.graphql)即當(dāng)前進程工作目錄process.cwd()下的schema.graphqlemitSchemaFile: 路徑字符串把字符串直接當(dāng)作完整的目標(biāo)文件路徑包含文件名示例中的__snapshots__/schema/schema.graphql即屬此類emitSchemaFile: { ... }配置對象對象類型為EmitSchemaFileOptions即{ path?: string } PartialPrintSchemaOptions。其中path缺省時回落為默認(rèn)路徑其余屬性即PrintSchemaOptions的字段會與默認(rèn)值做淺合并{ ...defaultPrintSchemaOptions, ...options }。PrintSchemaOptions控制 schema 輸出的格式PrintSchemaOptions是控制輸出格式的配置接口定義于 src/utils/emitSchemaDefinitionFile.tsexport interface PrintSchemaOptions { sortedSchema: boolean; } export const defaultPrintSchemaOptions: PrintSchemaOptions { sortedSchema: true, };sortedSchema默認(rèn)true決定打印前是否對 schema 做字典序排序。排序通過graphql-js的lexicographicSortSchema實現(xiàn)見同文件getSchemaFileContent使類型、字段按字母序穩(wěn)定排列利于生成 diff 友好的快照文件設(shè)為false則保留 schema 構(gòu)建時的原始定義順序。0.17.0 舊版文檔中展示的commentDescriptions: true選項把...描述輸出為#注釋形式在舊版PrintSchemaOptions中存在當(dāng)前倉庫版本的選項接口已收斂為sortedSchema一個字段使用時以當(dāng)前安裝版本導(dǎo)出的類型為準(zhǔn)。自動生成的文件頭部警告通過emitSchemaFile或emitSchemaDefinitionFile生成的文件并非純 SDL而是帶有一段固定的生成警告頭generatedSchemaWarning定義于 src/utils/emitSchemaDefinitionFile.ts# ----------------------------------------------- # !!! THIS FILE WAS GENERATED BY TYPE-GRAPHQL !!! # !!! DO NOT MODIFY THIS FILE BY YOURSELF !!! # -----------------------------------------------這提醒開發(fā)者該文件是構(gòu)建產(chǎn)物、不應(yīng)手工修改。測試 tests/functional/emit-schema-sdl.ts 中的checkSchemaSDL也明確斷言生成內(nèi)容必須包含THIS FILE WAS GENERATED字樣。路徑不存在時自動創(chuàng)建目錄emitSchemaFile指向的目錄不存在時TypeGraphQL 不會報錯而是自動遞歸創(chuàng)建目錄。其底層由 src/helpers/filesystem.ts 的outputFile/outputFileSync完成先嘗試直接寫文件若拋出ENOENT目錄不存在則先用mkdir(dirname, { recursive: true })建目錄再寫入其他異常則原樣向上拋出。這也解釋了為何示例中__snapshots__/schema/schema.graphql這樣的深層路徑可以一次成功。buildSchemaSync 同步版本如果項目環(huán)境不適合異步構(gòu)建例如某些啟動腳本或同步初始化流程可以使用buildSchemaSync。它與buildSchema接受完全相同的BuildSchemaOptions包括emitSchemaFile的三種形態(tài)內(nèi)部調(diào)用emitSchemaDefinitionFileSync同步寫盤見 src/utils/buildSchema.ts。異步/同步兩種 API 由emitSchemaDefinitionFile基于fs/promises與emitSchemaDefinitionFileSync基于fs分別支撐。方式二程序化調(diào)用 emitSchemaDefinitionFile 手動生成第二種方式完全繞開buildSchema在任何持有GraphQLSchema對象的地方手動調(diào)用導(dǎo)出函數(shù)寫文件。TypeGraphQL 從 src/utils/index.ts 導(dǎo)出emitSchemaDefinitionFile、emitSchemaDefinitionFileSync以及PrintSchemaOptions類型、defaultPrintSchemaOptions常量。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); });函數(shù)簽名見 src/utils/emitSchemaDefinitionFile.tsexport function emitSchemaDefinitionFileSync( schemaFilePath: string, schema: GraphQLSchema, options: PrintSchemaOptions defaultPrintSchemaOptions, ): void; export async function emitSchemaDefinitionFile( schemaFilePath: string, schema: GraphQLSchema, options: PrintSchemaOptions defaultPrintSchemaOptions, ): Promisevoid;第一個參數(shù)為完整目標(biāo)文件路徑含文件名第二個參數(shù)為任意GraphQLSchema對象不要求它一定來自buildSchema上例中的getSchemaNotFromBuildSchemaFunction即示意任意來源第三個可選參數(shù)為PrintSchemaOptions省略時使用defaultPrintSchemaOptions即sortedSchema: true。典型應(yīng)用場景官方文檔點名的兩類典型用法快照測試把該函數(shù)放進測試腳本生成 schema 快照并與預(yù)期文件比對從而在 schema 發(fā)生意外變化時讓測試失敗本地開發(fā)熱生成結(jié)合文件監(jiān)聽器如上例的hypotheticalFileWatcher在.ts源文件變更時自動重新生成 SDL保持本地隨時有一份最新 schema 可讀。進階讓自定義指令出現(xiàn)在生成的 SDL 中TypeGraphQL 本身并不直接支持在輸出的 schema 中攜帶自定義指令custom directives原因是graphql-js的printSchema函數(shù)存在限制無法打印指令定義。如果你需要自定義指令出現(xiàn)在生成文件中就需要自行實現(xiàn)一個輸出函數(shù)借助第三方printSchema實現(xiàn)例如graphql-tools/utils提供的printSchemaWithDirectives。這一主題完整收錄于當(dāng)前版本文檔 docs/emit-schema.md實現(xiàn)示例import { 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); }用法與標(biāo)準(zhǔn)emitSchemaDefinitionFile完全一致const schema await buildSchema(/*...*/); await emitSchemaDefinitionWithDirectivesFile(/path/to/folder/schema.graphql, schema);自定義函數(shù)可以同時復(fù)用 TypeGraphQL 的lexicographicSortSchema排序思路保持輸出穩(wěn)定。若無需自定義指令則優(yōu)先使用內(nèi)建的emitSchemaDefinitionFile即可。測試與真實項目中的用法參考倉庫中的功能測試 tests/functional/emit-schema-sdl.ts 完整覆蓋了上述全部行為可作為實現(xiàn)細(xì)節(jié)的權(quán)威佐證默認(rèn)路徑mockprocess.cwd()后emitSchemaFile: true會在工作目錄生成schema.graphql測試第 168-177 行路徑字符串emitSchemaFile: targetPath直接寫入指定路徑測試第 158-166 行配置對象emitSchemaFile: { path, sortedSchema: false }同時生效測試第 179-192 行傳空對象{}時回落默認(rèn)路徑與默認(rèn)排序測試第 194-205 行排序行為checkSchemaSDL斷言sortedSchema: true時descriptionProperty排在normalProperty之前字母序false時保持定義順序測試第 57-69 行錯誤傳播寫入或建目錄遇到非ENOENT異常時錯誤會原樣拋出測試第 89-113、134-154 行同步版本buildSchemaSync與emitSchemaDefinitionFileSync的行為逐項等價測試第 208-257 行。在真實項目中emitSchemaFile常與運行環(huán)境聯(lián)動。例如 docs/azure-functions.md 展示了按環(huán)境變量條件開啟的做法emitSchemaFile: process.env.NODE_ENV local ? path.resolve(./src/schema.graphql) : false,這樣在本地開發(fā)時自動產(chǎn)出 schema 文件而在云端運行時關(guān)閉以免寫只讀文件系統(tǒng)。另一個例子是 docs/nestjs.md在 NestJS 集成中同樣通過emitSchemaFile: true便捷生成 SDL。這兩處都是自動生成方式在實際工程中的典型落地形態(tài)。小結(jié)自動生成buildSchema({ emitSchemaFile: true | 路徑 | { path?, sortedSchema? } })構(gòu)建 schema 的同時寫盤默認(rèn)輸出到process.cwd()/schema.graphql默認(rèn)按字典序排序并自動附帶由 TypeGraphQL 生成的警告頭、自動創(chuàng)建缺失目錄同步場景可用buildSchemaSync。程序化生成emitSchemaDefinitionFile(path, schema, options?)與同步版emitSchemaDefinitionFileSync適合快照測試、文件監(jiān)聽熱更新等需要掌控時機的場景schema 對象可來自任意來源。自定義指令內(nèi)建輸出基于printSchema無法打印指令定義需要自定義輸出函數(shù)如借助printSchemaWithDirectives后以相同方式調(diào)用。兩種方式均以 src/utils/emitSchemaDefinitionFile.ts 為統(tǒng)一實現(xiàn)核心文件寫入細(xì)節(jié)封裝在 src/helpers/filesystem.ts完整行為由 tests/functional/emit-schema-sdl.ts 驗證可按需深入源碼進一步探索。贊分享后端GraphQLAPI設(shè)計【免費下載鏈接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!項目地址https://gitcode.com/gh_mirrors/ty/type-graphql點擊查看免費下載相關(guān)推薦TypeGraphQL 輸出 Schema SDL從 buildSchema 自動生成到程序化導(dǎo)出與自定義指令TypeGraphQL 輸出 Schema SDL從 buildSchema 自動生成到程序化導(dǎo)出與自定義指令 TypeGraphQL 的核心特性是僅憑 Ty后端GraphQLAPI設(shè)計TypeGraphQL Schema SDL 生成指南用 buildSchema 與 emitSchemaDefinitionFile 將 GraphQL Schema 導(dǎo)出為文件TypeGraphQL Schema SDL 生成指南用 buildSchema 與 emitSchemaDefinitionFile 將 GraphQL S后端GraphQLAPI設(shè)計TypeGraphQL 輸出 Schema SDL 文件全指南從 emitSchemaFile 到程序化導(dǎo)出與自定義指令TypeGraphQL 輸出 Schema SDL 文件全指南從 emitSchemaFile 到程序化導(dǎo)出與自定義指令 導(dǎo)讀 TypeGraphQL 的核心后端GraphQLAPI設(shè)計上一篇三分鐘裝好胡桃工具箱 Snap.Hutao原神抽卡保底不再手記下一篇零基礎(chǔ)10分鐘做出MapleStory MODHarepacker復(fù)活版資源編輯與地圖創(chuàng)作完整指南創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考