Skip to content

Commit

Permalink
MOAR EDGE CASES!
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Jun 20, 2018
1 parent 887e7ba commit ebf9ebf
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ exports[`Leaves other graphql tags alone 1`] = `
"import React from 'react';
import { graphql } from 'relay';
export default (() => React.createElement(\\"div\\", null, data.site.siteMetadata.title));
export const query = graphql\`
{
site { siteMetadata { title }}
}
\`;"
export const query = \\"3687030656\\";"
`;

exports[`Transforms queries in <StaticQuery> 1`] = `
Expand All @@ -22,14 +18,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\\";"`;
132 changes: 81 additions & 51 deletions packages/babel-plugin-remove-graphql-queries/src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => (
<StaticQuery
query={graphql\`{site { siteMetadata { title }}}\`}
render={data => <div>{data.site.siteMetadata.title}</div>}
/>
)
`

var pageComponent = `
import React from 'react'
import { graphql } from 'gatsby'
export default () => (
<div>{data.site.siteMetadata.title}</div>
)
export const query = graphql\`
{
site { siteMetadata { title }}
}
\`
`

it(`Transforms queries in <StaticQuery>`, () => {
const { code } = babel.transform(staticQuery, {
function matchesSnapshot(query) {
const { code } = babel.transform(query, {
presets: [reactPreset],
plugins: [plugin],
})
expect(code).toMatchSnapshot()
}

it(`Transforms queries in <StaticQuery>`, () => {
matchesSnapshot(`
import React from 'react'
import { graphql, StaticQuery } from 'gatsby'
export default () => (
<StaticQuery
query={graphql\`{site { siteMetadata { title }}}\`}
render={data => <div>{data.site.siteMetadata.title}</div>}
/>
)
`)
})

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 () => (
<div>{data.site.siteMetadata.title}</div>
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'
Expand All @@ -83,11 +118,6 @@ it(`Leaves other graphql tags alone`, () => {
site { siteMetadata { title }}
}
\`
`,
{
presets: [reactPreset],
plugins: [plugin],
}
`
)
expect(code).toMatchSnapshot()
})
102 changes: 83 additions & 19 deletions packages/babel-plugin-remove-graphql-queries/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,91 @@ 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

const importPath = getTagImport(identifier)
if (!importPath) return 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 null

if (!tag.isIdentifier({ name: `graphql` })) 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()) {
console.log(`heee`)
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

Expand Down Expand Up @@ -92,21 +170,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))
Expand Down

0 comments on commit ebf9ebf

Please sign in to comment.