Skip to content

Commit

Permalink
feat: ability to rename root types (#976)
Browse files Browse the repository at this point in the history
Closes #867
  • Loading branch information
tgriesser authored Sep 2, 2021
1 parent 6de1cb6 commit d4c6260
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 3 deletions.
37 changes: 34 additions & 3 deletions src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import {
AllNexusNamedInputTypeDefs,
AllNexusNamedOutputTypeDefs,
AllNexusNamedTypeDefs,
AllNexusOutputTypeDefs,
finalizeWrapping,
isNexusDynamicInputMethod,
isNexusDynamicOutputMethod,
Expand Down Expand Up @@ -283,6 +284,15 @@ export type SchemaConfig = BuilderConfigInput & {
* the values, if it's an array we flatten out the valid types, ignoring invalid ones.
*/
types: any
/**
* If we wish to override the "Root" type for the schema, we can do so by specifying the rootTypes option,
* which will replace the default roots of Query / Mutation / Subscription
*/
schemaRoots?: {
query?: GetGen<'allOutputTypes', string> | AllNexusOutputTypeDefs
mutation?: GetGen<'allOutputTypes', string> | AllNexusOutputTypeDefs
subscription?: GetGen<'allOutputTypes', string> | AllNexusOutputTypeDefs
}
/**
* Whether we should process.exit after the artifacts are generated. Useful if you wish to explicitly
* generate the test artifacts at a certain stage in a startup or build process.
Expand Down Expand Up @@ -1702,9 +1712,30 @@ export interface BuildTypes<TypeMapDefs extends Record<string, GraphQLNamedType>
export function makeSchemaInternal(config: SchemaConfig) {
const builder = new SchemaBuilder(config)
builder.addTypes(config.types)
if (config.schemaRoots) {
builder.addTypes(config.schemaRoots)
}
const { finalConfig, typeMap, missingTypes, schemaExtension, onAfterBuildFns } = builder.getFinalTypeMap()
const { Query, Mutation, Subscription } = typeMap

function getRootType(rootType: 'query' | 'mutation' | 'subscription', defaultType: string) {
const rootTypeVal = config.schemaRoots?.[rootType] ?? defaultType
let returnVal: null | GraphQLNamedType = null
if (typeof rootTypeVal === 'string') {
returnVal = typeMap[rootTypeVal]
} else if (rootTypeVal) {
if (isNexusObjectTypeDef(rootTypeVal)) {
returnVal = typeMap[rootTypeVal.name]
} else if (isObjectType(rootTypeVal)) {
returnVal = typeMap[rootTypeVal.name]
}
}
if (returnVal && !isObjectType(returnVal)) {
throw new Error(`Expected ${rootType} to be a objectType, saw ${returnVal.constructor.name}`)
}
return returnVal
}

/* istanbul ignore next */
if (!isObjectType(Query)) {
throw new Error(`Expected Query to be a objectType, saw ${Query.constructor.name}`)
Expand All @@ -1719,9 +1750,9 @@ export function makeSchemaInternal(config: SchemaConfig) {
}

const schema = new GraphQLSchema({
query: Query,
mutation: Mutation,
subscription: Subscription,
query: getRootType('query', 'Query'),
mutation: getRootType('mutation', 'Mutation'),
subscription: getRootType('subscription', 'Subscription'),
types: objValues(typeMap),
extensions: {
...config.extensions,
Expand Down
56 changes: 56 additions & 0 deletions tests/__snapshots__/builder.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`builder can replace the Mutation root type with an alternate type 1`] = `
"schema {
query: Query
mutation: RootMutation
}
type Mutation {
ok: String
}
type Query {
ok: Boolean!
}
type RootMutation {
name: String
}
"
`;

exports[`builder can replace the Query root type with an alternate type 1`] = `
"schema {
query: RootQuery
}
type Query {
ok: String
}
type RootQuery {
name: String
}
"
`;

exports[`builder can replace the Subscription root type with an alternate type 1`] = `
"schema {
query: Query
subscription: RootSubscription
}
type Query {
ok: Boolean!
}
type RootSubscription {
name: String
}
type Subscription {
ok: String
}
"
`;
76 changes: 76 additions & 0 deletions tests/builder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { lexicographicSortSchema, printSchema } from 'graphql'
import { makeSchema, objectType } from '../src'

describe('builder', () => {
it('can replace the Query root type with an alternate type', () => {
const OtherQuery = objectType({
name: 'RootQuery',
definition(t) {
t.string('name')
},
})

const Query = objectType({
name: 'Query',
definition(t) {
t.string('ok')
},
})

const schema = makeSchema({
types: [OtherQuery, Query],
schemaRoots: {
query: OtherQuery,
},
})
expect(printSchema(lexicographicSortSchema(schema))).toMatchSnapshot()
})

it('can replace the Mutation root type with an alternate type', () => {
const OtherMutation = objectType({
name: 'RootMutation',
definition(t) {
t.string('name')
},
})

const Mutation = objectType({
name: 'Mutation',
definition(t) {
t.string('ok')
},
})

const schema = makeSchema({
types: [OtherMutation, Mutation],
schemaRoots: {
mutation: OtherMutation,
},
})
expect(printSchema(lexicographicSortSchema(schema))).toMatchSnapshot()
})

it('can replace the Subscription root type with an alternate type', () => {
const OtherSubscription = objectType({
name: 'RootSubscription',
definition(t) {
t.string('name')
},
})

const Subscription = objectType({
name: 'Subscription',
definition(t) {
t.string('ok')
},
})

const schema = makeSchema({
types: [OtherSubscription, Subscription],
schemaRoots: {
subscription: OtherSubscription,
},
})
expect(printSchema(lexicographicSortSchema(schema))).toMatchSnapshot()
})
})

0 comments on commit d4c6260

Please sign in to comment.