Skip to content

Commit

Permalink
feat(gatsby): Initial GraphQL Typegen Implementation (#35487)
Browse files Browse the repository at this point in the history
Co-authored-by: Michal Piechowiak <misiek.piechowiak@gmail.com>
  • Loading branch information
LekoArts and pieh committed May 3, 2022
1 parent 17cbc7c commit c9d98a4
Show file tree
Hide file tree
Showing 36 changed files with 1,343 additions and 64 deletions.
2 changes: 2 additions & 0 deletions e2e-tests/development-runtime/.gitignore
Expand Up @@ -74,3 +74,5 @@ cypress/fixtures
cypress/videos

__history__.json

src/gatsby-types.d.ts
@@ -0,0 +1,5 @@
describe('fragments.graphql', () => {
it('exists in .cache folder', () => {
cy.readFile('.cache/typegen/fragments.graphql')
})
})
@@ -0,0 +1,20 @@
describe('graphql-config', () => {
it('exists in .cache folder with correct data', () => {
cy.readFile('.cache/typegen/graphql.config.json', 'utf-8').then((json) => {
expect(json).to.deep.equal({
"schema": ".cache/typegen/schema.graphql",
"documents": [
"src/**/**.{ts,js,tsx,jsx}",
".cache/typegen/fragments.graphql"
],
"extensions": {
"endpoints": {
"default": {
"url": "http://localhost:8000/___graphql"
}
}
}
})
})
})
})
@@ -0,0 +1,5 @@
describe('schema.graphql', () => {
it('exists in .cache folder', () => {
cy.readFile('.cache/typegen/schema.graphql')
})
})
@@ -0,0 +1,5 @@
describe('gatsby-types.d.ts', () => {
it('exists in src folder', () => {
cy.readFile('src/gatsby-types.d.ts')
})
})
1 change: 1 addition & 0 deletions e2e-tests/development-runtime/gatsby-config.js
Expand Up @@ -8,6 +8,7 @@ module.exports = {
},
flags: {
DEV_SSR: false,
GRAPHQL_TYPEGEN: true,
},
plugins: [
`gatsby-plugin-react-helmet`,
Expand Down
4 changes: 2 additions & 2 deletions e2e-tests/development-runtime/package.json
Expand Up @@ -25,7 +25,7 @@
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-helmet": "^5.2.1",
"react-helmet": "^6.1.0",
"sass": "^1.32.8"
},
"keywords": [
Expand All @@ -35,7 +35,7 @@
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "cross-env CYPRESS_SUPPORT=y ENABLE_GATSBY_REFRESH_ENDPOINT=true GATSBY_EXPERIMENTAL_QUERY_ON_DEMAND=y gatsby develop",
"develop": "cross-env CYPRESS_SUPPORT=y ENABLE_GATSBY_REFRESH_ENDPOINT=true GATSBY_EXPERIMENTAL_QUERY_ON_DEMAND=y GATSBY_GRAPHQL_TYPEGEN=y gatsby develop",
"serve": "gatsby serve",
"clean": "gatsby clean",
"start": "npm run develop",
Expand Down
Expand Up @@ -15,7 +15,7 @@ export default function FakeDataHogwarts({ data: { fake }, pageContext: { uuid }
}

export const blogPostQuery = graphql`
query($id: String!) {
query FakeDataHogwarts($id: String!) {
fake: fakeData(id: { eq: $id }) {
fields {
slug
Expand Down
Expand Up @@ -15,7 +15,7 @@ export default function FakeDataPrefix({ data: { fake }, pageContext: { uuid } }
}

export const blogPostQuery = graphql`
query($id: String!) {
query FakeDataPrefix($id: String!) {
fake: fakeData(id: { eq: $id }) {
fields {
slug
Expand Down
Expand Up @@ -15,7 +15,7 @@ export default function FakeDataNested({ data: { fake }, pageContext: { uuid } }
}

export const blogPostQuery = graphql`
query($id: String!) {
query FakeDataNested($id: String!) {
fake: fakeData(id: { eq: $id }) {
fields {
slug
Expand Down
Expand Up @@ -15,7 +15,7 @@ export default function FakeDataPostfix({ data: { fake }, pageContext: { uuid }
}

export const blogPostQuery = graphql`
query($id: String!) {
query FakeDataPostfix($id: String!) {
fake: fakeData(id: { eq: $id }) {
fields {
slug
Expand Down
Expand Up @@ -15,7 +15,7 @@ export default function FakeData({ data: { fake }, pageContext: { uuid } }) {
}

export const blogPostQuery = graphql`
query($id: String!) {
query FakeData($id: String!) {
fake: fakeData(id: { eq: $id }) {
fields {
slug
Expand Down
7 changes: 7 additions & 0 deletions packages/gatsby/package.json
Expand Up @@ -20,6 +20,13 @@
"@babel/types": "^7.15.4",
"@gatsbyjs/reach-router": "^1.3.6",
"@gatsbyjs/webpack-hot-middleware": "^2.25.2",
"@graphql-codegen/add": "^3.1.1",
"@graphql-codegen/core": "^2.5.1",
"@graphql-codegen/plugin-helpers": "^2.4.2",
"@graphql-codegen/typescript": "^2.4.8",
"@graphql-codegen/typescript-operations": "^2.3.5",
"@graphql-tools/code-file-loader": "^7.2.14",
"@graphql-tools/load": "^7.5.10",
"@nodelib/fs.walk": "^1.2.8",
"@parcel/core": "^2.3.2",
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
Expand Down
2 changes: 2 additions & 0 deletions packages/gatsby/src/commands/develop-process.ts
Expand Up @@ -150,7 +150,9 @@ module.exports = async (program: IDevelopArgs): Promise<void> => {
program,
parentSpan,
app,
reporter,
pendingQueryRuns: new Set([`/`]),
shouldRunInitialTypegen: true,
})

const service = interpret(machine)
Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby/src/query/query-watcher.ts
Expand Up @@ -137,7 +137,7 @@ const watch = async (rootDir: string): Promise<void> => {
watcher = chokidar
.watch(
[slash(path.join(rootDir, `/src/**/*.{js,jsx,ts,tsx}`)), ...packagePaths],
{ ignoreInitial: true }
{ ignoreInitial: true, ignored: [`**/*.d.ts`] }
)
.on(`change`, path => {
emitter.emit(`SOURCE_FILE_CHANGED`, path)
Expand Down
14 changes: 10 additions & 4 deletions packages/gatsby/src/redux/types.ts
@@ -1,7 +1,12 @@
import type { TrailingSlash } from "gatsby-page-utils"
import { IProgram } from "../commands/types"
import { GraphQLFieldExtensionDefinition } from "../schema/extensions"
import { DocumentNode, GraphQLSchema, DefinitionNode } from "graphql"
import {
DocumentNode,
GraphQLSchema,
DefinitionNode,
SourceLocation,
} from "graphql"
import { SchemaComposer } from "graphql-compose"
import { IGatsbyCLIState } from "gatsby-cli/src/reporter/redux/types"
import { ThunkAction } from "redux-thunk"
Expand Down Expand Up @@ -153,12 +158,13 @@ export interface IDefinitionMeta {
def: DefinitionNode
filePath: string
text: string
templateLoc: any
printedAst: string
templateLoc: SourceLocation
printedAst: string | null
isHook: boolean
isStaticQuery: boolean
isFragment: boolean
hash: string
isConfigQuery: boolean
hash: number
}

type GatsbyNodes = Map<string, IGatsbyNode>
Expand Down
14 changes: 2 additions & 12 deletions packages/gatsby/src/schema/print.ts
Expand Up @@ -27,7 +27,7 @@ import {
import { printBlockString } from "graphql/language/blockString"
import { internalExtensionNames } from "./extensions"
import _ from "lodash"
import { builtInScalarTypeNames } from "./types/built-in-types"
import { internalTypeNames } from "./types/built-in-types"

export interface ISchemaPrintConfig {
path?: string
Expand Down Expand Up @@ -341,16 +341,6 @@ export const printTypeDefinitions = ({
)
return Promise.resolve()
}

const internalTypes = [
...builtInScalarTypeNames,
`Buffer`,
`Internal`,
`InternalInput`,
`Node`,
`NodeInput`,
`Query`,
]
const internalPlugins = [`internal-data-bridge`]

const typesToExclude = exclude?.types || []
Expand All @@ -360,7 +350,7 @@ export const printTypeDefinitions = ({

const isInternalType = (tc: NamedTypeComposer<unknown>): boolean => {
const typeName = getName(tc)
if (internalTypes.includes(typeName)) {
if (internalTypeNames.includes(typeName)) {
return true
}

Expand Down
10 changes: 10 additions & 0 deletions packages/gatsby/src/schema/types/built-in-types.ts
Expand Up @@ -157,3 +157,13 @@ export const builtInScalarTypeNames = [
`JSON`,
`String`,
]

export const internalTypeNames = [
...builtInScalarTypeNames,
`Buffer`,
`Internal`,
`InternalInput`,
`Node`,
`NodeInput`,
`Query`,
]
59 changes: 59 additions & 0 deletions packages/gatsby/src/services/graphql-typegen.ts
@@ -0,0 +1,59 @@
import { EventObject } from "xstate"
import { IBuildContext } from "../internal"
import { IDataLayerContext, IQueryRunningContext } from "../state-machines"
import {
writeGraphQLFragments,
writeGraphQLSchema,
} from "../utils/graphql-typegen/file-writes"
import { writeTypeScriptTypes } from "../utils/graphql-typegen/ts-codegen"

export async function graphQLTypegen(
{
program,
store,
parentSpan,
reporter,
}: IBuildContext | IQueryRunningContext | IDataLayerContext,
_: EventObject,
{
src: { compile },
}: {
src: {
type: string
compile?: "all" | "schema" | "definitions"
}
}
): Promise<void> {
// TypeScript requires null/undefined checks for these
// But this should never happen unless e.g. the state machine doesn't receive this information from a parent state machine
if (!program || !store || !compile || !reporter) {
throw new Error(
`Missing required params in graphQLTypegen. program: ${!!program}. store: ${!!store}. compile: ${!!compile}`
)
}
const directory = program.directory

const activity = reporter.activityTimer(
`Generating GraphQL and TypeScript types`,
{
parentSpan,
}
)
activity.start()

if (compile === `all` || compile === `schema`) {
await writeGraphQLSchema(directory, store)
if (compile === `schema`) {
reporter.verbose(`Re-Generate GraphQL Schema types`)
}
}
if (compile === `all` || compile === `definitions`) {
await writeGraphQLFragments(directory, store)
await writeTypeScriptTypes(directory, store)
if (compile === `definitions`) {
reporter.verbose(`Re-Generate TypeScript types & GraphQL fragments`)
}
}

activity.end()
}
1 change: 1 addition & 0 deletions packages/gatsby/src/services/index.ts
Expand Up @@ -15,5 +15,6 @@ export { runPageQueries } from "./run-page-queries"
export { waitUntilAllJobsComplete } from "../utils/wait-until-jobs-complete"
export { runMutationBatch } from "./run-mutation-batch"
export { recompile } from "./recompile"
export { graphQLTypegen } from "./graphql-typegen"

export * from "./types"
6 changes: 6 additions & 0 deletions packages/gatsby/src/services/initialize.ts
Expand Up @@ -26,6 +26,7 @@ import type { InternalJob } from "../utils/jobs/types"
import { enableNodeMutationsDetection } from "../utils/detect-node-mutations"
import { compileGatsbyFiles } from "../utils/parcel/compile-gatsby-files"
import { resolveModule } from "../utils/module-resolver"
import { writeGraphQLConfig } from "../utils/graphql-typegen/file-writes"

interface IPluginResolution {
resolve: string
Expand Down Expand Up @@ -658,6 +659,11 @@ export async function initialize({

const workerPool = WorkerPool.create()

// This is only run during `gatsby develop`
if (process.env.GATSBY_GRAPHQL_TYPEGEN) {
writeGraphQLConfig(program)
}

return {
store,
workerPool,
Expand Down
5 changes: 5 additions & 0 deletions packages/gatsby/src/services/types.ts
@@ -1,4 +1,5 @@
import { Span } from "opentracing"
import reporter from "gatsby-cli/lib/reporter"
import { IProgram } from "../commands/types"
import { Runner } from "../bootstrap/create-graphql-runner"
import { GraphQLRunner } from "../query/graphql-runner"
Expand All @@ -11,6 +12,8 @@ import { Compiler } from "webpack"
import { WebsocketManager } from "../utils/websocket-manager"
import { IWebpackWatchingPauseResume } from "../utils/start-server"

type Reporter = typeof reporter

export interface IGroupedQueryIds {
pageQueryIds: Array<IGatsbyPage>
staticQueryIds: Array<string>
Expand All @@ -23,6 +26,8 @@ export interface IMutationAction {
}

export interface IBuildContext {
reporter?: Reporter
shouldRunInitialTypegen?: boolean
program: IProgram
store?: Store<IGatsbyState, AnyAction>
parentSpan?: Span
Expand Down

0 comments on commit c9d98a4

Please sign in to comment.