From e509a2bafe399e5e0cc70d0bcb5cea382b448fb4 Mon Sep 17 00:00:00 2001 From: Mikhail Novikov Date: Wed, 10 May 2023 14:03:42 +0200 Subject: [PATCH 1/2] WIP relay mode --- .../ts-transform-graphql-js-tag/src/index.ts | 55 +++++++++++++++++-- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/packages/ts-transform-graphql-js-tag/src/index.ts b/packages/ts-transform-graphql-js-tag/src/index.ts index ae744ea47..f3c14db05 100644 --- a/packages/ts-transform-graphql-js-tag/src/index.ts +++ b/packages/ts-transform-graphql-js-tag/src/index.ts @@ -4,6 +4,7 @@ import { OperationDefinitionNode, parse, Kind, + DefinitionNode, } from "graphql"; interface GraphQLTagTransformContext { @@ -12,6 +13,7 @@ interface GraphQLTagTransformContext { transformer?: ( node: FragmentDefinitionNode | OperationDefinitionNode, ) => unknown; + relayMode: boolean; } export interface GraphQLTagTransformOptions { graphqlTagModule?: string; @@ -19,11 +21,13 @@ export interface GraphQLTagTransformOptions { transformer?: ( node: FragmentDefinitionNode | OperationDefinitionNode, ) => unknown; + relayMode?: boolean; } const DefaultContext: GraphQLTagTransformContext = { graphqlTagModuleRegexp: new RegExp(/^['"]@graphitation\/graphql-js-tag['"]$/), graphqlTagModuleExport: "graphql", + relayMode: false, }; export function getTransformer( @@ -169,12 +173,16 @@ function getVisitor( source = source.replace(/\$\{(.*)\}/g, ""); } - let definitions = getDefinitions( - source, - transformerContext.transformer, - ); - - return createDocument(definitions, interpolations); + if (transformerContext.relayMode) { + let definitions = getDefinitions(source, undefined); + return createRelayImport(definitions); + } else { + let definitions = getDefinitions( + source, + transformerContext.transformer, + ); + return createDocument(definitions, interpolations); + } } } @@ -278,6 +286,41 @@ function createDocument( ]); } +function createRelayImport(definitions: Array) { + if (definitions.length > 1) { + throw new Error("In relay mode you can only have one definition."); + } + const definition = definitions[0]; + if (definition) { + if ( + (definition.kind === "OperationDefinition" || + definition.kind === "FragmentDefinition") && + definition.name + ) { + return [ + ts.factory.createExpressionStatement( + ts.factory.createPropertyAccessExpression( + ts.factory.createCallExpression( + ts.factory.createIdentifier("require"), + undefined, + [ + ts.factory.createStringLiteral( + `./__generated__/${definition.name.value}.graphql.ts`, + ), + ], + ), + ts.factory.createIdentifier("default"), + ), + ), + ]; + } else { + throw new Error( + "In relay mode for each graphql tag, you can only have one definition, it must be named and be either operation of fragment.", + ); + } + } +} + function toAst(literal: any): ts.Expression { if (literal === null) { return ts.factory.createNull(); From 3edfb28aeb8e699892c4506997e814599e1f8643 Mon Sep 17 00:00:00 2001 From: Mikhail Novikov Date: Wed, 10 May 2023 15:03:50 +0200 Subject: [PATCH 2/2] Wip --- .../src/index.test.ts | 31 +++++++++++++++++++ .../ts-transform-graphql-js-tag/src/index.ts | 30 +++++++++--------- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/packages/ts-transform-graphql-js-tag/src/index.test.ts b/packages/ts-transform-graphql-js-tag/src/index.test.ts index 0e4fd0226..55fcc81d6 100644 --- a/packages/ts-transform-graphql-js-tag/src/index.test.ts +++ b/packages/ts-transform-graphql-js-tag/src/index.test.ts @@ -262,5 +262,36 @@ describe("transformer tests", () => { " `); }); + + it("should convert to imports in relay mode", () => { + expect.assertions(1); + const transformer = new Transformer() + .addTransformer((program: ts.Program) => + getTransformer({ + graphqlTagModule: "graphql-tag", + graphqlTagModuleExport: "gql", + relayMode: true, + }), + ) + .addMock({ + name: "graphql-tag", + content: `export const gql:any = () => {}`, + }) + .setFilePath("/index.tsx"); + + const actual = transformer.transform(` + import { gql } from "graphql-tag" + + export const query = gql\` + query Foo { + foo + } + \` + `); + expect(actual).toMatchInlineSnapshot(` + "export const query = require("./__generated__/Foo.graphql.ts").default; + " + `); + }); }); }); diff --git a/packages/ts-transform-graphql-js-tag/src/index.ts b/packages/ts-transform-graphql-js-tag/src/index.ts index f3c14db05..e2c2429c6 100644 --- a/packages/ts-transform-graphql-js-tag/src/index.ts +++ b/packages/ts-transform-graphql-js-tag/src/index.ts @@ -63,6 +63,10 @@ export function createTransformerContext( context.transformer = options.transformer; + if (options.relayMode) { + context.relayMode = options.relayMode; + } + return context; } @@ -175,7 +179,7 @@ function getVisitor( if (transformerContext.relayMode) { let definitions = getDefinitions(source, undefined); - return createRelayImport(definitions); + return createRelayImport(definitions as DefinitionNode[]); } else { let definitions = getDefinitions( source, @@ -297,22 +301,18 @@ function createRelayImport(definitions: Array) { definition.kind === "FragmentDefinition") && definition.name ) { - return [ - ts.factory.createExpressionStatement( - ts.factory.createPropertyAccessExpression( - ts.factory.createCallExpression( - ts.factory.createIdentifier("require"), - undefined, - [ - ts.factory.createStringLiteral( - `./__generated__/${definition.name.value}.graphql.ts`, - ), - ], + return ts.factory.createPropertyAccessExpression( + ts.factory.createCallExpression( + ts.factory.createIdentifier("require"), + undefined, + [ + ts.factory.createStringLiteral( + `./__generated__/${definition.name.value}.graphql.ts`, ), - ts.factory.createIdentifier("default"), - ), + ], ), - ]; + ts.factory.createIdentifier("default"), + ); } else { throw new Error( "In relay mode for each graphql tag, you can only have one definition, it must be named and be either operation of fragment.",