diff --git a/fixtures/merged-root-fields/a.graphql b/fixtures/merged-root-fields/a.graphql index b2d361f..6ec2ae3 100644 --- a/fixtures/merged-root-fields/a.graphql +++ b/fixtures/merged-root-fields/a.graphql @@ -1,4 +1,4 @@ -# import Query.* from 'b.graphql' +# import Query.*, Dummy.* from 'b.graphql' type Query { helloA: String diff --git a/fixtures/merged-root-fields/b.graphql b/fixtures/merged-root-fields/b.graphql index f1d3db5..c580b95 100644 --- a/fixtures/merged-root-fields/b.graphql +++ b/fixtures/merged-root-fields/b.graphql @@ -9,4 +9,8 @@ type Post { input PostFilter { field3: Int +} + +type Dummy { + field2: String } \ No newline at end of file diff --git a/src/definition.ts b/src/definition.ts index e9f2b2a..1766cd9 100644 --- a/src/definition.ts +++ b/src/definition.ts @@ -1,9 +1,6 @@ import { keyBy, uniqBy, includes } from 'lodash' import { - DocumentNode, TypeDefinitionNode, - ObjectTypeDefinitionNode, - InputObjectTypeDefinitionNode, TypeNode, NamedTypeNode, DirectiveNode, diff --git a/src/index.test.ts b/src/index.test.ts index db867f3..a86fa22 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -261,7 +261,7 @@ type C2 { id: ID! } ` - t.is(importSchema(schemaA, schemas), expectedSDL) + t.is(importSchema(schemaA, { schemas }), expectedSDL) }) test(`importSchema: single object schema`, t => { @@ -324,7 +324,7 @@ type C2 { id: ID! } ` - t.is(importSchema(schemaA, schemas), expectedSDL) + t.is(importSchema(schemaA, { schemas }), expectedSDL) }) test(`importSchema: import all mix 'n match 2`, t => { @@ -443,7 +443,7 @@ type C2 { id: ID! } ` - t.is(importSchema(schemaA, schemas), expectedSDL) + t.is(importSchema(schemaA, { schemas }), expectedSDL) }) test('importSchema: scalar', t => { @@ -704,6 +704,31 @@ input PostFilter { t.is(actualSDL, expectedSDL) }) +test('merged custom root fields imports', t => { + const expectedSDL = `\ +type Query { + helloA: String + posts(filter: PostFilter): [Post] + hello: String +} + +type Dummy { + field: String + field2: String +} + +type Post { + field1: String +} + +input PostFilter { + field3: Int +} +` + const actualSDL = importSchema('fixtures/merged-root-fields/a.graphql', { mergeableTypes: ['Dummy'] }) + t.is(actualSDL, expectedSDL) +}) + test('global schema modules', t => { const shared = ` type Shared { @@ -720,7 +745,7 @@ type Shared { first: String } ` - t.is(importSchema('fixtures/global/a.graphql', { shared }), expectedSDL) + t.is(importSchema('fixtures/global/a.graphql', { schemas: { shared } }), expectedSDL) }) test('missing type on type', t => { diff --git a/src/index.ts b/src/index.ts index 0ab3252..1bfedc6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,8 +3,6 @@ import { DefinitionNode, parse, print, - TypeDefinitionNode, - GraphQLObjectType, ObjectTypeDefinitionNode, DocumentNode, Kind, @@ -24,6 +22,14 @@ export interface RawModule { from: string } +/** + * Configuration options that may be passed to `importSchema` + */ +interface ImportSchemaOptions { + schemas?: { [key: string]: string } + mergeableTypes?: [string] +} + const rootFields = ['Query', 'Mutation', 'Subscription'] const read = (schema: string, schemas?: { [key: string]: string }) => { @@ -33,7 +39,7 @@ const read = (schema: string, schemas?: { [key: string]: string }) => { return schemas ? schemas[schema] : schema } -const isFile = f => f.endsWith('.graphql') +const isFile = (f: string) => f.endsWith('.graphql') /** * Parse a single import line and extract imported types and schema filename @@ -77,13 +83,20 @@ export function parseSDL(sdl: string): RawModule[] { /** * Main entry point. Recursively process all import statement in a schema * - * @param filePath File path to the initial schema file + * @see https://oss.prisma.io/content/graphql-import/overview#description + * @param schema File path to the initial schema file + * @param options Import configuration options + * @param options.schemas An object of schemas as strings + * @param options.mergeableTypes An array of custom GraphQL types that will + * be treated as [root fields]{@link https://oss.prisma.io/content/graphql-import/overview#import-root-fields} * @returns Single bundled schema with all imported types */ export function importSchema( schema: string, - schemas?: { [key: string]: string }, + options: ImportSchemaOptions = {}, ): string { + const { schemas, mergeableTypes = [] } = options + const allMergeableTypes = [...mergeableTypes, ...rootFields] const sdl = read(schema, schemas) || schema let document = getDocumentFromSDL(sdl) @@ -96,14 +109,15 @@ export function importSchema( ) // Post processing of the final schema (missing types, unused types, etc.) - // Query, Mutation and Subscription should be merged + // Query, Mutation, Subscription and any custom type defined in `mergeableTypes` + // should be merged // And should always be in the first set, to make sure they // are not filtered out. const firstTypes = flatten(typeDefinitions).filter(d => - includes(rootFields, d.name.value), + includes(allMergeableTypes, d.name.value), ) const otherFirstTypes = typeDefinitions[0].filter( - d => !includes(rootFields, d.name.value), + d => !includes(allMergeableTypes, d.name.value), ) const firstSet = firstTypes.concat(otherFirstTypes) const processedTypeNames = []