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 ae744ea47..e2c2429c6 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( @@ -59,6 +63,10 @@ export function createTransformerContext( context.transformer = options.transformer; + if (options.relayMode) { + context.relayMode = options.relayMode; + } + return context; } @@ -169,12 +177,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 as DefinitionNode[]); + } else { + let definitions = getDefinitions( + source, + transformerContext.transformer, + ); + return createDocument(definitions, interpolations); + } } } @@ -278,6 +290,37 @@ 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.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();