Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gatsby): Initial GraphQL Typegen Implementation #35487

Merged
merged 36 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7c40b47
first try as internal plugin
LekoArts Apr 19, 2022
028b08d
fix types
LekoArts Apr 19, 2022
3b49391
remove unused stuff
LekoArts Apr 20, 2022
776b143
begin moving to internal
LekoArts Apr 21, 2022
077a863
move more to own state machine
LekoArts Apr 21, 2022
6b677cb
remove internal plugin
LekoArts Apr 22, 2022
6d8c210
have initial creation working
LekoArts Apr 22, 2022
a2a6e46
only strict filter TS types
LekoArts Apr 22, 2022
8aeed25
Merge branch 'master' into poc/typegen
LekoArts Apr 25, 2022
3e76b5d
move stuff around
LekoArts Apr 25, 2022
193a5fb
support gatsby-node.ts in root and local plugins
LekoArts Apr 25, 2022
97678b7
Merge branch 'master' into poc/typegen
LekoArts Apr 25, 2022
91bd469
make it experimental
LekoArts Apr 25, 2022
c0f5889
add schema rebuilding
LekoArts Apr 26, 2022
6f39fc6
use createMachine
LekoArts Apr 26, 2022
46a890c
re-generate types/fragments
LekoArts Apr 26, 2022
92cf7d6
change type
LekoArts Apr 27, 2022
67a4e14
remove unneeded changes
LekoArts Apr 27, 2022
3267cb5
Merge branch 'master' into poc/typegen
LekoArts Apr 27, 2022
59fd0af
tried to fix ts-ignore without success
LekoArts Apr 27, 2022
75bfdcc
better error handling for documents
LekoArts Apr 28, 2022
dbb5423
name queries with param
LekoArts Apr 28, 2022
4d10b8c
Fix third-party fragments
LekoArts Apr 28, 2022
4c8dcff
add e2e test cases
LekoArts Apr 28, 2022
22d640e
linting
LekoArts Apr 28, 2022
d6b02fd
types
LekoArts Apr 28, 2022
5357ba6
review comments
LekoArts Apr 28, 2022
84d1c65
get rid of some of ts-ignores
pieh Apr 28, 2022
5cbcf58
pass required program
LekoArts Apr 28, 2022
257cc2c
Merge branch 'master' into poc/typegen
LekoArts Apr 28, 2022
0e5b13e
review comments
LekoArts May 2, 2022
7d0b681
use noCI for now
LekoArts May 3, 2022
16b133e
forgot env var in e2e test
LekoArts May 3, 2022
5a5cc0b
merge master
LekoArts May 3, 2022
a93a1cd
merge master
LekoArts May 3, 2022
d4d2f37
ward review comments
LekoArts May 3, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions e2e-tests/development-runtime/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,5 @@ cypress/fixtures
cypress/videos

__history__.json

src/gatsby-types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe('fragments.graphql', () => {
it('exists in .cache folder', () => {
cy.readFile('.cache/typegen/fragments.graphql')
})
})
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
})
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe('schema.graphql', () => {
it('exists in .cache folder', () => {
cy.readFile('.cache/typegen/schema.graphql')
})
})
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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",
wardpeet marked this conversation as resolved.
Show resolved Hide resolved
"serve": "gatsby serve",
"clean": "gatsby clean",
"start": "npm run develop",
Expand Down
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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,
LekoArts marked this conversation as resolved.
Show resolved Hide resolved
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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) {
LekoArts marked this conversation as resolved.
Show resolved Hide resolved
writeGraphQLConfig(program)
}

return {
store,
workerPool,
Expand Down
5 changes: 5 additions & 0 deletions packages/gatsby/src/services/types.ts
Original file line number Diff line number Diff line change
@@ -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
Loading