From 947d97d6c0be959028eb9df9792fc601d6a0b1ee Mon Sep 17 00:00:00 2001 From: Jason Quense Date: Wed, 20 Jun 2018 14:07:58 -0400 Subject: [PATCH] MOAR EDGE CASES! --- .../src/__tests__/__snapshots__/index.js.snap | 20 +-- .../src/__tests__/index.js | 132 +++++++++++------- .../src/index.js | 104 +++++++++++--- 3 files changed, 176 insertions(+), 80 deletions(-) diff --git a/packages/babel-plugin-remove-graphql-queries/src/__tests__/__snapshots__/index.js.snap b/packages/babel-plugin-remove-graphql-queries/src/__tests__/__snapshots__/index.js.snap index 91920cf6c1b9f..e6c7e0dea8655 100644 --- a/packages/babel-plugin-remove-graphql-queries/src/__tests__/__snapshots__/index.js.snap +++ b/packages/babel-plugin-remove-graphql-queries/src/__tests__/__snapshots__/index.js.snap @@ -22,14 +22,14 @@ export default (() => React.createElement(StaticQuery, { }));" `; -exports[`Transforms queries in page components 1`] = ` -"import React from 'react'; -export default (() => React.createElement(\\"div\\", null, data.site.siteMetadata.title)); -export const query = \\"3227941719\\";" -`; +exports[`Transforms queries in page components 1`] = `"export const query = \\"3687030656\\";"`; -exports[`allows the global tag 1`] = ` -"import React from 'react'; -export default (() => React.createElement(\\"div\\", null, data.site.siteMetadata.title)); -export const query = \\"3687030656\\";" -`; +exports[`allows the global tag 1`] = `"export const query = \\"3687030656\\";"`; + +exports[`handles import aliasing 1`] = `"export const query = \\"3687030656\\";"`; + +exports[`handles require 1`] = `"export const query = \\"3687030656\\";"`; + +exports[`handles require alias 1`] = `"export const query = \\"3687030656\\";"`; + +exports[`handles require namespace 1`] = `"export const query = \\"3687030656\\";"`; diff --git a/packages/babel-plugin-remove-graphql-queries/src/__tests__/index.js b/packages/babel-plugin-remove-graphql-queries/src/__tests__/index.js index fada793593bd8..0e360bc06d0c6 100644 --- a/packages/babel-plugin-remove-graphql-queries/src/__tests__/index.js +++ b/packages/babel-plugin-remove-graphql-queries/src/__tests__/index.js @@ -2,74 +2,109 @@ const babel = require(`babel-core`) const reactPreset = require(`@babel/preset-react`) const plugin = require(`../`) -var staticQuery = ` -import React from 'react' -import { graphql, StaticQuery } from 'gatsby' - -export default () => ( -
{data.site.siteMetadata.title}
} - /> -) -` - -var pageComponent = ` -import React from 'react' -import { graphql } from 'gatsby' - -export default () => ( -
{data.site.siteMetadata.title}
-) - -export const query = graphql\` - { - site { siteMetadata { title }} - } -\` -` - -it(`Transforms queries in `, () => { - const { code } = babel.transform(staticQuery, { +function matchesSnapshot(query) { + const { code } = babel.transform(query, { presets: [reactPreset], plugins: [plugin], }) expect(code).toMatchSnapshot() +} + +it(`Transforms queries in `, () => { + matchesSnapshot(` + import React from 'react' + import { graphql, StaticQuery } from 'gatsby' + + export default () => ( +
{data.site.siteMetadata.title}
} + /> + ) + `) }) it(`Transforms queries in page components`, () => { - const { code } = babel.transform(pageComponent, { - presets: [reactPreset], - plugins: [plugin], - }) - expect(code).toMatchSnapshot() + matchesSnapshot(` + import { graphql } from 'gatsby' + + export const query = graphql\` + { + site { siteMetadata { title }} + } + \` + `) }) it(`allows the global tag`, () => { - const { code } = babel.transform( + matchesSnapshot( ` - import React from 'react' + export const query = graphql\` + { + site { siteMetadata { title }} + } + \` + ` + ) +}) - export default () => ( -
{data.site.siteMetadata.title}
+it(`handles import aliasing`, () => { + matchesSnapshot( + ` + import { graphql as gql } from 'gatsby' + + export const query = gql\` + { + site { siteMetadata { title }} + } + \` + ` ) +}) + +it(`handles require`, () => { + matchesSnapshot( + ` + const { graphql } = require('gatsby') export const query = graphql\` { site { siteMetadata { title }} } \` - `, - { - presets: [reactPreset], - plugins: [plugin], - } + ` + ) +}) + +it(`handles require namespace`, () => { + matchesSnapshot( + ` + const Gatsby = require('gatsby') + + export const query = Gatsby.graphql\` + { + site { siteMetadata { title }} + } + \` + ` + ) +}) +it(`handles require alias`, () => { + matchesSnapshot( + ` + const { graphql: gql } = require('gatsby') + + export const query = gql\` + { + site { siteMetadata { title }} + } + \` + ` ) - expect(code).toMatchSnapshot() }) it(`Leaves other graphql tags alone`, () => { - const { code } = babel.transform( + matchesSnapshot( ` import React from 'react' import { graphql } from 'relay' @@ -83,11 +118,6 @@ it(`Leaves other graphql tags alone`, () => { site { siteMetadata { title }} } \` - `, - { - presets: [reactPreset], - plugins: [plugin], - } + ` ) - expect(code).toMatchSnapshot() }) diff --git a/packages/babel-plugin-remove-graphql-queries/src/index.js b/packages/babel-plugin-remove-graphql-queries/src/index.js index 9146ce024589f..09b9703c9abfe 100644 --- a/packages/babel-plugin-remove-graphql-queries/src/index.js +++ b/packages/babel-plugin-remove-graphql-queries/src/index.js @@ -3,13 +3,93 @@ const graphql = require(`gatsby/graphql`) const murmurhash = require(`./murmur`) const nodePath = require(`path`) -function getGraphQLTag(path) { - const tag = path.get(`tag`) +function getTagImport(tag) { + const name = tag.node.name + const binding = tag.scope.getBinding(name) + + if (!binding) return null + + const path = binding.path + const parent = path.parentPath + + if ( + binding.kind === `module` && + parent.isImportDeclaration() && + parent.node.source.value === `gatsby` + ) + return path + + if ( + path.isVariableDeclarator() && + path.get(`init`).isCallExpression() && + path.get(`init.callee`).isIdentifier({ name: `require` }) && + path.get(`init`).node.arguments[0].value === `gatsby` + ) { + const id = path.get(`id`) + if (id.isObjectPattern()) { + return id + .get(`properties`) + .find(path => path.get(`value`).node.name === name) + } + return id + } + return null +} + +function isGraphqlTag(tag) { + const isExpression = tag.isMemberExpression() + const identifier = isExpression ? tag.get(`object`) : tag - if (!tag.isIdentifier({ name: `graphql` })) return {} + const importPath = getTagImport(identifier) + if (!importPath) + return ( + tag.scope.hasGlobal(`graphql`) && tag.isIdentifier({ name: `graphql` }) + ) + + if ( + isExpression && + (importPath.isImportNamespaceSpecifier() || importPath.isIdentifier()) + ) { + return tag.get(`property`).node.name === `graphql` + } + + if (importPath.isImportSpecifier()) + return importPath.node.imported.name === `graphql` + + if (importPath.isObjectProperty()) + return importPath.get(`key`).node.name === `graphql` + + return false +} +function removeImport(tag) { + const isExpression = tag.isMemberExpression() + const identifier = isExpression ? tag.get(`object`) : tag + const importPath = getTagImport(identifier) + + if (!importPath) return + + const parent = importPath.parentPath + + if (importPath.isImportSpecifier()) { + if (parent.node.specifiers.length === 1) parent.remove() + else importPath.remove() + } + if (importPath.isObjectProperty()) { + if (parent.node.properties.length === 1) + importPath.findParent(p => p.isVariableDeclaration())?.remove() + else importPath.remove() + } + if (importPath.isIdentifier()) { + importPath.findParent(p => p.isVariableDeclaration())?.remove() + } +} + +function getGraphQLTag(path) { + const tag = path.get(`tag`) const isGlobal = tag.scope.hasGlobal(`graphql`) - if (!isGlobal && !tag.referencesImport(`gatsby`)) return {} + + if (!isGlobal && !isGraphqlTag(tag)) return {} const quasis = path.node.quasi.quasis @@ -92,21 +172,7 @@ export default function({ types: t }) { const query = text const tag = path2.get(`tag`) - const binding = tag.scope.getBinding(tag.node.name) - if (!isGlobal && binding && binding.kind === `module`) { - const importPath = binding.path - - if (importPath.isImportSpecifier()) { - const parent = importPath.parentPath - - // remove the runtime import, or if there are no other gatsby imports remove the entire import - if (parent.node.specifiers.length === 1) { - parent.remove() - } else { - importPath.remove() - } - } - } + if (!isGlobal) removeImport(tag) // Replace the query with the hash of the query. path2.replaceWith(t.StringLiteral(queryHash))