Protobuf till GraphQL-konverterare
Klistra in ett .proto-schema. Få GraphQL SDL med types, enums, icke-nullbara listor och syntetiska entry-typer för map-fält — redo att starta upp ett gateway-schema.
Indata (.proto-schema)
Utdata (GraphQL SDL)
Vad det här verktyget gör
Du har ett Protocol Buffers-schema och en GraphQL-gateway framför (eller är på väg att bygga en). Verktyg som Googles rejoiner kopplar proto-meddelanden till en levande GraphQL-endpoint i runtime, men för att skissa schemat, göra kodgranskning eller så en handskriven resolver-lager räcker det oftast att se hur SDL:en ser ut. Den här konverteraren gör det i din webbläsare — klistra in, kopiera utdata, släpp in i schema.graphql.
Varje message blir en GraphQL-type; varje enum blir en GraphQL-enum. Fältnamn konverteras från snake_case (proto-konvention) till camelCase (konventionen som finns i GraphQL-specen och som varje linter tvingar fram). Skalärer och enums skrivs ut non-null (String!, OrderStatus!) eftersom proto3-fält alltid har ett värde på tråden — även icke-satta hamnar på nollvärdet. Singulära nästlade meddelanden skrivs ut som nullable, vilket matchar proto3:s has-value-semantik.
repeated-fält renderas som [T!]! — non-null lista med non-null element — för att proto3:s repeated-fält aldrig är null och aldrig innehåller null-poster. Maps kräver en omväg: GraphQL har ingen inbyggd map-typ, så map<string, string> på ett metadata-fält blir [OrderMetadataEntry!]! med en syntetisk type OrderMetadataEntry { key: String! value: String! } — samma mönster som Apollo och de flesta produktions-gateway:er från proto till GraphQL använder. Hela konverteringen körs på klientsidan; inget av ditt schema lämnar sidan.
Så använder du det
Tre steg. Utdata är klar att klistra in i vilken GraphQL-server som helst som accepterar SDL.
Klistra in ditt .proto-schema
Släpp schemat i editorn till vänster. syntax = "proto3"; överst är valfritt — parsern hanterar nästlade message-block, enum-deklarationer, oneof, map<K, V> och fält-options. Imports känns igen men hoppas över, så klistra in importerade typer inline om du beror på dem.
Fältnamnskonverteringen är automatisk: order_id i .proto blir orderId i GraphQL. Type- och enum-namn behåller PascalCase. Map-fält får en syntetisk entry-typ med namnet <Förälder><Fält>Entry.
Läs utdatan
Till höger: GraphQL SDL med enums först, sedan map-entry-typer, sedan messages i deklarationsordning. Nästlade typer kommer före sina föräldrar så att filen läses uppifrån och ner. Släpp in det i en .graphql-fil som din server laddar via graphql-tools eller buildSchema.
Koppla in resolvers
Schemat ger dig formen; du måste fortfarande skriva resolvers (eller generera dem från din gRPC-tjänst). För en snabb väg, peka en Apollo Server mot detta SDL med stub-resolvers, och byt sedan ut varje stub mot ett anrop till ditt gRPC-backend. Justera nullbarhet om ditt runtime-kontrakt avviker från proto3-defaulterna.
När det här faktiskt sparar tid
Starta upp en GraphQL-gateway ovanför ett gRPC-backend
Ditt team har en gRPC-tjänst och produkten vill ha en GraphQL-endpoint för webbklienten. Du behöver ett startschema att diskutera med frontend-folket innan du skriver några resolvers. Klistra in protot, kopiera SDL:en, släpp in i ett dokument — klart.
Granska en Protobuf-API-ändring
En backend-kollega lade till fält i ett message. Du vill se hur det påverkar den publika GraphQL-ytan utan att köra om hela codegen-pipelinen. Klistra in det nya .proto:t, diffa SDL-utdatan mot ditt nuvarande schema och lämna en fokuserad granskningskommentar.
Dokumentation och designdiskussioner
Du skriver en RFC om en ny gRPC-tjänst som så småningom kommer behöva ett GraphQL framför. Att lägga in båda formerna i dokumentet — proto på ena sidan, SDL på andra — gör samtalet konkret. Den här konverteraren ger dig SDL-sidan utan att du behöver dra igång en build.
Migrera från REST eller gRPC till GraphQL
Du ärvde en Protobuf-definierad tjänst och den nya produktbriefen kräver ett GraphQL-API. Generera ett utkast till schema här som startpunkt för migreringen och iterera sedan för hand på fältnamn, nullbarhet och paginering.
Vanliga frågor
Skickas mitt schema någonstans?
Nej. .proto-parsern och SDL-emittern körs båda som JavaScript i din webbläsare. Öppna DevTools och kolla Network-fliken medan du klistrar in — noll requests. Användbart när schemat innehåller interna typnamn, paketsökvägar eller annat du inte vill skicka till en tredjepartstjänst.
Varför skrivs 64-bitars heltal som String?
Den inbyggda Int-skaläret i GraphQL är signed 32-bitars enligt GraphQL-specen, vilket inte rymmer ett proto-int64 eller uint64. Den vedertagna lösningen är att definiera en custom-skalär (ofta kallad BigInt, Long eller Int64) och serialisera värdet som en sträng. Den här konverteraren skriver ut String för alla 64-bitars heltalsTyper så att schemat blir giltigt direkt; byt ut de förekomsterna mot din custom-skaläres namn när du har definierat den på servern.
Hur hanteras map-fält?
GraphQL har ingen inbyggd map-typ — det finns ingen { String: String }-form. Standardlösningen är att rulla ut mapen till en lista av { key, value }-par. Så map<string, string> metadata = 8; på ett message Order blir metadata: [OrderMetadataEntry!]! med en syntetisk type OrderMetadataEntry { key: String! value: String! }. Entry-typens namn härleds från förälder-message + fältnamn i PascalCase + Entry, vilket är konventionen som de flesta proto-till-GraphQL-gateway:er använder, inklusive rejoiner.
Hur hanteras oneof?
Varje fält i ett oneof skrivs ut som ett vanligt nullable-fält med en kommentar som markerar gruppen. GraphQL har inget inbyggt koncept för diskriminerade unioner som mappar rent mot proto-oneof — närmast kommer en custom union-typ eller en @oneOf-input-direktiv (nyligen tillagd i specen för inputs). För output-typer skriver de flesta scheman bara ut varje oneof-fall som nullable och dokumenterar restriktionen, vilket är vad vi gör här. Redigera utdatan för hand om du vill ha strikta union-typer.
Varför är skalärer non-null men messages nullable?
Det matchar proto3:s semantik. Skalärer i proto3 har alltid ett värde på tråden — ett icke-satt string-fält hamnar på "", ett icke-satt int32 hamnar på 0. Det går inte att skilja "satt till default" från "icke-satt" för skalärer utan att använda optional eller wrapper-typer. Singulära nästlade messages har dock has-value-semantik — fälttaggen kan saknas helt — så de mappar naturligt till nullable GraphQL-fält. repeated-fält är alltid non-null-listor med non-null-element, även det enligt proto3.
Hur är det med google.protobuf.Timestamp och andra well-known types?
Well-known types skrivs som standard ut som String, eftersom GraphQL inte har en inbyggd DateTime-skalär. De flesta produktionsscheman definierar en custom DateTime- (eller ISO8601String-)skalär och byter ut String-förekomsterna efter generering. Samma sak gäller google.protobuf.Duration, Any och Value — skriv ut som String först, byt mot custom-skalärer när de är definierade.
bytes-fält — varför String?
GraphQL har ingen inbyggd binär skalär. Den konventionella kodningen är base64 i ett String-fält, vilket också är vad proto3:s JSON-mappning använder för bytes. Vill du ha striktare typning, definiera en custom Base64String-skalär på servern och byt ut String på de fälten.
Relaterade verktyg
Jobbar du med Protobuf, GraphQL och JSON funkar dessa bra ihop: