Skip to content

Commit

Permalink
feat(gatsby): Add option to emit TS types during build (#36405)
Browse files Browse the repository at this point in the history
  • Loading branch information
LekoArts committed Aug 18, 2022
1 parent c01806e commit 3760a0e
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 4 deletions.
2 changes: 1 addition & 1 deletion docs/docs/how-to/local-development/graphql-typegen.md
Expand Up @@ -9,7 +9,7 @@ examples:

If you're already using [Gatsby with TypeScript](/docs/how-to/custom-configuration/typescript) and manually typing the results of your queries, you'll learn in this guide how Gatsby's automatic GraphQL Typegen feature can make your life easier. By relying on the types that are generated by Gatsby itself and using autocompletion for GraphQL queries in your IDE you'll be able to write GraphQL queries quicker and safer.

This feature was added in `gatsby@4.15.0`.
This feature was added in `gatsby@4.15.0`. By default, this feature is only generating files during `gatsby develop`.

## Prerequisites

Expand Down
4 changes: 4 additions & 0 deletions docs/docs/reference/config-files/gatsby-config.md
Expand Up @@ -206,6 +206,10 @@ module.exports = {

You can specifiy the path of the generated TypeScript types file relative to the site root. Default: `src/gatsby-types.d.ts`.

### generateOnBuild

By default, `graphqlTypegen` is only run during `gatsby develop`. Set this option to `true` to create the `src/gatsby-types.d.ts` file also during `gatsby build`. Default: `false`.

## polyfill

Gatsby uses the ES6 Promise API. Because some browsers don't support this, Gatsby includes a Promise polyfill by default.
Expand Down
1 change: 1 addition & 0 deletions packages/gatsby/index.d.ts
Expand Up @@ -258,6 +258,7 @@ export const graphql: (query: TemplateStringsArray) => StaticQueryDocument

export interface GraphQLTypegenOptions {
typesOutputPath?: string
generateOnBuild?: boolean
}

/**
Expand Down
37 changes: 37 additions & 0 deletions packages/gatsby/src/commands/build.ts
Expand Up @@ -63,6 +63,7 @@ import {
import { validateEngines } from "../utils/validate-engines"
import { constructConfigObject } from "../utils/gatsby-cloud-config"
import { waitUntilWorkerJobsAreComplete } from "../utils/jobs/worker-messaging"
import { writeTypeScriptTypes } from "../utils/graphql-typegen/ts-codegen"

module.exports = async function build(
program: IBuildArgs,
Expand Down Expand Up @@ -419,6 +420,42 @@ module.exports = async function build(
await waitMaterializePageMode
const waitWorkerPoolEnd = Promise.all(workerPool.end())

// create scope so we don't leak state object
{
const { schema, definitions, config } = store.getState()
const directory = program.directory
const graphqlTypegenOptions = config.graphqlTypegen

// Only generate types when the option is enabled
if (graphqlTypegenOptions && graphqlTypegenOptions.generateOnBuild) {
const typegenActivity = reporter.activityTimer(
`Generating TypeScript types`,
{
parentSpan: buildSpan,
}
)
typegenActivity.start()

try {
await writeTypeScriptTypes(
directory,
schema,
definitions,
graphqlTypegenOptions
)
} catch (err) {
typegenActivity.panicOnBuild({
id: `12100`,
context: {
sourceMessage: err,
},
})
}

typegenActivity.end()
}
}

{
let SSGCount = 0
let DSGCount = 0
Expand Down
22 changes: 21 additions & 1 deletion packages/gatsby/src/joi-schemas/__tests__/joi.ts
Expand Up @@ -186,6 +186,7 @@ describe(`gatsby config`, () => {
expect.objectContaining({
graphqlTypegen: {
typesOutputPath: `src/gatsby-types.d.ts`,
generateOnBuild: false,
},
})
)
Expand All @@ -201,12 +202,12 @@ describe(`gatsby config`, () => {
expect.objectContaining({
graphqlTypegen: {
typesOutputPath: `src/gatsby-types.d.ts`,
generateOnBuild: false,
},
})
)
})

// TODO: Write "return partial defaults for graphqlTypegen when partial options object is set" test with more graphqlTypegen options
it(`graphqlTypegen config object can be overwritten`, () => {
const config = {
graphqlTypegen: {
Expand All @@ -219,6 +220,25 @@ describe(`gatsby config`, () => {
expect.objectContaining({
graphqlTypegen: {
typesOutputPath: `gatsby-types.d.ts`,
generateOnBuild: false,
},
})
)
})

it(`returns partial defaults for graphqlTypegen when partial options object is set`, () => {
const config = {
graphqlTypegen: {
generateOnBuild: true,
},
}

const result = gatsbyConfigSchema.validate(config)
expect(result.value).toEqual(
expect.objectContaining({
graphqlTypegen: {
typesOutputPath: `src/gatsby-types.d.ts`,
generateOnBuild: true,
},
})
)
Expand Down
2 changes: 2 additions & 0 deletions packages/gatsby/src/joi-schemas/joi.ts
Expand Up @@ -61,6 +61,7 @@ export const gatsbyConfigSchema: Joi.ObjectSchema<IGatsbyConfig> = Joi.object()
Joi.object()
.keys({
typesOutputPath: Joi.string().default(DEFAULT_TYPES_OUTPUT_PATH),
generateOnBuild: Joi.boolean().default(false),
})
.unknown(false)
)
Expand All @@ -69,6 +70,7 @@ export const gatsbyConfigSchema: Joi.ObjectSchema<IGatsbyConfig> = Joi.object()
if (value === true) {
return {
typesOutputPath: DEFAULT_TYPES_OUTPUT_PATH,
generateOnBuild: false,
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/gatsby/src/redux/types.ts
Expand Up @@ -80,6 +80,7 @@ export interface IGatsbyFunction {

export interface IGraphQLTypegenOptions {
typesOutputPath: string
generateOnBuild: boolean
}

export interface IGatsbyConfig {
Expand Down
6 changes: 4 additions & 2 deletions packages/gatsby/src/services/initialize.ts
Expand Up @@ -659,10 +659,12 @@ export async function initialize({

const workerPool = WorkerPool.create()

// This is only run during `gatsby develop`
if (state.config.graphqlTypegen) {
telemetry.trackFeatureIsUsed(`GraphQLTypegen`)
writeGraphQLConfig(program)
// This is only run during `gatsby develop`
if (process.env.gatsby_executing_command === `develop`) {
writeGraphQLConfig(program)
}
}

return {
Expand Down

0 comments on commit 3760a0e

Please sign in to comment.