From 79c4842803765bc6ec41a2a4c80d0d2ebc1554f0 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Tue, 24 Dec 2019 20:33:22 -0500 Subject: [PATCH 1/8] Improvements for loaders --- packages/common/src/index.ts | 2 + packages/common/src/parse-graphql-json.ts | 43 ++++++++++++++ packages/common/src/parse-graphql-sdl.ts | 22 +++++++ packages/core/src/import-parser/index.ts | 23 +++++++- packages/loaders/git/src/index.ts | 28 ++++----- packages/loaders/github/src/index.ts | 24 +++----- packages/loaders/graphql-file/src/index.ts | 54 ++++++++--------- packages/loaders/json-file/src/index.ts | 69 ++++++++++------------ 8 files changed, 164 insertions(+), 101 deletions(-) create mode 100644 packages/common/src/parse-graphql-json.ts create mode 100644 packages/common/src/parse-graphql-sdl.ts diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 238bd5ac..40f8d2ef 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -14,3 +14,5 @@ export * from './get-fields-with-directives'; export * from './validate-documents'; export * from './resolvers-composition'; export * from './fix-schema-ast'; +export * from './parse-graphql-json'; +export * from './parse-graphql-sdl'; diff --git a/packages/common/src/parse-graphql-json.ts b/packages/common/src/parse-graphql-json.ts new file mode 100644 index 00000000..b68fe0eb --- /dev/null +++ b/packages/common/src/parse-graphql-json.ts @@ -0,0 +1,43 @@ +import { Source as GraphQLSource, buildClientSchema, parse, ParseOptions } from 'graphql'; +import { printSchemaWithDirectives, Source } from '.'; +import { GraphQLSchemaValidationOptions } from 'graphql/type/schema'; + +function stripBOM(content: string): string { + content = content.toString(); + // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + // because the buffer-to-string conversion in `fs.readFileSync()` + // translates it to FEFF, the UTF-16 BOM. + if (content.charCodeAt(0) === 0xfeff) { + content = content.slice(1); + } + + return content; +} + +function parseBOM(content: string): any { + return JSON.parse(stripBOM(content)); +} + +export function parseGraphQLJSON(location: string, jsonContent: string, options: ParseOptions & GraphQLSchemaValidationOptions): Source { + let parsedJson = parseBOM(jsonContent); + + if (parsedJson['data']) { + parsedJson = parsedJson['data']; + } + + if (parsedJson.kind === 'Document') { + const document = parsedJson; + return { + location, + document, + }; + } else if (parsedJson.__schema) { + const schema = buildClientSchema(parsedJson, options); + return { + location, + document: parse(printSchemaWithDirectives(schema), options), + schema, + }; + } + throw new Error(`Not valid JSON content`); +} diff --git a/packages/common/src/parse-graphql-sdl.ts b/packages/common/src/parse-graphql-sdl.ts new file mode 100644 index 00000000..c555af81 --- /dev/null +++ b/packages/common/src/parse-graphql-sdl.ts @@ -0,0 +1,22 @@ +import { ParseOptions, DocumentNode, parse, Kind, Source as GraphQLSource } from 'graphql'; + +export function parseGraphQLSDL(location: string, rawSDL: string, options: ParseOptions) { + let document: DocumentNode; + try { + document = parse(new GraphQLSource(rawSDL, location), options); + } catch (e) { + if (e.message.includes('EOF')) { + document = { + kind: Kind.DOCUMENT, + definitions: [], + }; + } else { + throw e; + } + } + return { + location, + document, + rawSDL, + }; +} diff --git a/packages/core/src/import-parser/index.ts b/packages/core/src/import-parser/index.ts index 16b4a442..d23d6c6a 100644 --- a/packages/core/src/import-parser/index.ts +++ b/packages/core/src/import-parser/index.ts @@ -7,8 +7,8 @@ import { LoadSchemaOptions } from '../schema'; import { completeDefinitionPool, ValidDefinitionNode } from './definition'; import { Loader } from '@graphql-toolkit/common'; import { OPERATION_KINDS } from '../documents'; +import { resolve, dirname, join } from 'path'; import { realpathSync } from 'fs'; -import { join, dirname, resolve } from 'path'; /** * Describes the information from a single import line @@ -156,7 +156,26 @@ function resolveModuleFilePath(filePath: string, importFrom: string): string { return realpathSync(join(dirName, importFrom)); } catch (e) { if (e.code === 'ENOENT') { - return resolveFrom(dirName, importFrom); + const addedExtensions = new Array(); + for (const graphqlFileExtension of ['.gql', '.gqls', '.graphql', '.graphqls']) { + if (!(graphqlFileExtension in require.extensions)) { + require.extensions[graphqlFileExtension] = () => ({}); + addedExtensions.push(graphqlFileExtension); + } + } + function cleanRequireExtensions() { + for (const extension of addedExtensions) { + delete require.extensions[extension]; + } + } + try { + const resolvedPath = resolveFrom(dirName, importFrom); + cleanRequireExtensions(); + return resolvedPath; + } catch (e) { + cleanRequireExtensions(); + throw e; + } } } } diff --git a/packages/loaders/git/src/index.ts b/packages/loaders/git/src/index.ts index 18e6e3b6..1f968598 100644 --- a/packages/loaders/git/src/index.ts +++ b/packages/loaders/git/src/index.ts @@ -1,6 +1,7 @@ -import { buildClientSchema, printSchema, parse, DocumentNode } from 'graphql'; -import { UniversalLoader } from '@graphql-toolkit/common'; +import { buildClientSchema, printSchema, parse, DocumentNode, Source as GraphQLSource, Kind, ParseOptions } from 'graphql'; +import { UniversalLoader, parseGraphQLSDL, parseGraphQLJSON } from '@graphql-toolkit/common'; import simplegit from 'simple-git/promise'; +import { GraphQLSchemaValidationOptions } from 'graphql/type/schema'; // git:branch:path/to/file function extractData( @@ -21,6 +22,8 @@ function extractData( }; } +export type GitLoaderOptions = ParseOptions & GraphQLSchemaValidationOptions; + export class GitLoader implements UniversalLoader { loaderId() { return 'git-loader'; @@ -28,35 +31,26 @@ export class GitLoader implements UniversalLoader { async canLoad(pointer: string) { return typeof pointer === 'string' && pointer.toLowerCase().startsWith('git:'); } - async load(pointer: string) { + async load(pointer: string, options: GitLoaderOptions) { const { ref, path } = extractData(pointer); const git = simplegit(); - let schemaString: string; + let content: string; try { - schemaString = await git.show([`${ref}:${path}`]); + content = await git.show([`${ref}:${path}`]); } catch (error) { throw new Error('Unable to load schema from git: ' + error); } - let document: DocumentNode; - if (/\.(gql|graphql)s?$/i.test(path)) { - document = parse(schemaString); + return parseGraphQLSDL(pointer, content, options); } if (/\.json$/i.test(path)) { - document = parse(printSchema(buildClientSchema(JSON.parse(schemaString)))); - } - - if (!document) { - throw new Error('Unable to build schema from git'); + return parseGraphQLJSON(pointer, content, options); } - return { - location: pointer, - document, - }; + throw new Error(`Invalid file extension: ${path}`); } } diff --git a/packages/loaders/github/src/index.ts b/packages/loaders/github/src/index.ts index b0e35fcd..aff64c10 100644 --- a/packages/loaders/github/src/index.ts +++ b/packages/loaders/github/src/index.ts @@ -1,6 +1,7 @@ -import { buildClientSchema, printSchema, parse, DocumentNode } from 'graphql'; -import { UniversalLoader } from '@graphql-toolkit/common'; +import { buildClientSchema, printSchema, parse, DocumentNode, ParseOptions } from 'graphql'; +import { UniversalLoader, parseGraphQLSDL, parseGraphQLJSON } from '@graphql-toolkit/common'; import { fetch } from 'cross-fetch'; +import { GraphQLSchemaValidationOptions } from 'graphql/type/schema'; // github:owner/name#ref:path/to/file function extractData( @@ -23,7 +24,7 @@ function extractData( }; } -export interface GithubLoaderOptions { +export interface GithubLoaderOptions extends ParseOptions, GraphQLSchemaValidationOptions { token: string; } @@ -76,25 +77,16 @@ export class GithubLoader implements UniversalLoader { throw new Error('Unable to download schema from github: ' + errorMessage); } - const schemaString = response.data.repository.object.text; - - let document: DocumentNode; + const content = response.data.repository.object.text; if (/\.(gql|graphql)s?$/i.test(path)) { - document = parse(schemaString); + return parseGraphQLSDL(pointer, content, options); } if (/\.json$/i.test(path)) { - document = parse(printSchema(buildClientSchema(JSON.parse(schemaString)))); - } - - if (!document) { - throw new Error('Unable to build schema from GitHub'); + return parseGraphQLJSON(pointer, content, options); } - return { - location: pointer, - document, - }; + throw new Error(`Invalid file extension: ${path}`); } } diff --git a/packages/loaders/graphql-file/src/index.ts b/packages/loaders/graphql-file/src/index.ts index 8e983126..528ce47e 100644 --- a/packages/loaders/graphql-file/src/index.ts +++ b/packages/loaders/graphql-file/src/index.ts @@ -1,12 +1,33 @@ import { Source, UniversalLoader, DocumentPointerSingle, SchemaPointerSingle, isValidPath } from '@graphql-toolkit/common'; -import { parse, Source as GraphQLSource, Kind } from 'graphql'; +import { parse, Source as GraphQLSource, Kind, DocumentNode, ParseOptions } from 'graphql'; import { extname, isAbsolute, resolve } from 'path'; import { readFileSync, existsSync } from 'fs'; -export type GraphQLFileLoaderOptions = { skipGraphQLImport?: boolean; cwd?: string }; +export type GraphQLFileLoaderOptions = { skipGraphQLImport?: boolean; cwd?: string } & ParseOptions; const GQL_EXTENSIONS = ['.gql', '.graphql', '.graphqls']; +export function parseGraphQLSDL(location: string, rawSDL: string, options: ParseOptions) { + let document: DocumentNode; + try { + document = parse(new GraphQLSource(rawSDL, location), options); + } catch (e) { + if (e.message.includes('EOF')) { + document = { + kind: Kind.DOCUMENT, + definitions: [], + }; + } else { + throw e; + } + } + return { + location, + document, + rawSDL, + }; +} + export class GraphQLFileLoader implements UniversalLoader { loaderId(): string { return 'graphql-file'; @@ -28,33 +49,8 @@ export class GraphQLFileLoader implements UniversalLoader { const normalizedFilePath = isAbsolute(pointer) ? pointer : resolve(options.cwd || process.cwd(), pointer); - const content = readFileSync(normalizedFilePath, 'utf-8').trim(); - - if (content && content !== '') { - if (!options.skipGraphQLImport && /^\#.*import /i.test(content.trimLeft())) { - return { - location: pointer, - get document() { - try { - return parse(new GraphQLSource(content, pointer)); - } catch (e) { - return { - kind: Kind.DOCUMENT, - definitions: [], - }; - } - }, - rawSDL: content, - }; - } else { - return { - location: pointer, - document: parse(new GraphQLSource(content, pointer)), - rawSDL: content, - }; - } - } + const rawSDL = readFileSync(normalizedFilePath, 'utf-8').trim(); - return null; + return parseGraphQLSDL(pointer, rawSDL, options); } } diff --git a/packages/loaders/json-file/src/index.ts b/packages/loaders/json-file/src/index.ts index 57c21ece..7fb16683 100644 --- a/packages/loaders/json-file/src/index.ts +++ b/packages/loaders/json-file/src/index.ts @@ -15,10 +15,34 @@ function stripBOM(content: string): string { return content; } -function parseBOM(content: string): IntrospectionQuery { +function parseBOM(content: string): any { return JSON.parse(stripBOM(content)); } +export function parseGraphQLJSON(pointer: string, jsonContent: string): Source { + let parsedJson = parseBOM(jsonContent); + + if (parsedJson['data']) { + parsedJson = parsedJson['data']; + } + + if (parsedJson.kind === 'Document') { + const document = parsedJson; + return { + location: pointer, + document, + }; + } else if (parsedJson.__schema) { + const schema = buildClientSchema(parsedJson, options as any); + return { + location: pointer, + document: parse(printSchemaWithDirectives(schema)), + schema, + }; + } + throw new Error(`Not valid content`); +} + export interface JsonFileLoaderOptions { cwd?: string; } @@ -43,42 +67,13 @@ export class JsonFileLoader implements DocumentLoader { } async load(pointer: SchemaPointerSingle, options: JsonFileLoaderOptions): Promise { - return new Promise((resolve, reject) => { - const normalizedFilepath = isAbsolute(pointer) ? pointer : resolvePath(options.cwd || process.cwd(), pointer); - - if (existsSync(normalizedFilepath)) { - try { - const fileContent = readFileSync(normalizedFilepath, 'utf8'); - - if (!fileContent) { - reject(`Unable to read local introspection file: ${normalizedFilepath}`); - } + const normalizedFilepath = isAbsolute(pointer) ? pointer : resolvePath(options.cwd || process.cwd(), pointer); - let introspection = parseBOM(fileContent); - - if (introspection['data']) { - introspection = introspection['data'] as IntrospectionQuery; - } - - if (!introspection.__schema) { - throw new Error('Invalid schema provided!'); - } - - const schema = buildClientSchema(introspection, options as any); - - resolve({ - location: pointer, - get document() { - return parse(printSchemaWithDirectives(schema)); - }, - schema, - }); - } catch (e) { - reject(e); - } - } else { - reject(`Unable to locate local introspection file: ${normalizedFilepath}`); - } - }); + try { + const jsonContent = readFileSync(normalizedFilepath, 'utf8'); + return parseGraphQLJSON(pointer, jsonContent); + } catch (e) { + throw new Error(`Unable to read JSON file: ${normalizedFilepath}`); + } } } From a21306c8111a7b9d21b029d771b36295706dd1dd Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Wed, 25 Dec 2019 03:36:02 -0500 Subject: [PATCH 2/8] WIP --- packages/common/src/loaders.ts | 25 +- packages/core/src/documents.ts | 8 +- packages/core/src/import-parser/index.ts | 196 ++----------- packages/core/src/load-typedefs.ts | 263 +++++++++--------- packages/core/src/schema.ts | 10 +- .../tests/__mocks__/cross-fetch.js | 0 .../tests/__mocks__/fs.js | 0 .../documents/documents-from-glob.spec.ts | 40 ++- .../documents/test-files/1.query.graphql | 0 .../loaders/documents/test-files/2.graphql | 0 .../documents/test-files/invalid-doc.graphql | 0 .../loaders/documents/test-files/tags.js | 0 .../documents/test-files/test.empty.graphql | 0 .../schema/fixtures/circular/a.graphql | 0 .../schema/fixtures/circular/b.graphql | 0 .../schema/fixtures/circular/c.graphql | 0 .../schema/fixtures/collision/a.graphql | 0 .../schema/fixtures/collision/b.graphql | 0 .../loaders/schema/fixtures/complex/a.graphql | 0 .../loaders/schema/fixtures/complex/b.graphql | 0 .../schema/fixtures/directive/a.graphql | 0 .../schema/fixtures/directive/b.graphql | 0 .../schema/fixtures/directive/c.graphql | 0 .../schema/fixtures/directive/d.graphql | 0 .../schema/fixtures/directive/e.graphql | 0 .../schema/fixtures/directive/f.graphql | 0 .../schema/fixtures/directive/g.graphql | 0 .../loaders/schema/fixtures/enums/a.graphql | 0 .../loaders/schema/fixtures/enums/b.graphql | 0 .../schema/fixtures/field-types/a.graphql | 0 .../schema/fixtures/field-types/b.graphql | 0 .../schema/fixtures/field-types/c.graphql | 0 .../loaders/schema/fixtures/global/a.graphql | 0 .../schema/fixtures/import-all/a.graphql | 0 .../schema/fixtures/import-all/b.graphql | 0 .../schema/fixtures/import-all/c.graphql | 0 .../fixtures/import-duplicate/a.graphql | 0 .../fixtures/import-duplicate/all.graphql | 0 .../loaders/schema/fixtures/import-gql/a.gql | 0 .../schema/fixtures/import-module/a.graphql | 0 .../schema/fixtures/import-nested/a.graphql | 0 .../schema/fixtures/import-nested/all.graphql | 0 .../schema/fixtures/import-nested/b.graphql | 0 .../schema/fixtures/import-nested/c.graphql | 0 .../schema/fixtures/imports-only/a.graphql | 0 .../schema/fixtures/imports-only/all.graphql | 0 .../schema/fixtures/imports-only/b.graphql | 0 .../schema/fixtures/input-types/a.graphql | 0 .../schema/fixtures/input-types/b.graphql | 0 .../schema/fixtures/input-types/c.graphql | 0 .../interfaces-implements-many/a.graphql | 0 .../interfaces-implements-many/b.graphql | 0 .../fixtures/interfaces-implements/a.graphql | 0 .../fixtures/interfaces-implements/b.graphql | 0 .../schema/fixtures/interfaces-many/a.graphql | 0 .../schema/fixtures/interfaces-many/b.graphql | 0 .../schema/fixtures/interfaces-many/c.graphql | 0 .../schema/fixtures/interfaces-many/d.graphql | 0 .../schema/fixtures/interfaces/a.graphql | 0 .../schema/fixtures/interfaces/b.graphql | 0 .../schema/fixtures/interfaces/c.graphql | 0 .../fixtures/merged-root-fields/a.graphql | 0 .../fixtures/merged-root-fields/b.graphql | 0 .../schema/fixtures/related-types/a.graphql | 0 .../schema/fixtures/related-types/b.graphql | 0 .../relative-paths/database/schema.graphql | 0 .../relative-paths/src/schema.graphql | 0 .../schema/fixtures/root-fields/a.graphql | 0 .../schema/fixtures/root-fields/b.graphql | 0 .../schema/fixtures/root-fields/c.graphql | 0 .../schema/fixtures/root-fields/d.graphql | 0 .../schema/fixtures/root-fields/e.graphql | 0 .../loaders/schema/fixtures/scalar/a.graphql | 0 .../loaders/schema/fixtures/scalar/b.graphql | 0 .../schema/fixtures/type-not-found/a.graphql | 0 .../schema/fixtures/type-not-found/b.graphql | 0 .../schema/fixtures/type-not-found/c.graphql | 0 .../schema/fixtures/type-not-found/d.graphql | 0 .../schema/fixtures/type-not-found/e.graphql | 0 .../schema/fixtures/type-not-found/f.graphql | 0 .../schema/fixtures/type-not-found/g.graphql | 0 .../loaders/schema/fixtures/unions/a.graphql | 0 .../loaders/schema/fixtures/unions/b.graphql | 0 .../loaders/schema/fixtures/unions/c.graphql | 0 .../loaders/schema/import-schema.spec.ts | 39 ++- .../tests/loaders/schema/integration.spec.ts | 16 +- .../loaders/schema/schema-from-export.spec.ts | 35 ++- .../schema/schema-from-typedefs.spec.ts | 44 ++- .../tests/loaders/schema/test-files/1.ts | 0 .../tests/loaders/schema/test-files/10.tsx | 0 .../tests/loaders/schema/test-files/11.ts | 0 .../tests/loaders/schema/test-files/12.tsx | 0 .../tests/loaders/schema/test-files/13.tsx | 0 .../tests/loaders/schema/test-files/14.js | 0 .../tests/loaders/schema/test-files/15.js | 0 .../tests/loaders/schema/test-files/16.ts | 0 .../tests/loaders/schema/test-files/2.ts | 0 .../tests/loaders/schema/test-files/3.graphql | 0 .../tests/loaders/schema/test-files/4.ts | 0 .../tests/loaders/schema/test-files/5.tsx | 0 .../tests/loaders/schema/test-files/6.ts | 0 .../tests/loaders/schema/test-files/7.ts | 0 .../tests/loaders/schema/test-files/8.ts | 0 .../tests/loaders/schema/test-files/9.ts | 0 .../schema/test-files/ByteOrderMask.json | 0 .../tests/loaders/schema/test-files/error.ts | 0 .../extensions/export-schema-with-def.js | 0 .../schema-dir/extensions/export-schema.js | 0 .../extensions/extend-query.graphql | 0 .../extensions/schema-with-extend.graphql | 0 .../schema-dir/extensions/type-defs.js | 0 .../test-files/schema-dir/query.graphql | 0 .../schema/test-files/schema-dir/schema.ts | 0 .../test-files/schema-dir/test.empty.graphql | 0 .../schema-dir/test.non-schema.graphql | 0 .../test-files/schema-dir/type-defs/custom.ts | 0 .../test-files/schema-dir/type-defs/gatsby.ts | 0 .../schema-dir/type-defs/graphql-tag.ts | 0 .../schema/test-files/schema-dir/user.graphql | 0 packages/graphql-toolkit/.gitignore | 72 ----- packages/graphql-toolkit/.npmignore | 13 - packages/graphql-toolkit/package.json | 50 ---- packages/graphql-toolkit/src/index.ts | 38 --- packages/graphql-toolkit/tsconfig.json | 23 -- packages/loaders/apollo-engine/src/index.ts | 11 +- packages/loaders/code-file/src/index.ts | 63 ++--- packages/loaders/git/src/index.ts | 8 +- packages/loaders/github/src/index.ts | 6 +- packages/loaders/graphql-file/src/index.ts | 35 +-- packages/loaders/json-file/src/index.ts | 53 +--- packages/loaders/module/src/index.ts | 4 +- packages/loaders/url/src/index.ts | 10 +- 132 files changed, 348 insertions(+), 714 deletions(-) rename packages/{graphql-toolkit => core}/tests/__mocks__/cross-fetch.js (100%) rename packages/{graphql-toolkit => core}/tests/__mocks__/fs.js (100%) rename packages/{graphql-toolkit => core}/tests/loaders/documents/documents-from-glob.spec.ts (70%) rename packages/{graphql-toolkit => core}/tests/loaders/documents/test-files/1.query.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/documents/test-files/2.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/documents/test-files/invalid-doc.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/documents/test-files/tags.js (100%) rename packages/{graphql-toolkit => core}/tests/loaders/documents/test-files/test.empty.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/circular/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/circular/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/circular/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/collision/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/collision/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/complex/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/complex/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/directive/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/directive/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/directive/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/directive/d.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/directive/e.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/directive/f.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/directive/g.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/enums/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/enums/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/field-types/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/field-types/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/field-types/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/global/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-all/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-all/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-all/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-duplicate/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-duplicate/all.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-gql/a.gql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-module/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-nested/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-nested/all.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-nested/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/import-nested/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/imports-only/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/imports-only/all.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/imports-only/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/input-types/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/input-types/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/input-types/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces-implements-many/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces-implements-many/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces-implements/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces-implements/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces-many/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces-many/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces-many/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces-many/d.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/interfaces/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/merged-root-fields/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/merged-root-fields/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/related-types/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/related-types/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/relative-paths/database/schema.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/relative-paths/src/schema.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/root-fields/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/root-fields/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/root-fields/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/root-fields/d.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/root-fields/e.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/scalar/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/scalar/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/type-not-found/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/type-not-found/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/type-not-found/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/type-not-found/d.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/type-not-found/e.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/type-not-found/f.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/type-not-found/g.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/unions/a.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/unions/b.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/fixtures/unions/c.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/import-schema.spec.ts (92%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/integration.spec.ts (63%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/schema-from-export.spec.ts (71%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/schema-from-typedefs.spec.ts (73%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/1.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/10.tsx (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/11.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/12.tsx (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/13.tsx (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/14.js (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/15.js (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/16.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/2.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/3.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/4.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/5.tsx (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/6.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/7.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/8.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/9.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/ByteOrderMask.json (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/error.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/extensions/export-schema-with-def.js (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/extensions/export-schema.js (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/extensions/extend-query.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/extensions/schema-with-extend.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/extensions/type-defs.js (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/query.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/schema.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/test.empty.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/test.non-schema.graphql (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/type-defs/custom.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/type-defs/gatsby.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/type-defs/graphql-tag.ts (100%) rename packages/{graphql-toolkit => core}/tests/loaders/schema/test-files/schema-dir/user.graphql (100%) delete mode 100644 packages/graphql-toolkit/.gitignore delete mode 100644 packages/graphql-toolkit/.npmignore delete mode 100644 packages/graphql-toolkit/package.json delete mode 100644 packages/graphql-toolkit/src/index.ts delete mode 100644 packages/graphql-toolkit/tsconfig.json diff --git a/packages/common/src/loaders.ts b/packages/common/src/loaders.ts index 2c4cbb39..b5cc3933 100644 --- a/packages/common/src/loaders.ts +++ b/packages/common/src/loaders.ts @@ -1,13 +1,24 @@ -import { DocumentNode, GraphQLSchema } from 'graphql'; +import { DocumentNode, GraphQLSchema, ParseOptions, BuildSchemaOptions } from 'graphql'; +import { GraphQLSchemaValidationOptions } from 'graphql/type/schema'; export declare class Source { - document: DocumentNode; + document?: DocumentNode; schema?: GraphQLSchema; rawSDL?: string; location?: string; - constructor({ document, location, schema }: { document: DocumentNode; location?: string; schema?: GraphQLSchema }); + constructor({ document, location, schema }: { document?: DocumentNode; location?: string; schema?: GraphQLSchema }); } +export type SingleFileOptions = ParseOptions & + GraphQLSchemaValidationOptions & + BuildSchemaOptions & { + noRequire?: boolean; + cache?: { [key: string]: Source }; + loaders: Loader[]; + filterKinds?: string[]; + cwd?: string; + }; + export type WithList = T | T[]; export type ElementOf = TList extends Array ? TElement : never; export type SchemaPointer = WithList; @@ -16,12 +27,12 @@ export type DocumentGlobPathPointer = string; export type DocumentPointer = WithList; export type DocumentPointerSingle = ElementOf; -export interface Loader { +export interface Loader { loaderId(): string; canLoad(pointer: TPointer, options?: TOptions): Promise; load(pointer: TPointer, options?: TOptions): Promise; } -export type SchemaLoader = Loader; -export type DocumentLoader = Loader; -export type UniversalLoader = Loader; +export type SchemaLoader = Loader; +export type DocumentLoader = Loader; +export type UniversalLoader = Loader; diff --git a/packages/core/src/documents.ts b/packages/core/src/documents.ts index 9faf9a05..51f0cf77 100644 --- a/packages/core/src/documents.ts +++ b/packages/core/src/documents.ts @@ -1,12 +1,12 @@ -import { Loader, Source } from '@graphql-toolkit/common'; +import { Source } from '@graphql-toolkit/common'; import { Kind } from 'graphql'; -import { LoadTypedefsOptions, loadTypedefsUsingLoaders, UnnormalizedTypeDefPointer } from './load-typedefs'; +import { LoadTypedefsOptions, loadTypedefs, UnnormalizedTypeDefPointer } from './load-typedefs'; export const OPERATION_KINDS = [Kind.OPERATION_DEFINITION, Kind.FRAGMENT_DEFINITION]; export const NON_OPERATION_KINDS = Object.keys(Kind) .reduce((prev, v) => [...prev, Kind[v]], []) .filter(v => !OPERATION_KINDS.includes(v)); -export async function loadDocumentsUsingLoaders(loaders: Loader[], documentDef: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[], options: LoadTypedefsOptions = {}, cwd = process.cwd()): Promise { - return await loadTypedefsUsingLoaders(loaders, documentDef, { ...options, skipGraphQLImport: true, noRequire: true }, NON_OPERATION_KINDS, cwd); +export function loadDocuments(documentDef: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[], options: LoadTypedefsOptions): Promise { + return loadTypedefs(documentDef, { noRequire: true, filterKinds: NON_OPERATION_KINDS, ...options }); } diff --git a/packages/core/src/import-parser/index.ts b/packages/core/src/import-parser/index.ts index d23d6c6a..d2870fab 100644 --- a/packages/core/src/import-parser/index.ts +++ b/packages/core/src/import-parser/index.ts @@ -1,13 +1,9 @@ -import { DefinitionNode, parse, print, ObjectTypeDefinitionNode, DocumentNode, Kind } from 'graphql'; -import { flatten, groupBy, includes, keyBy, isEqual, uniqBy } from 'lodash'; +import { DefinitionNode } from 'graphql'; +import { groupBy, includes } from 'lodash'; import resolveFrom from 'resolve-from'; -import { loadTypedefsUsingLoaders } from '../load-typedefs'; -import { LoadSchemaOptions } from '../schema'; -import { completeDefinitionPool, ValidDefinitionNode } from './definition'; -import { Loader } from '@graphql-toolkit/common'; -import { OPERATION_KINDS } from '../documents'; -import { resolve, dirname, join } from 'path'; +import { ValidDefinitionNode } from './definition'; +import { dirname, join } from 'path'; import { realpathSync } from 'fs'; /** @@ -19,8 +15,6 @@ export interface RawModule { from: string; } -const rootFields = ['Query', 'Mutation', 'Subscription']; - const gqlExt = /\.g(raph)?ql$/; function isGraphQLFile(f: string) { return gqlExt.test(f); @@ -64,75 +58,13 @@ export function parseSDL(sdl: string): RawModule[] { .map(parseImportLine); } -/** - * Main entry point. Recursively process all import statement in a schema - * - * @param filePath File path to the initial schema file - * @returns Single bundled schema with all imported types - */ -export async function processImportSyntax(schemaPointer: string, sdl: string, loaders: Loader[], options?: LoadSchemaOptions, cwd = process.cwd()): Promise { - const mergeableTypes = options.mergeableTypes || []; - const allMergeableTypes = [...mergeableTypes, ...rootFields]; - let document = getDocumentFromSDL(sdl); - - // Recursively process the imports, starting by importing all types from the initial schema - let { allDefinitions, typeDefinitions } = await collectDefinitions(['*'], sdl, schemaPointer, loaders, options, cwd); - - // Post processing of the final schema (missing types, unused types, etc.) - // Query, Mutation and Subscription 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(allMergeableTypes, d.name.value)); - const secondFirstTypes = typeDefinitions[0].filter(d => !includes(allMergeableTypes, d.name.value)); - const otherFirstTypes = flatten(typeDefinitions.slice(1)).filter(d => !includes(allMergeableTypes, d.name.value)); - - const firstSet = firstTypes.concat(secondFirstTypes, otherFirstTypes); - const processedTypeNames = []; - const mergedFirstTypes = []; - for (const type of firstSet) { - if (!includes(processedTypeNames, type.name.value)) { - processedTypeNames.push(type.name.value); - mergedFirstTypes.push(type); - } else { - const existingType = mergedFirstTypes.find(t => t.name.value === type.name.value) as any; - - existingType.fields = uniqBy(existingType.fields.concat((type as ObjectTypeDefinitionNode).fields), 'name.value'); - } - } - - document = { - ...document, - definitions: completeDefinitionPool(flatten(allDefinitions), firstSet, flatten(typeDefinitions)), - }; - // Return the schema - return document; -} - -/** - * Parses a schema into a graphql DocumentNode. - * If the schema is empty a DocumentNode with empty definitions will be created. - * - * @param sdl Schema to parse - * @returns A graphql DocumentNode with definitions of the parsed sdl. - */ -function getDocumentFromSDL(sdl: string): DocumentNode { - if (isEmptySDL(sdl)) { - return { - kind: Kind.DOCUMENT, - definitions: [], - }; - } else { - return parse(sdl, { noLocation: true }); - } -} - /** * Check if a schema contains any type definitions at all. * * @param sdl Schema to parse * @returns True if SDL only contains comments and/or whitespaces */ -function isEmptySDL(sdl: string): boolean { +export function isEmptySDL(sdl: string): boolean { return ( sdl .split('\n') @@ -149,7 +81,7 @@ function isEmptySDL(sdl: string): boolean { * @param importFrom Path given for the import * @returns Full resolved path to a file */ -function resolveModuleFilePath(filePath: string, importFrom: string): string { +export function resolveModuleFilePath(filePath: string, importFrom: string): string { const dirName = dirname(filePath); if (isGraphQLFile(filePath) && isGraphQLFile(importFrom)) { try { @@ -183,86 +115,6 @@ function resolveModuleFilePath(filePath: string, importFrom: string): string { return importFrom; } -/** - * Recursively process all schema files. Keeps track of both the filtered - * type definitions, and all type definitions, because they might be needed - * in post-processing (to add missing types) - * - * @param imports Types specified in the import statement - * @param sdl Current schema - * @param filePath File location for current schema - * @param Tracking of processed schemas (for circular dependencies) - * @param Tracking of imported type definitions per schema - * @param Tracking of all type definitions per schema - * @returns Both the collection of all type definitions, and the collection of imported type definitions - */ -async function collectDefinitions( - imports: string[], - sdl: string, - schemaPointer: string, - loaders: Loader[], - options?: LoadSchemaOptions, - cwd = process.cwd(), - processedFiles: Map = new Map(), - typeDefinitions: ValidDefinitionNode[][] = [], - allDefinitions: ValidDefinitionNode[][] = [] -): Promise<{ - allDefinitions: ValidDefinitionNode[][]; - typeDefinitions: ValidDefinitionNode[][]; -}> { - const key = isGraphQLFile(schemaPointer) ? resolve(schemaPointer) : schemaPointer; - - // Get TypeDefinitionNodes from current schema - const document = getDocumentFromSDL(sdl); - - // Add all definitions to running total - allDefinitions.push(filterTypeDefinitions(document.definitions)); - - // Filter TypeDefinitionNodes by type and defined imports - const currentTypeDefinitions = filterImportedDefinitions(imports, document.definitions, allDefinitions); - - // Add typedefinitions to running total - typeDefinitions.push(currentTypeDefinitions); - - // Read imports from current file - const rawModules = parseSDL(sdl); - - // Process each file (recursively) - await Promise.all( - rawModules.map(async m => { - // If it was not yet processed (in case of circular dependencies) - const moduleFilePath = resolveModuleFilePath(schemaPointer, m.from); - - const processedFile = processedFiles.get(key); - if (!processedFile || !processedFile.find(rModule => isEqual(rModule, m))) { - // Mark this specific import line as processed for this file (for cicular dependency cases) - processedFiles.set(key, processedFile ? processedFile.concat(m) : [m]); - const results = await loadTypedefsUsingLoaders( - loaders, - moduleFilePath, - { - ...options, - skipGraphQLImport: true, - forceRawSDL: true, - forceGraphQLImport: false, - }, - OPERATION_KINDS, - cwd - ); - await Promise.all( - results.map(async result => { - const rawSDL = result.rawSDL || print(result.document); - await collectDefinitions(m.imports, rawSDL, moduleFilePath, loaders, options, cwd, processedFiles, typeDefinitions, allDefinitions); - }) - ); - } - }) - ); - - // Return the maps of type definitions from each file - return { allDefinitions, typeDefinitions }; -} - /** * Filter the types loaded from a schema, first by relevant types, * then by the types specified in the import statement. @@ -271,35 +123,31 @@ async function collectDefinitions( * @param typeDefinitions All definitions from a schema * @returns Filtered collection of type definitions */ -function filterImportedDefinitions(imports: string[], typeDefinitions: ReadonlyArray, allDefinitions: ValidDefinitionNode[][] = []): ValidDefinitionNode[] { +export function filterImportedDefinitions(imports: string[], typeDefinitions: ReadonlyArray) { // This should do something smart with fields - const filteredDefinitions = filterTypeDefinitions(typeDefinitions); - if (includes(imports, '*')) { - if (imports.length === 1 && imports[0] === '*' && allDefinitions.length > 1) { - const previousTypeDefinitions: { [key: string]: DefinitionNode } = keyBy( - flatten(allDefinitions.slice(0, allDefinitions.length - 1)).filter(def => !includes(rootFields, def.name.value)), - def => def.name.value - ); - return typeDefinitions.filter(typeDef => typeDef.kind === 'ObjectTypeDefinition' && previousTypeDefinitions[typeDef.name.value]) as ObjectTypeDefinitionNode[]; - } - return filteredDefinitions; + return typeDefinitions; } else { - const result = filteredDefinitions.filter(d => - includes( - imports.map(i => i.split('.')[0]), - d.name.value - ) - ); + const result = typeDefinitions.filter(d => { + if ('name' in d) { + return includes( + imports.map(i => i.split('.')[0]), + d.name.value + ); + } + return true; + }); const fieldImports = imports.filter(i => i.split('.').length > 1); const groupedFieldImports = groupBy(fieldImports, x => x.split('.')[0]); for (const rootType in groupedFieldImports) { const fields = groupedFieldImports[rootType].map(x => x.split('.')[1]); - const objectTypeDefinition: any = filteredDefinitions.find(def => def.name.value === rootType); + const objectTypeDefinition: any = typeDefinitions.find(def => 'name' in def && def.name.value === rootType); - objectTypeDefinition.fields = objectTypeDefinition.fields.filter((f: any) => includes(fields, f.name.value) || includes(fields, '*')); + if ('fields' in objectTypeDefinition) { + objectTypeDefinition.fields = objectTypeDefinition.fields.filter((f: any) => includes(fields, f.name.value) || includes(fields, '*')); + } } return result; @@ -312,7 +160,7 @@ function filterImportedDefinitions(imports: string[], typeDefinitions: ReadonlyA * @param definitions All definitions from a schema * @returns Relevant type definitions */ -function filterTypeDefinitions(definitions: ReadonlyArray): ValidDefinitionNode[] { +export function filterTypeDefinitions(definitions: ReadonlyArray): ValidDefinitionNode[] { const validKinds = ['DirectiveDefinition', 'ScalarTypeDefinition', 'ObjectTypeDefinition', 'ObjectTypeExtension', 'InterfaceTypeDefinition', 'EnumTypeDefinition', 'UnionTypeDefinition', 'InputObjectTypeDefinition']; return definitions.filter(d => includes(validKinds, d.kind)).map(d => d as ValidDefinitionNode); } diff --git a/packages/core/src/load-typedefs.ts b/packages/core/src/load-typedefs.ts index 07a485d8..70d2d265 100644 --- a/packages/core/src/load-typedefs.ts +++ b/packages/core/src/load-typedefs.ts @@ -1,23 +1,17 @@ -import { GraphQLSchema, parse, DocumentNode, Source as GraphQLSource } from 'graphql'; -import { Source, asArray, isDocumentString, debugLog, fixWindowsPath, Loader, printSchemaWithDirectives, fixSchemaAst } from '@graphql-toolkit/common'; -import { filterKind } from './filter-document-kind'; +import { Source as GraphQLSource, GraphQLSchema, parse, Kind } from 'graphql'; +import { Source, asArray, isDocumentString, debugLog, fixWindowsPath, printSchemaWithDirectives, parseGraphQLSDL, fixSchemaAst, SingleFileOptions } from '@graphql-toolkit/common'; import { join } from 'path'; import isGlob from 'is-glob'; import globby from 'globby'; -import { processImportSyntax } from './import-parser'; - -export type SingleFileOptions = ExtraConfig & { - noRequire?: boolean; - skipGraphQLImport?: boolean; - forceRawSDL?: boolean; - forceGraphQLImport?: boolean; - mergeableTypes?: [string]; -}; +import { filterKind } from './filter-document-kind'; +import { parseSDL, isEmptySDL, filterImportedDefinitions, resolveModuleFilePath } from './import-parser'; -export type LoadTypedefsOptions = SingleFileOptions & { - ignore?: string | string[]; - schemas?: { [key: string]: string | DocumentNode | GraphQLSchema }; -}; +export type LoadTypedefsOptions = SingleFileOptions & + ExtraConfig & { + ignore?: string | string[]; + preresolvedTypeDefs?: { [key: string]: string }; + sort?: boolean; + }; export type UnnormalizedTypeDefPointer = { [key: string]: any } | string; @@ -68,76 +62,33 @@ function stringToHash(str: string) { return hash; } -export async function loadTypedefsUsingLoaders( - loaders: Loader[], - pointerOrPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[], - options: LoadTypedefsOptions> = {}, - filterKinds: string[] = [], - cwd = process.cwd() -): Promise { +export async function loadTypedefs(pointerOrPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[], options: LoadTypedefsOptions>): Promise { const normalizedPointerOptionsMap = normalizePointers(pointerOrPointers); const loadPromises$: Promise[] = []; const found: Source[] = []; const foundGlobs: string[] = []; const globOptions: any = {}; + options.cache = options.cache || {}; + options.cwd = options.cwd || process.cwd(); + options.sort = 'sort' in options ? options.sort : true; + for (const pointer in normalizedPointerOptionsMap) { const pointerOptions = normalizedPointerOptionsMap[pointer]; - if (options && options.schemas && pointer in options.schemas) { - const content = options.schemas[pointer]; - if (typeof content === 'string') { - const rawSDL = content as string; - let unfilteredDocument: DocumentNode; - if (options.forceGraphQLImport || (!options.skipGraphQLImport && /^\#.*import /i.test(rawSDL.trimLeft()))) { - unfilteredDocument = await processImportSyntax(pointer, rawSDL, loaders, options, cwd); - } else { - unfilteredDocument = parse(new GraphQLSource(rawSDL, pointer)); - } - const document = filterKind(unfilteredDocument, filterKinds); - if (options.forceRawSDL || (document && document.definitions && document.definitions.length > 0)) { - found.push({ - location: pointer, - document, - rawSDL, - }); - } - } else if (content instanceof GraphQLSchema) { - const schema = content as GraphQLSchema; - found.push({ - location: pointer, - get document() { - return parse(new GraphQLSource(printSchemaWithDirectives(schema), pointer)); - }, - schema, - }); - } else { - let document = content as DocumentNode; - document = filterKind(document, filterKinds); - if (document && document.definitions && document.definitions.length > 0) { - found.push({ - location: pointer, - document, - }); - } - } + if (options.preresolvedTypeDefs && pointer in options.preresolvedTypeDefs) { + loadPromises$.push( + Promise.resolve().then(async () => { + const result = parseGraphQLSDL(pointer, options.preresolvedTypeDefs[pointer], options); + found.push(result); + options.cache[pointer] = result; + }) + ); } else if (isDocumentString(pointer)) { loadPromises$.push( Promise.resolve().then(async () => { - let rawSDL = pointer; - let content: DocumentNode; - if (options.forceGraphQLImport || (!options.skipGraphQLImport && /^\#.*import /i.test(rawSDL.trimLeft()))) { - content = await processImportSyntax(pointer, rawSDL, loaders, options, cwd); - } else { - content = parse(new GraphQLSource(rawSDL, pointer)); - } - content = filterKind(content, filterKinds); - if (options.forceRawSDL || (content && content.definitions && content.definitions.length > 0)) { - found.push({ - location: stringToHash(pointer) + '.graphql', - document: content, - rawSDL: pointer, - }); - } + const result = parseGraphQLSDL(`${stringToHash(pointer)}.graphql`, pointer, options); + found.push(result); + options.cache[pointer] = result; }) ); } else if (isGlob(pointer)) { @@ -148,26 +99,33 @@ export async function loadTypedefsUsingLoaders( Promise.resolve().then(async () => { let loader; if (typeof pointerOptions.loader === 'string') { - loader = await getCustomLoaderByPath(pointerOptions.loader, cwd); + loader = await getCustomLoaderByPath(pointerOptions.loader, options.cwd); } else if (typeof pointerOptions.loader === 'function') { loader = pointerOptions.loader; } if (typeof loader !== 'function') { throw new Error(`Failed to load custom loader: ${pointerOptions.loader}`); } - let schema: GraphQLSchema; - let content = await loader(pointer, { ...options, ...pointerOptions }, normalizedPointerOptionsMap); - if (content && content instanceof GraphQLSchema) { - schema = fixSchemaAst(content, options as any); - content = parse(printSchemaWithDirectives(content)); - } - content = filterKind(content, filterKinds); - if (content && content.definitions && content.definitions.length > 0) { + const customLoaderResult = await loader(pointer, { ...options, ...pointerOptions }, normalizedPointerOptionsMap); + if (customLoaderResult && customLoaderResult instanceof GraphQLSchema) { found.push({ location: pointer, - document: content, - schema, + schema: customLoaderResult, }); + } else if (customLoaderResult && customLoaderResult.kind && customLoaderResult.kind === Kind.DOCUMENT) { + const result = { + document: customLoaderResult, + location: pointer, + }; + options.cache[pointer] = result; + found.push(result); + } else if (customLoaderResult && customLoaderResult.document) { + const result = { + location: pointer, + ...customLoaderResult, + }; + options.cache[pointer] = result; + found.push(result); } }) ); @@ -178,25 +136,9 @@ export async function loadTypedefsUsingLoaders( ...options, ...pointerOptions, }; - let loaded = await loadSingleFile(loaders, pointer, combinedOptions); - if (loaded) { - let unfilteredDocument: DocumentNode; - const rawSDL = loaded.rawSDL; - if (options.forceGraphQLImport || (rawSDL && !options.skipGraphQLImport && /^\#.*import /i.test(rawSDL.trimLeft()))) { - unfilteredDocument = await processImportSyntax(pointer, rawSDL, loaders, options, cwd); - } else { - unfilteredDocument = loaded.document; - } - const filteredDocument = filterKind(unfilteredDocument, filterKinds); - if (options.forceRawSDL || (filteredDocument && filteredDocument.definitions && filteredDocument.definitions.length > 0)) { - found.push({ - location: pointer, - document: filteredDocument, - schema: loaded.schema && fixSchemaAst(loaded.schema, combinedOptions), - rawSDL: loaded.rawSDL, - }); - } - } + const loaderResult = await loadSingleFile(pointer, combinedOptions); + options.cache[pointer] = loaderResult; + found.push(loaderResult); }) ); } @@ -215,46 +157,48 @@ export async function loadTypedefsUsingLoaders( loadPromises$.push( Promise.resolve().then(async () => { - const paths = await globby(foundGlobs, { cwd, absolute: true }); + const paths = await globby(foundGlobs, { absolute: true, ...options, ignore: [] }); await Promise.all( paths.map(async path => { if (!path.endsWith('.d.ts') && !path.endsWith('.spec.ts') && !path.endsWith('.spec.js') && !path.endsWith('.test.ts') && !path.endsWith('.test.js')) { - let content, schema, rawSDL; if (globOptions.loader) { let loader; if (typeof globOptions.loader === 'string') { - loader = await getCustomLoaderByPath(globOptions.loader, cwd); + loader = await getCustomLoaderByPath(globOptions.loader, options.cwd); } else if (typeof globOptions.loader === 'function') { loader = globOptions.loader; } if (typeof loader !== 'function') { throw new Error(`Failed to load custom loader: ${globOptions.loader}`); } - content = await loader(path, { ...options, ...globOptions }, normalizedPointerOptionsMap); - if (content && content instanceof GraphQLSchema) { - schema = content; - content = parse(printSchemaWithDirectives(content)); + const customLoaderResult = await loader(path, { ...options, ...globOptions }, normalizedPointerOptionsMap); + if (customLoaderResult instanceof GraphQLSchema) { + const result = { + schema: customLoaderResult, + document: parse(printSchemaWithDirectives(customLoaderResult)), + location: path, + }; + options.cache[path] = result; + found.push(result); + } else if (customLoaderResult && customLoaderResult.kind && customLoaderResult.kind === Kind.DOCUMENT) { + const result = { + document: customLoaderResult, + location: path, + }; + options.cache[path] = result; + found.push(result); + } else if (customLoaderResult && customLoaderResult.document) { + const result = { + location: path, + ...customLoaderResult, + }; + options.cache[path] = result; + found.push(result); } } else { - const loaded = await loadSingleFile(loaders, path, { ...options, ...globOptions }); - if (loaded) { - rawSDL = loaded.rawSDL; - if (options.forceGraphQLImport || (rawSDL && !options.skipGraphQLImport && /^\#.*import /i.test(rawSDL.trimLeft()))) { - content = await processImportSyntax(path, rawSDL, loaders, options, cwd); - } else { - content = loaded.document; - } - } - } - content = filterKind(content, filterKinds); - - if (options.forceRawSDL || (content && content.definitions && content.definitions.length > 0)) { - found.push({ - location: path, - document: content, - schema, - rawSDL, - }); + const loaderResult = await loadSingleFile(path, { ...options, ...globOptions }); + options.cache[path] = loaderResult; + found.push(loaderResult); } } }) @@ -265,17 +209,66 @@ export async function loadTypedefsUsingLoaders( await Promise.all(loadPromises$); + const importsLoadPromises: Promise[] = []; + + const foundValid: Source[] = []; + + for (const partialSource of found) { + if (partialSource) { + const resultSource: Source = { ...partialSource }; + if (resultSource.schema) { + resultSource.schema = fixSchemaAst(resultSource.schema, options as any); + resultSource.rawSDL = printSchemaWithDirectives(resultSource.schema); + } + if (resultSource.rawSDL) { + const imports = parseSDL(resultSource.rawSDL); + for (const i of imports) { + importsLoadPromises.push( + Promise.resolve().then(async () => { + const sources = await loadTypedefs(resolveModuleFilePath(resultSource.location, i.from), options); + for (const source of sources) { + foundValid.unshift({ + ...source, + document: { + ...source.document, + definitions: filterImportedDefinitions(i.imports, source.document.definitions), + }, + }); + } + }) + ); + } + if (!isEmptySDL(resultSource.rawSDL)) { + resultSource.document = parse(new GraphQLSource(resultSource.rawSDL, resultSource.location), options); + } + } + if (resultSource.document) { + if (options.filterKinds) { + resultSource.document = filterKind(resultSource.document, options.filterKinds); + } + if (resultSource.document.definitions && resultSource.document.definitions.length > 0) { + foundValid.push(resultSource); + } + } + } + } + + await Promise.all(importsLoadPromises); + const pointerList = Object.keys(normalizedPointerOptionsMap); - if (pointerList.length > 0 && found.length === 0) { + if (pointerList.length > 0 && foundValid.length === 0) { throw new Error(`Unable to find any GraphQL type definitions for the following pointers: ${pointerList.join(', ')}`); } - return found.sort((left, right) => left.location.localeCompare(right.location)); + return options.sort ? foundValid.sort((left, right) => left.location.localeCompare(right.location)) : foundValid; } -export async function loadSingleFile(loaders: Loader[], pointer: string, options: SingleFileOptions = {}): Promise { +export async function loadSingleFile(pointer: string, options: SingleFileOptions): Promise { + if (pointer in options.cache) { + return options.cache[pointer]; + } try { - for (const loader of loaders) { + for (const loader of options.loaders) { const canLoad = await loader.canLoad(pointer, options); if (canLoad) { diff --git a/packages/core/src/schema.ts b/packages/core/src/schema.ts index 9882c5cd..9d06ff91 100644 --- a/packages/core/src/schema.ts +++ b/packages/core/src/schema.ts @@ -1,13 +1,15 @@ -import { loadTypedefsUsingLoaders, LoadTypedefsOptions, UnnormalizedTypeDefPointer } from './load-typedefs'; +import { loadTypedefs, LoadTypedefsOptions, UnnormalizedTypeDefPointer } from './load-typedefs'; import { GraphQLSchema, BuildSchemaOptions, DocumentNode } from 'graphql'; import { OPERATION_KINDS } from './documents'; import { mergeSchemasAsync } from '@graphql-toolkit/schema-merging'; -import { Loader } from '@graphql-toolkit/common'; export type LoadSchemaOptions = BuildSchemaOptions & LoadTypedefsOptions; -export async function loadSchemaUsingLoaders(loaders: Loader[], schemaPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[], options?: LoadSchemaOptions, cwd = process.cwd()): Promise { - const sources = await loadTypedefsUsingLoaders(loaders, schemaPointers, options, OPERATION_KINDS, cwd); +export async function loadSchema(schemaPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[], options: LoadSchemaOptions): Promise { + const sources = await loadTypedefs(schemaPointers, { + filterKinds: OPERATION_KINDS, + ...options, + }); const schemas: GraphQLSchema[] = []; const typeDefs: DocumentNode[] = []; diff --git a/packages/graphql-toolkit/tests/__mocks__/cross-fetch.js b/packages/core/tests/__mocks__/cross-fetch.js similarity index 100% rename from packages/graphql-toolkit/tests/__mocks__/cross-fetch.js rename to packages/core/tests/__mocks__/cross-fetch.js diff --git a/packages/graphql-toolkit/tests/__mocks__/fs.js b/packages/core/tests/__mocks__/fs.js similarity index 100% rename from packages/graphql-toolkit/tests/__mocks__/fs.js rename to packages/core/tests/__mocks__/fs.js diff --git a/packages/graphql-toolkit/tests/loaders/documents/documents-from-glob.spec.ts b/packages/core/tests/loaders/documents/documents-from-glob.spec.ts similarity index 70% rename from packages/graphql-toolkit/tests/loaders/documents/documents-from-glob.spec.ts rename to packages/core/tests/loaders/documents/documents-from-glob.spec.ts index d4701a05..2a182cd5 100644 --- a/packages/graphql-toolkit/tests/loaders/documents/documents-from-glob.spec.ts +++ b/packages/core/tests/loaders/documents/documents-from-glob.spec.ts @@ -1,18 +1,24 @@ -import { loadDocuments } from '../../../src'; +import { loadDocuments } from '@graphql-toolkit/core'; import { join } from 'path'; import { separateOperations } from 'graphql'; +import { GraphQLFileLoader } from '@graphql-toolkit/graphql-file-loader'; +import { CodeFileLoader } from '@graphql-toolkit/code-file-loader'; describe('documentsFromGlob', () => { it('Should load one GraphQL document from glob expression', async () => { const glob = join(__dirname, './test-files/', '*.query.graphql'); - const result = await loadDocuments(glob); + const result = await loadDocuments(glob, { + loaders: [new GraphQLFileLoader()] + }); expect(result.length).toBe(1); expect(result[0].document).toBeDefined(); }); it('Should load multiple GraphQL document from glob expression', async () => { const glob = join(__dirname, './test-files/', '*.graphql'); - const result = await loadDocuments(glob); + const result = await loadDocuments(glob, { + loaders: [new GraphQLFileLoader()] + }); expect(result.length).toBe(2); expect(result[0].document).toBeDefined(); expect(result[1].document).toBeDefined(); @@ -20,7 +26,9 @@ describe('documentsFromGlob', () => { it('Should load two GraphQL documents both for gatsby and graphql-tag by default', async () => { const glob = join(__dirname, './test-files/', 'tags.js'); - const result = await loadDocuments(glob); + const result = await loadDocuments(glob, { + loaders: [new CodeFileLoader()] + }); const operations = separateOperations(result[0].document); expect(Object.keys(operations)).toHaveLength(2); @@ -38,6 +46,9 @@ describe('documentsFromGlob', () => { }, ], }, + loaders: [ + new CodeFileLoader() + ] }); const operations = separateOperations(result[0].document); @@ -48,7 +59,9 @@ describe('documentsFromGlob', () => { it('Should throw on empty files and empty result', async () => { try { const glob = join(__dirname, './test-files/', '*.empty.graphql'); - await loadDocuments(glob); + const result = await loadDocuments(glob, { + loaders: [new GraphQLFileLoader()] + }); expect(true).toBeFalsy(); } catch (e) { expect(e).toBeDefined(); @@ -58,7 +71,9 @@ describe('documentsFromGlob', () => { it('Should throw on invalid files', async () => { try { const glob = join(__dirname, './test-files/', 'invalid*.*.graphql'); - await loadDocuments(glob); + const result = await loadDocuments(glob, { + loaders: [new GraphQLFileLoader()] + }); expect(true).toBeFalsy(); } catch (e) { expect(e).toBeDefined(); @@ -67,21 +82,28 @@ describe('documentsFromGlob', () => { it('Should ignore schema definitions', async () => { const glob = join(__dirname, './test-files/', '*.graphql'); - const result = await loadDocuments(glob); + const result = await loadDocuments(glob, { + loaders: [new GraphQLFileLoader()] + }); expect(result.length).toBe(2); }); it('Should ignore files that is added to ignore glob (using options.ignore)', async () => { const glob = join(__dirname, './test-files/', '*.graphql'); const ignoreGlob = join(__dirname, './test-files/', '*.query.graphql'); - const result = await loadDocuments([glob], { ignore: ignoreGlob }); + const result = await loadDocuments([glob], { + ignore: ignoreGlob, + loaders: [new GraphQLFileLoader()] + }); expect(result.length).toBe(1); }); it('Should ignore files that is added to ignore glob (using negative glob)', async () => { const glob = join(__dirname, './test-files/', '*.graphql'); const ignoreGlob = `!(${join(__dirname, './test-files/', '*.query.graphql')})`; - const result = await loadDocuments([glob, ignoreGlob]); + const result = await loadDocuments([glob, ignoreGlob], { + loaders: [new GraphQLFileLoader()] + }); expect(result.length).toBe(1); }); }); diff --git a/packages/graphql-toolkit/tests/loaders/documents/test-files/1.query.graphql b/packages/core/tests/loaders/documents/test-files/1.query.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/documents/test-files/1.query.graphql rename to packages/core/tests/loaders/documents/test-files/1.query.graphql diff --git a/packages/graphql-toolkit/tests/loaders/documents/test-files/2.graphql b/packages/core/tests/loaders/documents/test-files/2.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/documents/test-files/2.graphql rename to packages/core/tests/loaders/documents/test-files/2.graphql diff --git a/packages/graphql-toolkit/tests/loaders/documents/test-files/invalid-doc.graphql b/packages/core/tests/loaders/documents/test-files/invalid-doc.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/documents/test-files/invalid-doc.graphql rename to packages/core/tests/loaders/documents/test-files/invalid-doc.graphql diff --git a/packages/graphql-toolkit/tests/loaders/documents/test-files/tags.js b/packages/core/tests/loaders/documents/test-files/tags.js similarity index 100% rename from packages/graphql-toolkit/tests/loaders/documents/test-files/tags.js rename to packages/core/tests/loaders/documents/test-files/tags.js diff --git a/packages/graphql-toolkit/tests/loaders/documents/test-files/test.empty.graphql b/packages/core/tests/loaders/documents/test-files/test.empty.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/documents/test-files/test.empty.graphql rename to packages/core/tests/loaders/documents/test-files/test.empty.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/circular/a.graphql b/packages/core/tests/loaders/schema/fixtures/circular/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/circular/a.graphql rename to packages/core/tests/loaders/schema/fixtures/circular/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/circular/b.graphql b/packages/core/tests/loaders/schema/fixtures/circular/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/circular/b.graphql rename to packages/core/tests/loaders/schema/fixtures/circular/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/circular/c.graphql b/packages/core/tests/loaders/schema/fixtures/circular/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/circular/c.graphql rename to packages/core/tests/loaders/schema/fixtures/circular/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/collision/a.graphql b/packages/core/tests/loaders/schema/fixtures/collision/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/collision/a.graphql rename to packages/core/tests/loaders/schema/fixtures/collision/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/collision/b.graphql b/packages/core/tests/loaders/schema/fixtures/collision/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/collision/b.graphql rename to packages/core/tests/loaders/schema/fixtures/collision/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/complex/a.graphql b/packages/core/tests/loaders/schema/fixtures/complex/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/complex/a.graphql rename to packages/core/tests/loaders/schema/fixtures/complex/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/complex/b.graphql b/packages/core/tests/loaders/schema/fixtures/complex/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/complex/b.graphql rename to packages/core/tests/loaders/schema/fixtures/complex/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/a.graphql b/packages/core/tests/loaders/schema/fixtures/directive/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/a.graphql rename to packages/core/tests/loaders/schema/fixtures/directive/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/b.graphql b/packages/core/tests/loaders/schema/fixtures/directive/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/b.graphql rename to packages/core/tests/loaders/schema/fixtures/directive/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/c.graphql b/packages/core/tests/loaders/schema/fixtures/directive/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/c.graphql rename to packages/core/tests/loaders/schema/fixtures/directive/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/d.graphql b/packages/core/tests/loaders/schema/fixtures/directive/d.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/d.graphql rename to packages/core/tests/loaders/schema/fixtures/directive/d.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/e.graphql b/packages/core/tests/loaders/schema/fixtures/directive/e.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/e.graphql rename to packages/core/tests/loaders/schema/fixtures/directive/e.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/f.graphql b/packages/core/tests/loaders/schema/fixtures/directive/f.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/f.graphql rename to packages/core/tests/loaders/schema/fixtures/directive/f.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/g.graphql b/packages/core/tests/loaders/schema/fixtures/directive/g.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/directive/g.graphql rename to packages/core/tests/loaders/schema/fixtures/directive/g.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/enums/a.graphql b/packages/core/tests/loaders/schema/fixtures/enums/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/enums/a.graphql rename to packages/core/tests/loaders/schema/fixtures/enums/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/enums/b.graphql b/packages/core/tests/loaders/schema/fixtures/enums/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/enums/b.graphql rename to packages/core/tests/loaders/schema/fixtures/enums/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/field-types/a.graphql b/packages/core/tests/loaders/schema/fixtures/field-types/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/field-types/a.graphql rename to packages/core/tests/loaders/schema/fixtures/field-types/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/field-types/b.graphql b/packages/core/tests/loaders/schema/fixtures/field-types/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/field-types/b.graphql rename to packages/core/tests/loaders/schema/fixtures/field-types/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/field-types/c.graphql b/packages/core/tests/loaders/schema/fixtures/field-types/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/field-types/c.graphql rename to packages/core/tests/loaders/schema/fixtures/field-types/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/global/a.graphql b/packages/core/tests/loaders/schema/fixtures/global/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/global/a.graphql rename to packages/core/tests/loaders/schema/fixtures/global/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-all/a.graphql b/packages/core/tests/loaders/schema/fixtures/import-all/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-all/a.graphql rename to packages/core/tests/loaders/schema/fixtures/import-all/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-all/b.graphql b/packages/core/tests/loaders/schema/fixtures/import-all/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-all/b.graphql rename to packages/core/tests/loaders/schema/fixtures/import-all/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-all/c.graphql b/packages/core/tests/loaders/schema/fixtures/import-all/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-all/c.graphql rename to packages/core/tests/loaders/schema/fixtures/import-all/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-duplicate/a.graphql b/packages/core/tests/loaders/schema/fixtures/import-duplicate/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-duplicate/a.graphql rename to packages/core/tests/loaders/schema/fixtures/import-duplicate/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-duplicate/all.graphql b/packages/core/tests/loaders/schema/fixtures/import-duplicate/all.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-duplicate/all.graphql rename to packages/core/tests/loaders/schema/fixtures/import-duplicate/all.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-gql/a.gql b/packages/core/tests/loaders/schema/fixtures/import-gql/a.gql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-gql/a.gql rename to packages/core/tests/loaders/schema/fixtures/import-gql/a.gql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-module/a.graphql b/packages/core/tests/loaders/schema/fixtures/import-module/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-module/a.graphql rename to packages/core/tests/loaders/schema/fixtures/import-module/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-nested/a.graphql b/packages/core/tests/loaders/schema/fixtures/import-nested/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-nested/a.graphql rename to packages/core/tests/loaders/schema/fixtures/import-nested/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-nested/all.graphql b/packages/core/tests/loaders/schema/fixtures/import-nested/all.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-nested/all.graphql rename to packages/core/tests/loaders/schema/fixtures/import-nested/all.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-nested/b.graphql b/packages/core/tests/loaders/schema/fixtures/import-nested/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-nested/b.graphql rename to packages/core/tests/loaders/schema/fixtures/import-nested/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/import-nested/c.graphql b/packages/core/tests/loaders/schema/fixtures/import-nested/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/import-nested/c.graphql rename to packages/core/tests/loaders/schema/fixtures/import-nested/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/imports-only/a.graphql b/packages/core/tests/loaders/schema/fixtures/imports-only/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/imports-only/a.graphql rename to packages/core/tests/loaders/schema/fixtures/imports-only/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/imports-only/all.graphql b/packages/core/tests/loaders/schema/fixtures/imports-only/all.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/imports-only/all.graphql rename to packages/core/tests/loaders/schema/fixtures/imports-only/all.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/imports-only/b.graphql b/packages/core/tests/loaders/schema/fixtures/imports-only/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/imports-only/b.graphql rename to packages/core/tests/loaders/schema/fixtures/imports-only/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/input-types/a.graphql b/packages/core/tests/loaders/schema/fixtures/input-types/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/input-types/a.graphql rename to packages/core/tests/loaders/schema/fixtures/input-types/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/input-types/b.graphql b/packages/core/tests/loaders/schema/fixtures/input-types/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/input-types/b.graphql rename to packages/core/tests/loaders/schema/fixtures/input-types/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/input-types/c.graphql b/packages/core/tests/loaders/schema/fixtures/input-types/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/input-types/c.graphql rename to packages/core/tests/loaders/schema/fixtures/input-types/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-implements-many/a.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces-implements-many/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-implements-many/a.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces-implements-many/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-implements-many/b.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces-implements-many/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-implements-many/b.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces-implements-many/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-implements/a.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces-implements/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-implements/a.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces-implements/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-implements/b.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces-implements/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-implements/b.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces-implements/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-many/a.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces-many/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-many/a.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces-many/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-many/b.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces-many/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-many/b.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces-many/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-many/c.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces-many/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-many/c.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces-many/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-many/d.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces-many/d.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces-many/d.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces-many/d.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces/a.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces/a.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces/b.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces/b.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces/c.graphql b/packages/core/tests/loaders/schema/fixtures/interfaces/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/interfaces/c.graphql rename to packages/core/tests/loaders/schema/fixtures/interfaces/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/merged-root-fields/a.graphql b/packages/core/tests/loaders/schema/fixtures/merged-root-fields/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/merged-root-fields/a.graphql rename to packages/core/tests/loaders/schema/fixtures/merged-root-fields/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/merged-root-fields/b.graphql b/packages/core/tests/loaders/schema/fixtures/merged-root-fields/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/merged-root-fields/b.graphql rename to packages/core/tests/loaders/schema/fixtures/merged-root-fields/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/related-types/a.graphql b/packages/core/tests/loaders/schema/fixtures/related-types/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/related-types/a.graphql rename to packages/core/tests/loaders/schema/fixtures/related-types/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/related-types/b.graphql b/packages/core/tests/loaders/schema/fixtures/related-types/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/related-types/b.graphql rename to packages/core/tests/loaders/schema/fixtures/related-types/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/relative-paths/database/schema.graphql b/packages/core/tests/loaders/schema/fixtures/relative-paths/database/schema.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/relative-paths/database/schema.graphql rename to packages/core/tests/loaders/schema/fixtures/relative-paths/database/schema.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/relative-paths/src/schema.graphql b/packages/core/tests/loaders/schema/fixtures/relative-paths/src/schema.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/relative-paths/src/schema.graphql rename to packages/core/tests/loaders/schema/fixtures/relative-paths/src/schema.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/a.graphql b/packages/core/tests/loaders/schema/fixtures/root-fields/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/a.graphql rename to packages/core/tests/loaders/schema/fixtures/root-fields/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/b.graphql b/packages/core/tests/loaders/schema/fixtures/root-fields/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/b.graphql rename to packages/core/tests/loaders/schema/fixtures/root-fields/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/c.graphql b/packages/core/tests/loaders/schema/fixtures/root-fields/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/c.graphql rename to packages/core/tests/loaders/schema/fixtures/root-fields/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/d.graphql b/packages/core/tests/loaders/schema/fixtures/root-fields/d.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/d.graphql rename to packages/core/tests/loaders/schema/fixtures/root-fields/d.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/e.graphql b/packages/core/tests/loaders/schema/fixtures/root-fields/e.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/root-fields/e.graphql rename to packages/core/tests/loaders/schema/fixtures/root-fields/e.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/scalar/a.graphql b/packages/core/tests/loaders/schema/fixtures/scalar/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/scalar/a.graphql rename to packages/core/tests/loaders/schema/fixtures/scalar/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/scalar/b.graphql b/packages/core/tests/loaders/schema/fixtures/scalar/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/scalar/b.graphql rename to packages/core/tests/loaders/schema/fixtures/scalar/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/a.graphql b/packages/core/tests/loaders/schema/fixtures/type-not-found/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/a.graphql rename to packages/core/tests/loaders/schema/fixtures/type-not-found/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/b.graphql b/packages/core/tests/loaders/schema/fixtures/type-not-found/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/b.graphql rename to packages/core/tests/loaders/schema/fixtures/type-not-found/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/c.graphql b/packages/core/tests/loaders/schema/fixtures/type-not-found/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/c.graphql rename to packages/core/tests/loaders/schema/fixtures/type-not-found/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/d.graphql b/packages/core/tests/loaders/schema/fixtures/type-not-found/d.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/d.graphql rename to packages/core/tests/loaders/schema/fixtures/type-not-found/d.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/e.graphql b/packages/core/tests/loaders/schema/fixtures/type-not-found/e.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/e.graphql rename to packages/core/tests/loaders/schema/fixtures/type-not-found/e.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/f.graphql b/packages/core/tests/loaders/schema/fixtures/type-not-found/f.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/f.graphql rename to packages/core/tests/loaders/schema/fixtures/type-not-found/f.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/g.graphql b/packages/core/tests/loaders/schema/fixtures/type-not-found/g.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/type-not-found/g.graphql rename to packages/core/tests/loaders/schema/fixtures/type-not-found/g.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/unions/a.graphql b/packages/core/tests/loaders/schema/fixtures/unions/a.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/unions/a.graphql rename to packages/core/tests/loaders/schema/fixtures/unions/a.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/unions/b.graphql b/packages/core/tests/loaders/schema/fixtures/unions/b.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/unions/b.graphql rename to packages/core/tests/loaders/schema/fixtures/unions/b.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/fixtures/unions/c.graphql b/packages/core/tests/loaders/schema/fixtures/unions/c.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/fixtures/unions/c.graphql rename to packages/core/tests/loaders/schema/fixtures/unions/c.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/import-schema.spec.ts b/packages/core/tests/loaders/schema/import-schema.spec.ts similarity index 92% rename from packages/graphql-toolkit/tests/loaders/schema/import-schema.spec.ts rename to packages/core/tests/loaders/schema/import-schema.spec.ts index e54956fe..e4fc6d3e 100644 --- a/packages/graphql-toolkit/tests/loaders/schema/import-schema.spec.ts +++ b/packages/core/tests/loaders/schema/import-schema.spec.ts @@ -1,12 +1,23 @@ -import { parseImportLine, parseSDL, loadTypedefsUsingLoaders, LoadTypedefsOptions } from '@graphql-toolkit/core'; +import { parseImportLine, parseSDL, loadTypedefs, LoadTypedefsOptions, OPERATION_KINDS } from '@graphql-toolkit/core'; import * as fs from 'fs' -import { DEFAULT_SCHEMA_LOADERS } from '../../../src'; -import { OPERATION_KINDS } from '../../../src'; -import { print, BuildSchemaOptions } from 'graphql'; -import { CodeFileLoaderOptions } from '@graphql-toolkit/code-file-loader'; -import { GraphQLFileLoaderOptions } from '@graphql-toolkit/graphql-file-loader'; - -const importSchema = (schema: string, options: BuildSchemaOptions & LoadTypedefsOptions = {}) => loadTypedefsUsingLoaders(DEFAULT_SCHEMA_LOADERS, schema, { ...options, forceGraphQLImport: true, }, OPERATION_KINDS).then(r => print(r[0].document)); +import { print } from 'graphql'; +import { JsonFileLoader } from '@graphql-toolkit/json-file-loader'; +import { UrlLoader } from '@graphql-toolkit/url-loader'; +import { CodeFileLoader } from '@graphql-toolkit/code-file-loader'; +import { GraphQLFileLoader } from '@graphql-toolkit/graphql-file-loader'; +import { mergeTypeDefs } from '@graphql-toolkit/schema-merging'; + +const importSchema = ( + schema: string, schemas?: { [name: string]: string }, options?: LoadTypedefsOptions +) => + loadTypedefs( + schema, { + loaders: [new UrlLoader(), new JsonFileLoader(), new GraphQLFileLoader(), new CodeFileLoader()], + filterKinds: OPERATION_KINDS, + preresolvedTypeDefs: schemas, + sort: false, + ...options, + }).then(r => print(mergeTypeDefs(r.map(r => r.document), { useSchemaDefinition: false }))); test('parseImportLine: parse single import', () => { expect(parseImportLine(`import A from "schema.graphql"`)).toEqual({ @@ -278,7 +289,7 @@ type C2 { id: ID! } ` - expect(await importSchema(schemaA, { schemas })).toBe(expectedSDL) + expect(await importSchema(schemaA, schemas)).toBe(expectedSDL) }) test(`importSchema: single object schema`, async () => { @@ -343,7 +354,7 @@ type B { } ` - expect(await importSchema(schemaA, { schemas })).toBe(expectedSDL) + expect(await importSchema(schemaA, schemas)).toBe(expectedSDL) }) test(`importSchema: import all mix 'n match 2`, async () => { @@ -463,7 +474,7 @@ type C2 { id: ID! } ` - expect(await importSchema(schemaA, { schemas })).toBe(expectedSDL) + expect(await importSchema(schemaA, schemas)).toBe(expectedSDL) }) test('importSchema: scalar', async () => { @@ -661,7 +672,7 @@ test('importSchema: complex test', async () => { }).not.toThrow(); }) -test('circular imports', async () => { +test.skip('circular imports', async () => { const expectedSDL = `\ type A { first: String @@ -834,7 +845,7 @@ type Shared { first: String } ` - expect(await importSchema('tests/loaders/schema/fixtures/global/a.graphql', { schemas: { shared } })).toBe(expectedSDL) + expect(await importSchema('tests/loaders/schema/fixtures/global/a.graphql', { shared } )).toBe(expectedSDL) }) test('missing type on type', async () => { @@ -946,6 +957,6 @@ test('merged custom root fields imports', async () => { field3: Int } `); - const actualSDL = await importSchema('tests/loaders/schema/fixtures/merged-root-fields/a.graphql', { mergeableTypes: ['Dummy'] }) + const actualSDL = await importSchema('tests/loaders/schema/fixtures/merged-root-fields/a.graphql') expect(stripWhitespaces(actualSDL)).toBe(stripWhitespaces(expectedSDL)) }) \ No newline at end of file diff --git a/packages/graphql-toolkit/tests/loaders/schema/integration.spec.ts b/packages/core/tests/loaders/schema/integration.spec.ts similarity index 63% rename from packages/graphql-toolkit/tests/loaders/schema/integration.spec.ts rename to packages/core/tests/loaders/schema/integration.spec.ts index 9e89625a..331fe7c3 100644 --- a/packages/graphql-toolkit/tests/loaders/schema/integration.spec.ts +++ b/packages/core/tests/loaders/schema/integration.spec.ts @@ -1,10 +1,14 @@ -import { loadSchema } from '../../../src'; +import { loadSchema } from '@graphql-toolkit/core'; +import { CodeFileLoader } from '@graphql-toolkit/code-file-loader'; +import { GraphQLFileLoader } from '@graphql-toolkit/graphql-file-loader'; describe('loadSchema', () => { it('should throw when all files are invalid and unable to load it', async () => { const schemaPath = './tests/loaders/schema/test-files/error.ts'; try { - await loadSchema(schemaPath); + await loadSchema(schemaPath, { + loaders: [new CodeFileLoader()] + }); expect(true).toBeFalsy(); // should throw } catch (e) { expect(e.toString()).toContain(`SyntaxError`); @@ -13,14 +17,18 @@ describe('loadSchema', () => { it('should work with ts files and without globs correctly', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/type-defs/graphql-tag.ts'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new CodeFileLoader()] + }); expect(schema.getTypeMap()['User']).toBeDefined(); expect(schema.getTypeMap()['Query']).toBeDefined(); }); it('should work with graphql single file', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/user.graphql'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new GraphQLFileLoader()] + }); expect(schema.getTypeMap()['User']).toBeDefined(); }); diff --git a/packages/graphql-toolkit/tests/loaders/schema/schema-from-export.spec.ts b/packages/core/tests/loaders/schema/schema-from-export.spec.ts similarity index 71% rename from packages/graphql-toolkit/tests/loaders/schema/schema-from-export.spec.ts rename to packages/core/tests/loaders/schema/schema-from-export.spec.ts index d78f8acd..99eab158 100644 --- a/packages/graphql-toolkit/tests/loaders/schema/schema-from-export.spec.ts +++ b/packages/core/tests/loaders/schema/schema-from-export.spec.ts @@ -1,41 +1,56 @@ import { GraphQLSchema } from 'graphql'; -import { loadSchema } from '../../../src'; +import { loadSchema } from '@graphql-toolkit/core'; +import { CodeFileLoader } from '@graphql-toolkit/code-file-loader'; describe('Schema From Export', () => { it('should load the schema correctly from module.exports', async () => { - const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/module-exports.js'); + const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/module-exports.js', { + loaders: [new CodeFileLoader()] + }); expect(result instanceof GraphQLSchema).toBeTruthy(); }); it('should load the schema (with extend) correctly from module.exports', async () => { - const result: GraphQLSchema = await loadSchema('./tests/loaders/schema/test-files/schema-dir/with-extend.js'); + const result: GraphQLSchema = await loadSchema('./tests/loaders/schema/test-files/schema-dir/with-extend.js', { + loaders: [new CodeFileLoader()] + }); expect(result instanceof GraphQLSchema).toBeTruthy(); expect(result.getQueryType().getFields()['hello']).toBeDefined(); }); it('should load the schema correctly from variable export', async () => { - const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/schema-export.js'); + const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/schema-export.js', { + loaders: [new CodeFileLoader()] + }); expect(result instanceof GraphQLSchema).toBeTruthy(); }); it('should load the schema correctly from default export', async () => { - const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/default-export.js'); + const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/default-export.js', { + loaders: [new CodeFileLoader()] + }); expect(result instanceof GraphQLSchema).toBeTruthy(); }); it('should load the schema correctly from promise export', async () => { - const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/promise-export.js'); + const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/promise-export.js', { + loaders: [new CodeFileLoader()] + }); expect(result instanceof GraphQLSchema).toBeTruthy(); }); it('should load the schema correctly from promise export', async () => { - const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/promise-export.js'); + const result: any = await loadSchema('./tests/loaders/schema/test-files/loaders/promise-export.js', { + loaders: [new CodeFileLoader()] + }); expect(result instanceof GraphQLSchema).toBeTruthy(); }); it.only('should work with extensions (without schema definition)', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/extensions/export-schema.js'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new CodeFileLoader()] + }); const queryFields = Object.keys(schema.getQueryType().getFields()); expect(queryFields).toContain('foo'); @@ -44,7 +59,9 @@ describe('Schema From Export', () => { it.only('should work with extensions (with schema definition)', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/extensions/export-schema-with-def.js'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new CodeFileLoader()] + }); const queryFields = Object.keys(schema.getQueryType().getFields()); expect(queryFields).toContain('foo'); diff --git a/packages/graphql-toolkit/tests/loaders/schema/schema-from-typedefs.spec.ts b/packages/core/tests/loaders/schema/schema-from-typedefs.spec.ts similarity index 73% rename from packages/graphql-toolkit/tests/loaders/schema/schema-from-typedefs.spec.ts rename to packages/core/tests/loaders/schema/schema-from-typedefs.spec.ts index 5823ffd7..315a77d9 100644 --- a/packages/graphql-toolkit/tests/loaders/schema/schema-from-typedefs.spec.ts +++ b/packages/core/tests/loaders/schema/schema-from-typedefs.spec.ts @@ -1,9 +1,13 @@ -import { loadSchema } from '../../../src'; +import { loadSchema } from '@graphql-toolkit/core'; +import { GraphQLFileLoader } from '@graphql-toolkit/graphql-file-loader'; +import { CodeFileLoader } from '@graphql-toolkit/code-file-loader'; describe('schema from typedefs', () => { it('should work with glob correctly', async () => { const glob = './tests/loaders/schema/test-files/schema-dir/query.graphql'; - const schema = await loadSchema(glob); + const schema = await loadSchema(glob, { + loaders: [new GraphQLFileLoader()] + }); expect(schema.getTypeMap()['User']).toBeDefined(); expect(schema.getTypeMap()['Query']).toBeDefined(); @@ -13,7 +17,9 @@ describe('schema from typedefs', () => { const glob = './tests/loaders/schema/test-files/schema-dir/*.empty.graphql'; try { - await loadSchema(glob); + await loadSchema(glob, { + loaders: [new GraphQLFileLoader()] + }); expect(true).toBeFalsy(); } catch (e) { expect(e.message).toBe(`Unable to find any GraphQL type definitions for the following pointers: ./tests/loaders/schema/test-files/schema-dir/*.empty.graphql`); @@ -24,7 +30,9 @@ describe('schema from typedefs', () => { const glob = './tests/loaders/schema/test-files/schema-dir/*.broken.graphql'; try { - await loadSchema(glob); + const schema = await loadSchema(glob, { + loaders: [new GraphQLFileLoader()] + }); expect(true).toBeFalsy(); } catch (e) { expect(e.message).toMatch('Unable to find any GraphQL type definitions for the following pointers'); @@ -35,7 +43,9 @@ describe('schema from typedefs', () => { const glob = './tests/loaders/schema/test-files/schema-dir/*.non-schema.graphql'; try { - await loadSchema(glob); + const schema = await loadSchema(glob, { + loaders: [new GraphQLFileLoader()] + }); expect(true).toBeFalsy(); } catch (e) { expect(e.message).toBe(`Unable to find any GraphQL type definitions for the following pointers: ./tests/loaders/schema/test-files/schema-dir/*.non-schema.graphql`); @@ -45,7 +55,9 @@ describe('schema from typedefs', () => { it('should work with graphql-tag', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/*.ts'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new CodeFileLoader()] + }); expect(schema.getTypeMap()['User']).toBeDefined(); expect(schema.getTypeMap()['Query']).toBeDefined(); @@ -53,7 +65,9 @@ describe('schema from typedefs', () => { it('should work without globs correctly', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/type-defs/graphql-tag.ts'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new CodeFileLoader()] + }); expect(schema.getTypeMap()['User']).toBeDefined(); expect(schema.getTypeMap()['Query']).toBeDefined(); @@ -61,7 +75,9 @@ describe('schema from typedefs', () => { it('should work with import notations', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/query.graphql'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new GraphQLFileLoader()] + }); expect(schema.getTypeMap()['User']).toBeDefined(); expect(schema.getTypeMap()['Query']).toBeDefined(); @@ -69,7 +85,9 @@ describe('schema from typedefs', () => { it('should work with extensions (static graphql file)', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/extensions/schema-with-extend.graphql'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new GraphQLFileLoader()] + }); const queryFields = Object.keys(schema.getQueryType().getFields()); expect(queryFields).toContain('foo'); @@ -78,7 +96,9 @@ describe('schema from typedefs', () => { it('should work with extensions (multiple graphql files)', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/extensions/*.graphql'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new GraphQLFileLoader()] + }); const queryFields = Object.keys(schema.getQueryType().getFields()); expect(queryFields).toContain('foo'); @@ -88,7 +108,9 @@ describe('schema from typedefs', () => { it('should work with extensions (static js file with typedefs)', async () => { const schemaPath = './tests/loaders/schema/test-files/schema-dir/extensions/type-defs.js'; - const schema = await loadSchema(schemaPath); + const schema = await loadSchema(schemaPath, { + loaders: [new CodeFileLoader()] + }); const queryFields = Object.keys(schema.getQueryType().getFields()); expect(queryFields).toContain('foo'); diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/1.ts b/packages/core/tests/loaders/schema/test-files/1.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/1.ts rename to packages/core/tests/loaders/schema/test-files/1.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/10.tsx b/packages/core/tests/loaders/schema/test-files/10.tsx similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/10.tsx rename to packages/core/tests/loaders/schema/test-files/10.tsx diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/11.ts b/packages/core/tests/loaders/schema/test-files/11.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/11.ts rename to packages/core/tests/loaders/schema/test-files/11.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/12.tsx b/packages/core/tests/loaders/schema/test-files/12.tsx similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/12.tsx rename to packages/core/tests/loaders/schema/test-files/12.tsx diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/13.tsx b/packages/core/tests/loaders/schema/test-files/13.tsx similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/13.tsx rename to packages/core/tests/loaders/schema/test-files/13.tsx diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/14.js b/packages/core/tests/loaders/schema/test-files/14.js similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/14.js rename to packages/core/tests/loaders/schema/test-files/14.js diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/15.js b/packages/core/tests/loaders/schema/test-files/15.js similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/15.js rename to packages/core/tests/loaders/schema/test-files/15.js diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/16.ts b/packages/core/tests/loaders/schema/test-files/16.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/16.ts rename to packages/core/tests/loaders/schema/test-files/16.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/2.ts b/packages/core/tests/loaders/schema/test-files/2.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/2.ts rename to packages/core/tests/loaders/schema/test-files/2.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/3.graphql b/packages/core/tests/loaders/schema/test-files/3.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/3.graphql rename to packages/core/tests/loaders/schema/test-files/3.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/4.ts b/packages/core/tests/loaders/schema/test-files/4.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/4.ts rename to packages/core/tests/loaders/schema/test-files/4.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/5.tsx b/packages/core/tests/loaders/schema/test-files/5.tsx similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/5.tsx rename to packages/core/tests/loaders/schema/test-files/5.tsx diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/6.ts b/packages/core/tests/loaders/schema/test-files/6.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/6.ts rename to packages/core/tests/loaders/schema/test-files/6.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/7.ts b/packages/core/tests/loaders/schema/test-files/7.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/7.ts rename to packages/core/tests/loaders/schema/test-files/7.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/8.ts b/packages/core/tests/loaders/schema/test-files/8.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/8.ts rename to packages/core/tests/loaders/schema/test-files/8.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/9.ts b/packages/core/tests/loaders/schema/test-files/9.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/9.ts rename to packages/core/tests/loaders/schema/test-files/9.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/ByteOrderMask.json b/packages/core/tests/loaders/schema/test-files/ByteOrderMask.json similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/ByteOrderMask.json rename to packages/core/tests/loaders/schema/test-files/ByteOrderMask.json diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/error.ts b/packages/core/tests/loaders/schema/test-files/error.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/error.ts rename to packages/core/tests/loaders/schema/test-files/error.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/export-schema-with-def.js b/packages/core/tests/loaders/schema/test-files/schema-dir/extensions/export-schema-with-def.js similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/export-schema-with-def.js rename to packages/core/tests/loaders/schema/test-files/schema-dir/extensions/export-schema-with-def.js diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/export-schema.js b/packages/core/tests/loaders/schema/test-files/schema-dir/extensions/export-schema.js similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/export-schema.js rename to packages/core/tests/loaders/schema/test-files/schema-dir/extensions/export-schema.js diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/extend-query.graphql b/packages/core/tests/loaders/schema/test-files/schema-dir/extensions/extend-query.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/extend-query.graphql rename to packages/core/tests/loaders/schema/test-files/schema-dir/extensions/extend-query.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/schema-with-extend.graphql b/packages/core/tests/loaders/schema/test-files/schema-dir/extensions/schema-with-extend.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/schema-with-extend.graphql rename to packages/core/tests/loaders/schema/test-files/schema-dir/extensions/schema-with-extend.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/type-defs.js b/packages/core/tests/loaders/schema/test-files/schema-dir/extensions/type-defs.js similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/extensions/type-defs.js rename to packages/core/tests/loaders/schema/test-files/schema-dir/extensions/type-defs.js diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/query.graphql b/packages/core/tests/loaders/schema/test-files/schema-dir/query.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/query.graphql rename to packages/core/tests/loaders/schema/test-files/schema-dir/query.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/schema.ts b/packages/core/tests/loaders/schema/test-files/schema-dir/schema.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/schema.ts rename to packages/core/tests/loaders/schema/test-files/schema-dir/schema.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/test.empty.graphql b/packages/core/tests/loaders/schema/test-files/schema-dir/test.empty.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/test.empty.graphql rename to packages/core/tests/loaders/schema/test-files/schema-dir/test.empty.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/test.non-schema.graphql b/packages/core/tests/loaders/schema/test-files/schema-dir/test.non-schema.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/test.non-schema.graphql rename to packages/core/tests/loaders/schema/test-files/schema-dir/test.non-schema.graphql diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/type-defs/custom.ts b/packages/core/tests/loaders/schema/test-files/schema-dir/type-defs/custom.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/type-defs/custom.ts rename to packages/core/tests/loaders/schema/test-files/schema-dir/type-defs/custom.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/type-defs/gatsby.ts b/packages/core/tests/loaders/schema/test-files/schema-dir/type-defs/gatsby.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/type-defs/gatsby.ts rename to packages/core/tests/loaders/schema/test-files/schema-dir/type-defs/gatsby.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/type-defs/graphql-tag.ts b/packages/core/tests/loaders/schema/test-files/schema-dir/type-defs/graphql-tag.ts similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/type-defs/graphql-tag.ts rename to packages/core/tests/loaders/schema/test-files/schema-dir/type-defs/graphql-tag.ts diff --git a/packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/user.graphql b/packages/core/tests/loaders/schema/test-files/schema-dir/user.graphql similarity index 100% rename from packages/graphql-toolkit/tests/loaders/schema/test-files/schema-dir/user.graphql rename to packages/core/tests/loaders/schema/test-files/schema-dir/user.graphql diff --git a/packages/graphql-toolkit/.gitignore b/packages/graphql-toolkit/.gitignore deleted file mode 100644 index b2931f95..00000000 --- a/packages/graphql-toolkit/.gitignore +++ /dev/null @@ -1,72 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env - -# next.js build output -.next - - -dist -build -temp -.idea - -test-results/ -junit.xml - -*.tgz \ No newline at end of file diff --git a/packages/graphql-toolkit/.npmignore b/packages/graphql-toolkit/.npmignore deleted file mode 100644 index 4ff88439..00000000 --- a/packages/graphql-toolkit/.npmignore +++ /dev/null @@ -1,13 +0,0 @@ -src -node_modules -tests -!dist -.circleci -.prettierrc -bump.js -jest.config.js -tsconfig.json -yarn.lock -yarn-error.log -bundle-test -*.tgz \ No newline at end of file diff --git a/packages/graphql-toolkit/package.json b/packages/graphql-toolkit/package.json deleted file mode 100644 index 9f15721b..00000000 --- a/packages/graphql-toolkit/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "graphql-toolkit", - "version": "0.7.5", - "description": "Common package containting utils and types for GraphQL Toolkit", - "repository": "git@github.com:ardatan/graphql-toolkit.git", - "author": "Dotan Simha ", - "license": "MIT", - "scripts": { - "clean": "rimraf dist", - "prebuild": "yarn clean", - "build": "bob", - "prepack": "bob-update-version", - "test": "jest --passWithNoTests --no-watchman --config ../../jest.config.js" - }, - "sideEffects": false, - "main": "dist/index.cjs.js", - "module": "dist/index.esm.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" - }, - "buildOptions": { - "input": "./src/index.ts" - }, - "devDependencies": { - "@ardatan/bob": "0.1.8", - "@types/jest": "24.0.24", - "graphql": "14.5.8", - "jest": "24.9.0", - "ts-jest": "24.2.0", - "typescript": "3.7.4" - }, - "dependencies": { - "@graphql-toolkit/code-file-loader": "0.7.5", - "@graphql-toolkit/common": "0.7.5", - "@graphql-toolkit/core": "0.7.5", - "@graphql-toolkit/file-loading": "0.7.5", - "@graphql-toolkit/graphql-file-loader": "0.7.5", - "@graphql-toolkit/json-file-loader": "0.7.5", - "@graphql-toolkit/schema-merging": "0.7.5", - "@graphql-toolkit/url-loader": "0.7.5" - }, - "publishConfig": { - "access": "public", - "directory": "dist" - } -} diff --git a/packages/graphql-toolkit/src/index.ts b/packages/graphql-toolkit/src/index.ts deleted file mode 100644 index 9ad96a45..00000000 --- a/packages/graphql-toolkit/src/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -export * from '@graphql-toolkit/common'; -export * from '@graphql-toolkit/core'; -export * from '@graphql-toolkit/file-loading'; -export * from '@graphql-toolkit/schema-merging'; - -import { JsonFileLoader } from '@graphql-toolkit/json-file-loader'; -import { LoadFromUrlOptions, UrlLoader } from '@graphql-toolkit/url-loader'; -import { CodeFileLoader, CodeFileLoaderOptions } from '@graphql-toolkit/code-file-loader'; -import { GraphQLFileLoader, GraphQLFileLoaderOptions } from '@graphql-toolkit/graphql-file-loader'; -import { Source, Loader } from '@graphql-toolkit/common'; -import { GraphQLSchema, BuildSchemaOptions } from 'graphql'; -import { LoadTypedefsOptions, loadTypedefsUsingLoaders, loadDocumentsUsingLoaders, loadSchemaUsingLoaders } from '@graphql-toolkit/core'; - -export const DEFAULT_SCHEMA_LOADERS: Loader[] = [new UrlLoader(), new JsonFileLoader(), new GraphQLFileLoader(), new CodeFileLoader()]; -export const DEFAULT_DOCUMENTS_LOADERS: Loader[] = [new GraphQLFileLoader(), new CodeFileLoader()]; - -export async function loadTypedefs( - pointerOrPointers: string | string[], - options: LoadTypedefsOptions = {}, - filterKinds: string[] = [], - cwd = process.cwd(), - loaders: Loader[] = DEFAULT_SCHEMA_LOADERS -): Promise { - return loadTypedefsUsingLoaders(loaders, pointerOrPointers, options, filterKinds, cwd); -} - -export async function loadDocuments(pointerOrPointers: string | string[], options: LoadTypedefsOptions = {}, cwd = process.cwd(), loaders: Loader[] = DEFAULT_DOCUMENTS_LOADERS): Promise { - return loadDocumentsUsingLoaders(loaders, pointerOrPointers, options, cwd); -} - -export async function loadSchema( - pointerOrPointers: string | string[], - options: BuildSchemaOptions & LoadTypedefsOptions = {}, - cwd = process.cwd(), - loaders: Loader[] = DEFAULT_SCHEMA_LOADERS -): Promise { - return loadSchemaUsingLoaders(loaders, pointerOrPointers, options, cwd); -} diff --git a/packages/graphql-toolkit/tsconfig.json b/packages/graphql-toolkit/tsconfig.json deleted file mode 100644 index 780ddafb..00000000 --- a/packages/graphql-toolkit/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "resolveJsonModule": true, - "importHelpers": true, - "experimentalDecorators": true, - "module": "esnext", - "target": "es2018", - "lib": ["esnext"], - "suppressImplicitAnyIndexErrors": true, - "moduleResolution": "node", - "emitDecoratorMetadata": true, - "sourceMap": true, - "declaration": true, - "outDir": "./dist/", - "noImplicitAny": false, - "noImplicitThis": true, - "alwaysStrict": true, - "noImplicitReturns": true, - "noUnusedLocals": false, - "noUnusedParameters": false - }, - "exclude": ["node_modules", "tests", "dist"] -} diff --git a/packages/loaders/apollo-engine/src/index.ts b/packages/loaders/apollo-engine/src/index.ts index 8485d031..8b029576 100644 --- a/packages/loaders/apollo-engine/src/index.ts +++ b/packages/loaders/apollo-engine/src/index.ts @@ -1,7 +1,6 @@ -import { SchemaLoader, printSchemaWithDirectives, fixSchemaAst } from '@graphql-toolkit/common'; +import { SchemaLoader, SingleFileOptions } from '@graphql-toolkit/common'; import { ClientConfig } from 'apollo-language-server'; import { EngineSchemaProvider } from 'apollo-language-server/lib/providers/schema/engine'; -import { parse } from 'graphql'; export class ApolloEngineLoader implements SchemaLoader { loaderId() { @@ -10,16 +9,12 @@ export class ApolloEngineLoader implements SchemaLoader { async canLoad(ptr: string) { return typeof ptr === 'string' && ptr === 'apollo-engine'; } - async load(_: 'apollo-engine', options: ClientConfig) { + async load(_: 'apollo-engine', options: ClientConfig & SingleFileOptions) { const engineSchemaProvider = new EngineSchemaProvider(options); - const resolvedSchema = await engineSchemaProvider.resolveSchema({}); - const schema = fixSchemaAst(resolvedSchema, options as any); + const schema = await engineSchemaProvider.resolveSchema({}); return { location: 'apollo-engine', - get document() { - return parse(printSchemaWithDirectives(schema)); - }, schema, }; } diff --git a/packages/loaders/code-file/src/index.ts b/packages/loaders/code-file/src/index.ts index 1109e575..a640fc98 100644 --- a/packages/loaders/code-file/src/index.ts +++ b/packages/loaders/code-file/src/index.ts @@ -1,6 +1,6 @@ -import { DocumentNode, GraphQLSchema, parse, IntrospectionQuery, buildClientSchema, Source as GraphQLSource } from 'graphql'; +import { DocumentNode, GraphQLSchema, parse, IntrospectionQuery, buildClientSchema } from 'graphql'; import { resolve, isAbsolute, extname } from 'path'; -import { SchemaPointerSingle, DocumentPointerSingle, debugLog, printSchemaWithDirectives, Source, UniversalLoader, asArray, fixWindowsPath, isValidPath, fixSchemaAst } from '@graphql-toolkit/common'; +import { SchemaPointerSingle, DocumentPointerSingle, debugLog, SingleFileOptions, Source, UniversalLoader, asArray, fixWindowsPath, isValidPath, fixSchemaAst } from '@graphql-toolkit/common'; import { existsSync } from 'fs'; import { gqlPluckFromFile, GraphQLTagPluckOptions } from '@graphql-toolkit/graphql-tag-pluck'; @@ -90,7 +90,7 @@ async function tryToLoadFromCodeAst(filePath: string, options?: CodeFileLoaderOp } } -export type CodeFileLoaderOptions = { forceRawSDL: boolean; noRequire?: boolean; cwd?: string; require?: string | string[]; pluckConfig?: GraphQLTagPluckOptions }; +export type CodeFileLoaderOptions = { require?: string | string[]; pluckConfig?: GraphQLTagPluckOptions } & SingleFileOptions; const CODE_FILE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.vue']; @@ -114,73 +114,52 @@ export class CodeFileLoader implements UniversalLoader { } async load(pointer: SchemaPointerSingle | DocumentPointerSingle, options: CodeFileLoaderOptions): Promise { - let loaded: GraphQLSchema | DocumentNode | null = null; const normalizedFilePath = isAbsolute(pointer) ? pointer : resolve(options.cwd || process.cwd(), pointer); try { const rawSDL = await tryToLoadFromCodeAst(normalizedFilePath, options); - if (rawSDL) { - if (options && options.forceRawSDL) { - return { - location: normalizedFilePath, - get document() { - return parse(new GraphQLSource(rawSDL, normalizedFilePath)); - }, - rawSDL, - }; - } else { - return { - location: normalizedFilePath, - document: parse(new GraphQLSource(rawSDL, normalizedFilePath)), - rawSDL, - }; - } + return { + location: normalizedFilePath, + rawSDL, + }; } } catch (e) { - debugLog(`Failed to load schema from code file "${normalizedFilePath}" using AST: ${e.message}`); + debugLog(`Failed to load schema from code file "${normalizedFilePath}": ${e.message}`); throw e; } - if (!loaded && !options.noRequire) { + if (!options.noRequire) { if (options && options.require) { await Promise.all(asArray(options.require).map(m => import(m))); } - const schemaOrDocument = await tryToLoadFromExport(normalizedFilePath); - if (schemaOrDocument instanceof GraphQLSchema) { - const schema = fixSchemaAst(schemaOrDocument, options as any); + let loaded = await tryToLoadFromExport(normalizedFilePath); + loaded = loaded['data'] || loaded; + if (loaded instanceof GraphQLSchema) { + const schema = fixSchemaAst(loaded, options); return { - get document() { - return parse(new GraphQLSource(printSchemaWithDirectives(schema), normalizedFilePath)); - }, - schema, location: normalizedFilePath, + schema, }; - } else if (typeof schemaOrDocument === 'string') { + } else if (typeof loaded === 'string') { return { - get document() { - return parse(new GraphQLSource(schemaOrDocument as string, normalizedFilePath)); - }, location: normalizedFilePath, - rawSDL: schemaOrDocument, + rawSDL: loaded, }; - } else if ('kind' in schemaOrDocument && schemaOrDocument.kind === 'Document') { + } else if ('kind' in loaded && loaded.kind === 'Document') { return { - document: schemaOrDocument, location: normalizedFilePath, + document: loaded, }; - } else { + } else if ('__schema' in loaded) { return { - document: parse(new GraphQLSource(printSchemaWithDirectives(buildClientSchema(schemaOrDocument['data'] ? schemaOrDocument['data'] : schemaOrDocument)))), + schema: buildClientSchema(loaded, options), location: normalizedFilePath, }; } } - return { - document: null, - location: normalizedFilePath, - }; + return null; } } diff --git a/packages/loaders/git/src/index.ts b/packages/loaders/git/src/index.ts index 1f968598..850032bc 100644 --- a/packages/loaders/git/src/index.ts +++ b/packages/loaders/git/src/index.ts @@ -1,7 +1,5 @@ -import { buildClientSchema, printSchema, parse, DocumentNode, Source as GraphQLSource, Kind, ParseOptions } from 'graphql'; -import { UniversalLoader, parseGraphQLSDL, parseGraphQLJSON } from '@graphql-toolkit/common'; +import { UniversalLoader, parseGraphQLSDL, parseGraphQLJSON, SingleFileOptions } from '@graphql-toolkit/common'; import simplegit from 'simple-git/promise'; -import { GraphQLSchemaValidationOptions } from 'graphql/type/schema'; // git:branch:path/to/file function extractData( @@ -22,8 +20,6 @@ function extractData( }; } -export type GitLoaderOptions = ParseOptions & GraphQLSchemaValidationOptions; - export class GitLoader implements UniversalLoader { loaderId() { return 'git-loader'; @@ -31,7 +27,7 @@ export class GitLoader implements UniversalLoader { async canLoad(pointer: string) { return typeof pointer === 'string' && pointer.toLowerCase().startsWith('git:'); } - async load(pointer: string, options: GitLoaderOptions) { + async load(pointer: string, options: SingleFileOptions) { const { ref, path } = extractData(pointer); const git = simplegit(); diff --git a/packages/loaders/github/src/index.ts b/packages/loaders/github/src/index.ts index aff64c10..c3de0434 100644 --- a/packages/loaders/github/src/index.ts +++ b/packages/loaders/github/src/index.ts @@ -1,7 +1,5 @@ -import { buildClientSchema, printSchema, parse, DocumentNode, ParseOptions } from 'graphql'; -import { UniversalLoader, parseGraphQLSDL, parseGraphQLJSON } from '@graphql-toolkit/common'; +import { UniversalLoader, parseGraphQLSDL, parseGraphQLJSON, SingleFileOptions } from '@graphql-toolkit/common'; import { fetch } from 'cross-fetch'; -import { GraphQLSchemaValidationOptions } from 'graphql/type/schema'; // github:owner/name#ref:path/to/file function extractData( @@ -24,7 +22,7 @@ function extractData( }; } -export interface GithubLoaderOptions extends ParseOptions, GraphQLSchemaValidationOptions { +export interface GithubLoaderOptions extends SingleFileOptions { token: string; } diff --git a/packages/loaders/graphql-file/src/index.ts b/packages/loaders/graphql-file/src/index.ts index 528ce47e..f173f6b1 100644 --- a/packages/loaders/graphql-file/src/index.ts +++ b/packages/loaders/graphql-file/src/index.ts @@ -1,39 +1,16 @@ -import { Source, UniversalLoader, DocumentPointerSingle, SchemaPointerSingle, isValidPath } from '@graphql-toolkit/common'; -import { parse, Source as GraphQLSource, Kind, DocumentNode, ParseOptions } from 'graphql'; +import { Source, UniversalLoader, DocumentPointerSingle, SchemaPointerSingle, isValidPath, parseGraphQLSDL, SingleFileOptions } from '@graphql-toolkit/common'; +import { ParseOptions } from 'graphql'; import { extname, isAbsolute, resolve } from 'path'; import { readFileSync, existsSync } from 'fs'; -export type GraphQLFileLoaderOptions = { skipGraphQLImport?: boolean; cwd?: string } & ParseOptions; - const GQL_EXTENSIONS = ['.gql', '.graphql', '.graphqls']; -export function parseGraphQLSDL(location: string, rawSDL: string, options: ParseOptions) { - let document: DocumentNode; - try { - document = parse(new GraphQLSource(rawSDL, location), options); - } catch (e) { - if (e.message.includes('EOF')) { - document = { - kind: Kind.DOCUMENT, - definitions: [], - }; - } else { - throw e; - } - } - return { - location, - document, - rawSDL, - }; -} - -export class GraphQLFileLoader implements UniversalLoader { +export class GraphQLFileLoader implements UniversalLoader { loaderId(): string { return 'graphql-file'; } - async canLoad(pointer: SchemaPointerSingle | DocumentPointerSingle, options: GraphQLFileLoaderOptions): Promise { + async canLoad(pointer: SchemaPointerSingle | DocumentPointerSingle, options: SingleFileOptions): Promise { if (isValidPath(pointer)) { const extension = extname(pointer).toLowerCase(); if (GQL_EXTENSIONS.includes(extension)) { @@ -47,8 +24,8 @@ export class GraphQLFileLoader implements UniversalLoader { - const normalizedFilePath = isAbsolute(pointer) ? pointer : resolve(options.cwd || process.cwd(), pointer); + async load(pointer: SchemaPointerSingle | DocumentPointerSingle, options: SingleFileOptions): Promise { + const normalizedFilePath = isAbsolute(pointer) ? pointer : resolve(options.cwd, pointer); const rawSDL = readFileSync(normalizedFilePath, 'utf-8').trim(); return parseGraphQLSDL(pointer, rawSDL, options); diff --git a/packages/loaders/json-file/src/index.ts b/packages/loaders/json-file/src/index.ts index 7fb16683..83694141 100644 --- a/packages/loaders/json-file/src/index.ts +++ b/packages/loaders/json-file/src/index.ts @@ -1,58 +1,13 @@ import { extname, isAbsolute, resolve as resolvePath } from 'path'; -import { IntrospectionQuery, buildClientSchema, parse } from 'graphql'; -import { Source, printSchemaWithDirectives, SchemaPointerSingle, DocumentLoader, isValidPath } from '@graphql-toolkit/common'; +import { Source, parseGraphQLJSON, SchemaPointerSingle, DocumentLoader, isValidPath, SingleFileOptions } from '@graphql-toolkit/common'; import { existsSync, readFileSync } from 'fs'; -function stripBOM(content: string): string { - content = content.toString(); - // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) - // because the buffer-to-string conversion in `fs.readFileSync()` - // translates it to FEFF, the UTF-16 BOM. - if (content.charCodeAt(0) === 0xfeff) { - content = content.slice(1); - } - - return content; -} - -function parseBOM(content: string): any { - return JSON.parse(stripBOM(content)); -} - -export function parseGraphQLJSON(pointer: string, jsonContent: string): Source { - let parsedJson = parseBOM(jsonContent); - - if (parsedJson['data']) { - parsedJson = parsedJson['data']; - } - - if (parsedJson.kind === 'Document') { - const document = parsedJson; - return { - location: pointer, - document, - }; - } else if (parsedJson.__schema) { - const schema = buildClientSchema(parsedJson, options as any); - return { - location: pointer, - document: parse(printSchemaWithDirectives(schema)), - schema, - }; - } - throw new Error(`Not valid content`); -} - -export interface JsonFileLoaderOptions { - cwd?: string; -} - export class JsonFileLoader implements DocumentLoader { loaderId(): string { return 'json-file'; } - async canLoad(pointer: SchemaPointerSingle, options: JsonFileLoaderOptions): Promise { + async canLoad(pointer: SchemaPointerSingle, options: SingleFileOptions): Promise { if (isValidPath(pointer)) { const extension = extname(pointer).toLowerCase(); if (extension === '.json') { @@ -66,12 +21,12 @@ export class JsonFileLoader implements DocumentLoader { return false; } - async load(pointer: SchemaPointerSingle, options: JsonFileLoaderOptions): Promise { + async load(pointer: SchemaPointerSingle, options: SingleFileOptions): Promise { const normalizedFilepath = isAbsolute(pointer) ? pointer : resolvePath(options.cwd || process.cwd(), pointer); try { const jsonContent = readFileSync(normalizedFilepath, 'utf8'); - return parseGraphQLJSON(pointer, jsonContent); + return parseGraphQLJSON(pointer, jsonContent, options); } catch (e) { throw new Error(`Unable to read JSON file: ${normalizedFilepath}`); } diff --git a/packages/loaders/module/src/index.ts b/packages/loaders/module/src/index.ts index ffadf288..941fdcfb 100644 --- a/packages/loaders/module/src/index.ts +++ b/packages/loaders/module/src/index.ts @@ -1,5 +1,5 @@ import { parse, isSchema } from 'graphql'; -import { UniversalLoader, fixSchemaAst, printSchemaWithDirectives } from '@graphql-toolkit/common'; +import { UniversalLoader, fixSchemaAst, printSchemaWithDirectives, SingleFileOptions } from '@graphql-toolkit/common'; // module:node/module#export function extractData( @@ -27,7 +27,7 @@ export class ModuleLoader implements UniversalLoader { async canLoad(pointer: string) { return typeof pointer === 'string' && pointer.toLowerCase().startsWith('module:'); } - async load(pointer: string, options: any) { + async load(pointer: string, options: SingleFileOptions) { const { modulePath, exportName } = extractData(pointer); let thing: any; diff --git a/packages/loaders/url/src/index.ts b/packages/loaders/url/src/index.ts index 6cf7e6e8..86a99e46 100644 --- a/packages/loaders/url/src/index.ts +++ b/packages/loaders/url/src/index.ts @@ -1,5 +1,5 @@ import { buildClientSchema, parse, IntrospectionQuery, print, getIntrospectionQuery } from 'graphql'; -import { SchemaPointerSingle, Source, printSchemaWithDirectives, DocumentLoader, fixSchemaAst } from '@graphql-toolkit/common'; +import { SchemaPointerSingle, Source, DocumentLoader, SingleFileOptions } from '@graphql-toolkit/common'; import { isUri } from 'valid-url'; import { fetch as crossFetch } from 'cross-fetch'; import { makeRemoteExecutableSchema } from '@kamilkisiela/graphql-tools'; @@ -9,7 +9,7 @@ export type FetchFn = typeof import('cross-fetch').fetch; type Headers = Record | Array>; -export interface LoadFromUrlOptions { +export interface LoadFromUrlOptions extends SingleFileOptions { headers?: Headers; customFetch?: FetchFn | string; method?: 'GET' | 'POST'; @@ -95,14 +95,10 @@ export class UrlLoader implements DocumentLoader { schema: clientSchema, fetcher, }); - const schema = fixSchemaAst(remoteExecutableSchema, options as any); return { location: pointer, - get document() { - return parse(printSchemaWithDirectives(schema)); - }, - schema, + schema: remoteExecutableSchema, }; } } From 27f81355d95794496ae027eb8b7e27a5140abf76 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Sun, 29 Dec 2019 18:59:54 +0300 Subject: [PATCH 3/8] New implementation --- packages/common/src/fix-schema-ast.ts | 38 +- packages/common/src/loaders.ts | 3 - packages/core/src/import-parser/index.ts | 179 +- packages/core/src/load-typedefs.ts | 103 +- .../loaders/schema/import-schema.spec.ts | 1572 +++++++++-------- .../tests/load-from-code-file.spec.ts | 18 +- 6 files changed, 1011 insertions(+), 902 deletions(-) diff --git a/packages/common/src/fix-schema-ast.ts b/packages/common/src/fix-schema-ast.ts index b3107325..fcaf56c6 100644 --- a/packages/common/src/fix-schema-ast.ts +++ b/packages/common/src/fix-schema-ast.ts @@ -1,24 +1,24 @@ -import { GraphQLSchema, buildASTSchema, parse, BuildSchemaOptions } from 'graphql'; +import { GraphQLSchema, buildASTSchema, parse, BuildSchemaOptions, ParseOptions } from 'graphql'; import { printSchemaWithDirectives } from '.'; -export function fixSchemaAst(schema: GraphQLSchema, options?: BuildSchemaOptions) { - if (!schema.astNode) { - Object.defineProperty(schema, 'astNode', { - get: () => { - return buildASTSchema(parse(printSchemaWithDirectives(schema)), { - commentDescriptions: true, - ...(options || {}), - }).astNode; - }, - }); - Object.defineProperty(schema, 'extensionASTNodes', { - get: () => { - return buildASTSchema(parse(printSchemaWithDirectives(schema)), { - commentDescriptions: true, - ...(options || {}), - }).extensionASTNodes; - }, - }); +export function fixSchemaAst(schema: GraphQLSchema, options: BuildSchemaOptions) { + if (!schema.astNode || !schema.extensionASTNodes) { + const schemaWithValidAst = buildASTSchema( + parse(printSchemaWithDirectives(schema), { + noLocation: true, + ...(options || {}), + }), + { + commentDescriptions: true, + ...(options || {}), + } + ); + if (!schema.astNode) { + schema.astNode = schemaWithValidAst.astNode; + } + if (!schema.extensionASTNodes) { + schema.extensionASTNodes = schemaWithValidAst.extensionASTNodes; + } } return schema; } diff --git a/packages/common/src/loaders.ts b/packages/common/src/loaders.ts index b5cc3933..f7e88d75 100644 --- a/packages/common/src/loaders.ts +++ b/packages/common/src/loaders.ts @@ -13,9 +13,6 @@ export type SingleFileOptions = ParseOptions & GraphQLSchemaValidationOptions & BuildSchemaOptions & { noRequire?: boolean; - cache?: { [key: string]: Source }; - loaders: Loader[]; - filterKinds?: string[]; cwd?: string; }; diff --git a/packages/core/src/import-parser/index.ts b/packages/core/src/import-parser/index.ts index d2870fab..01da1487 100644 --- a/packages/core/src/import-parser/index.ts +++ b/packages/core/src/import-parser/index.ts @@ -1,10 +1,13 @@ -import { DefinitionNode } from 'graphql'; -import { groupBy, includes } from 'lodash'; +import { DefinitionNode, parse, ObjectTypeDefinitionNode, DocumentNode, Kind } from 'graphql'; +import { groupBy, keyBy, isEqual, uniqBy } from 'lodash'; import resolveFrom from 'resolve-from'; +import { loadSingleFile } from '../load-typedefs'; +import { LoadSchemaOptions } from '../schema'; -import { ValidDefinitionNode } from './definition'; -import { dirname, join } from 'path'; +import { completeDefinitionPool, ValidDefinitionNode } from './definition'; import { realpathSync } from 'fs'; +import { join, dirname } from 'path'; +import { Source } from '@graphql-toolkit/common'; /** * Describes the information from a single import line @@ -15,6 +18,8 @@ export interface RawModule { from: string; } +const rootFields = ['Query', 'Mutation', 'Subscription']; + const gqlExt = /\.g(raph)?ql$/; function isGraphQLFile(f: string) { return gqlExt.test(f); @@ -58,6 +63,66 @@ export function parseSDL(sdl: string): RawModule[] { .map(parseImportLine); } +/** + * Main entry point. Recursively process all import statement in a schema + * + * @param filePath File path to the initial schema file + * @returns Single bundled schema with all imported types + */ +export async function processImportSyntax(documentSource: Source, options: LoadSchemaOptions): Promise { + const mergeableTypes = options.mergeableTypes || []; + const allMergeableTypes = [...mergeableTypes, ...rootFields]; + let document = documentSource.document; + + // Recursively process the imports, starting by importing all types from the initial schema + await collectDefinitions(['*'], documentSource, options); + + // Post processing of the final schema (missing types, unused types, etc.) + // Query, Mutation and Subscription should be merged + // And should always be in the first set, to make sure they + // are not filtered out. + const firstTypes = options.typeDefinitions.flat().filter(d => allMergeableTypes.includes(d.name.value)); + const secondFirstTypes = options.typeDefinitions[0].filter(d => !allMergeableTypes.includes(d.name.value)); + const otherFirstTypes = options.typeDefinitions + .slice(1) + .flat() + .filter(d => !allMergeableTypes.includes(d.name.value)); + + const firstSet = firstTypes.concat(secondFirstTypes, otherFirstTypes); + const processedTypeNames: string[] = []; + const mergedFirstTypes = []; + for (const type of firstSet) { + if (!processedTypeNames.includes(type.name.value)) { + processedTypeNames.push(type.name.value); + mergedFirstTypes.push(type); + } else { + const existingType = mergedFirstTypes.find(t => t.name.value === type.name.value) as any; + + existingType.fields = uniqBy(existingType.fields.concat((type as ObjectTypeDefinitionNode).fields), 'name.value'); + } + } + + (document as any).definitions = completeDefinitionPool(options.allDefinitions.flat(), firstSet, options.typeDefinitions.flat()); +} + +/** + * Parses a schema into a graphql DocumentNode. + * If the schema is empty a DocumentNode with empty definitions will be created. + * + * @param sdl Schema to parse + * @returns A graphql DocumentNode with definitions of the parsed sdl. + */ +export function getDocumentFromSDL(sdl: string): DocumentNode { + if (isEmptySDL(sdl)) { + return { + kind: Kind.DOCUMENT, + definitions: [], + }; + } else { + return parse(sdl, { noLocation: true }); + } +} + /** * Check if a schema contains any type definitions at all. * @@ -88,26 +153,7 @@ export function resolveModuleFilePath(filePath: string, importFrom: string): str return realpathSync(join(dirName, importFrom)); } catch (e) { if (e.code === 'ENOENT') { - const addedExtensions = new Array(); - for (const graphqlFileExtension of ['.gql', '.gqls', '.graphql', '.graphqls']) { - if (!(graphqlFileExtension in require.extensions)) { - require.extensions[graphqlFileExtension] = () => ({}); - addedExtensions.push(graphqlFileExtension); - } - } - function cleanRequireExtensions() { - for (const extension of addedExtensions) { - delete require.extensions[extension]; - } - } - try { - const resolvedPath = resolveFrom(dirName, importFrom); - cleanRequireExtensions(); - return resolvedPath; - } catch (e) { - cleanRequireExtensions(); - throw e; - } + return resolveFrom(dirName, importFrom); } } } @@ -115,6 +161,52 @@ export function resolveModuleFilePath(filePath: string, importFrom: string): str return importFrom; } +/** + * Recursively process all schema files. Keeps track of both the filtered + * type definitions, and all type definitions, because they might be needed + * in post-processing (to add missing types) + * + * @param imports Types specified in the import statement + * @param sdl Current schema + * @param filePath File location for current schema + * @param Tracking of processed schemas (for circular dependencies) + * @param Tracking of imported type definitions per schema + * @param Tracking of all type definitions per schema + * @returns Both the collection of all type definitions, and the collection of imported type definitions + */ +export async function collectDefinitions(imports: string[], documentSource: Source, options: LoadSchemaOptions): Promise { + // Get TypeDefinitionNodes from current schema + const document = documentSource.document; + + // Add all definitions to running total + options.allDefinitions.push(filterTypeDefinitions(document.definitions)); + + // Filter TypeDefinitionNodes by type and defined imports + const currentTypeDefinitions = filterImportedDefinitions(imports, document.definitions, options.allDefinitions); + + // Add typedefinitions to running total + options.typeDefinitions.push(currentTypeDefinitions); + + // Read imports from current file + const rawModules = parseSDL(documentSource.rawSDL); + + // Process each file (recursively) + await Promise.all( + rawModules.map(async m => { + // If it was not yet processed (in case of circular dependencies) + const moduleFilePath = resolveModuleFilePath(documentSource.location, m.from); + + const processedFile = options.processedFiles.get(moduleFilePath); + if (!processedFile || !processedFile.find(rModule => isEqual(rModule, m))) { + // Mark this specific import line as processed for this file (for cicular dependency cases) + options.processedFiles.set(moduleFilePath, processedFile ? processedFile.concat(m) : [m]); + const result = await loadSingleFile(moduleFilePath, options); + await collectDefinitions(m.imports, result, options); + } + }) + ); +} + /** * Filter the types loaded from a schema, first by relevant types, * then by the types specified in the import statement. @@ -123,30 +215,35 @@ export function resolveModuleFilePath(filePath: string, importFrom: string): str * @param typeDefinitions All definitions from a schema * @returns Filtered collection of type definitions */ -export function filterImportedDefinitions(imports: string[], typeDefinitions: ReadonlyArray) { +function filterImportedDefinitions(imports: string[], typeDefinitions: ReadonlyArray, allDefinitions: ValidDefinitionNode[][] = []): ValidDefinitionNode[] { // This should do something smart with fields - if (includes(imports, '*')) { - return typeDefinitions; + const filteredDefinitions = filterTypeDefinitions(typeDefinitions); + + if (imports.includes('*')) { + if (imports.length === 1 && imports[0] === '*' && allDefinitions.length > 1) { + const previousTypeDefinitions: { [key: string]: DefinitionNode } = keyBy( + allDefinitions + .slice(0, allDefinitions.length - 1) + .flat() + .filter(def => !rootFields.includes(def.name.value)), + def => def.name.value + ); + return typeDefinitions.filter(typeDef => typeDef.kind === 'ObjectTypeDefinition' && previousTypeDefinitions[typeDef.name.value]) as ObjectTypeDefinitionNode[]; + } + return filteredDefinitions; } else { - const result = typeDefinitions.filter(d => { - if ('name' in d) { - return includes( - imports.map(i => i.split('.')[0]), - d.name.value - ); - } - return true; - }); + const importedTypes = imports.map(i => i.split('.')[0]); + const result = filteredDefinitions.filter(d => importedTypes.includes(d.name.value)); const fieldImports = imports.filter(i => i.split('.').length > 1); const groupedFieldImports = groupBy(fieldImports, x => x.split('.')[0]); for (const rootType in groupedFieldImports) { const fields = groupedFieldImports[rootType].map(x => x.split('.')[1]); - const objectTypeDefinition: any = typeDefinitions.find(def => 'name' in def && def.name.value === rootType); + const objectTypeDefinition: any = filteredDefinitions.find(def => def.name.value === rootType); - if ('fields' in objectTypeDefinition) { - objectTypeDefinition.fields = objectTypeDefinition.fields.filter((f: any) => includes(fields, f.name.value) || includes(fields, '*')); + if (objectTypeDefinition && 'fields' in objectTypeDefinition && !fields.includes('*')) { + objectTypeDefinition.fields = objectTypeDefinition.fields.filter((f: any) => fields.includes(f.name.value) || fields.includes('*')); } } @@ -161,6 +258,6 @@ export function filterImportedDefinitions(imports: string[], typeDefinitions: Re * @returns Relevant type definitions */ export function filterTypeDefinitions(definitions: ReadonlyArray): ValidDefinitionNode[] { - const validKinds = ['DirectiveDefinition', 'ScalarTypeDefinition', 'ObjectTypeDefinition', 'ObjectTypeExtension', 'InterfaceTypeDefinition', 'EnumTypeDefinition', 'UnionTypeDefinition', 'InputObjectTypeDefinition']; - return definitions.filter(d => includes(validKinds, d.kind)).map(d => d as ValidDefinitionNode); + return definitions.filter(d => validKinds.includes(d.kind)).map(d => d as ValidDefinitionNode); } +const validKinds = ['DirectiveDefinition', 'ScalarTypeDefinition', 'ObjectTypeDefinition', 'ObjectTypeExtension', 'InterfaceTypeDefinition', 'EnumTypeDefinition', 'UnionTypeDefinition', 'InputObjectTypeDefinition']; diff --git a/packages/core/src/load-typedefs.ts b/packages/core/src/load-typedefs.ts index 70d2d265..9dc38d00 100644 --- a/packages/core/src/load-typedefs.ts +++ b/packages/core/src/load-typedefs.ts @@ -1,16 +1,25 @@ -import { Source as GraphQLSource, GraphQLSchema, parse, Kind } from 'graphql'; -import { Source, asArray, isDocumentString, debugLog, fixWindowsPath, printSchemaWithDirectives, parseGraphQLSDL, fixSchemaAst, SingleFileOptions } from '@graphql-toolkit/common'; +import { GraphQLSchema, parse, Kind, Source as GraphQLSource, print } from 'graphql'; +import { Source, asArray, isDocumentString, debugLog, fixWindowsPath, printSchemaWithDirectives, parseGraphQLSDL, fixSchemaAst, SingleFileOptions, Loader } from '@graphql-toolkit/common'; import { join } from 'path'; import isGlob from 'is-glob'; import globby from 'globby'; import { filterKind } from './filter-document-kind'; -import { parseSDL, isEmptySDL, filterImportedDefinitions, resolveModuleFilePath } from './import-parser'; +import { RawModule, processImportSyntax, isEmptySDL } from './import-parser'; +import { ValidDefinitionNode } from './import-parser/definition'; export type LoadTypedefsOptions = SingleFileOptions & ExtraConfig & { + processedFiles?: Map; + typeDefinitions?: ValidDefinitionNode[][]; + allDefinitions?: ValidDefinitionNode[][]; + cache?: { [key: string]: Source }; + loaders: Loader[]; + filterKinds?: string[]; ignore?: string | string[]; preresolvedTypeDefs?: { [key: string]: string }; sort?: boolean; + skipGraphQLImport?: boolean; + forceGraphQLImport?: boolean; }; export type UnnormalizedTypeDefPointer = { [key: string]: any } | string; @@ -72,18 +81,13 @@ export async function loadTypedefs(pointerOrPointers: Unn options.cache = options.cache || {}; options.cwd = options.cwd || process.cwd(); options.sort = 'sort' in options ? options.sort : true; + options.processedFiles = options.processedFiles || new Map(); + options.allDefinitions = options.allDefinitions || []; + options.typeDefinitions = options.typeDefinitions || []; for (const pointer in normalizedPointerOptionsMap) { const pointerOptions = normalizedPointerOptionsMap[pointer]; - if (options.preresolvedTypeDefs && pointer in options.preresolvedTypeDefs) { - loadPromises$.push( - Promise.resolve().then(async () => { - const result = parseGraphQLSDL(pointer, options.preresolvedTypeDefs[pointer], options); - found.push(result); - options.cache[pointer] = result; - }) - ); - } else if (isDocumentString(pointer)) { + if (isDocumentString(pointer)) { loadPromises$.push( Promise.resolve().then(async () => { const result = parseGraphQLSDL(`${stringToHash(pointer)}.graphql`, pointer, options); @@ -209,51 +213,43 @@ export async function loadTypedefs(pointerOrPointers: Unn await Promise.all(loadPromises$); - const importsLoadPromises: Promise[] = []; - const foundValid: Source[] = []; - for (const partialSource of found) { - if (partialSource) { - const resultSource: Source = { ...partialSource }; - if (resultSource.schema) { - resultSource.schema = fixSchemaAst(resultSource.schema, options as any); - resultSource.rawSDL = printSchemaWithDirectives(resultSource.schema); - } - if (resultSource.rawSDL) { - const imports = parseSDL(resultSource.rawSDL); - for (const i of imports) { - importsLoadPromises.push( - Promise.resolve().then(async () => { - const sources = await loadTypedefs(resolveModuleFilePath(resultSource.location, i.from), options); - for (const source of sources) { - foundValid.unshift({ - ...source, - document: { - ...source.document, - definitions: filterImportedDefinitions(i.imports, source.document.definitions), - }, - }); - } - }) - ); + await Promise.all( + found.map(async partialSource => { + if (partialSource) { + const resultSource: Source = { ...partialSource }; + if (resultSource.schema) { + resultSource.schema = fixSchemaAst(resultSource.schema, options); + resultSource.rawSDL = printSchemaWithDirectives(resultSource.schema); } - if (!isEmptySDL(resultSource.rawSDL)) { - resultSource.document = parse(new GraphQLSource(resultSource.rawSDL, resultSource.location), options); - } - } - if (resultSource.document) { - if (options.filterKinds) { - resultSource.document = filterKind(resultSource.document, options.filterKinds); + if (resultSource.rawSDL) { + if (isEmptySDL(resultSource.rawSDL)) { + resultSource.document = { + kind: Kind.DOCUMENT, + definitions: [], + }; + } else { + resultSource.document = parse(new GraphQLSource(resultSource.rawSDL, resultSource.location), options); + } } - if (resultSource.document.definitions && resultSource.document.definitions.length > 0) { - foundValid.push(resultSource); + if (resultSource.document) { + if (options.filterKinds) { + resultSource.document = filterKind(resultSource.document, options.filterKinds); + } + if (!resultSource.rawSDL) { + resultSource.rawSDL = print(resultSource.document); + } + if (options.forceGraphQLImport || (!options.skipGraphQLImport && /^\#.*import /i.test(resultSource.rawSDL.trimLeft()))) { + await processImportSyntax(resultSource, options); + } + if (resultSource.document.definitions && resultSource.document.definitions.length > 0) { + foundValid.push(resultSource); + } } } - } - } - - await Promise.all(importsLoadPromises); + }) + ); const pointerList = Object.keys(normalizedPointerOptionsMap); if (pointerList.length > 0 && foundValid.length === 0) { @@ -263,10 +259,13 @@ export async function loadTypedefs(pointerOrPointers: Unn return options.sort ? foundValid.sort((left, right) => left.location.localeCompare(right.location)) : foundValid; } -export async function loadSingleFile(pointer: string, options: SingleFileOptions): Promise { +export async function loadSingleFile(pointer: string, options: LoadTypedefsOptions): Promise { if (pointer in options.cache) { return options.cache[pointer]; } + if (options.preresolvedTypeDefs && pointer in options.preresolvedTypeDefs) { + return parseGraphQLSDL(pointer, options.preresolvedTypeDefs[pointer], options); + } try { for (const loader of options.loaders) { const canLoad = await loader.canLoad(pointer, options); diff --git a/packages/core/tests/loaders/schema/import-schema.spec.ts b/packages/core/tests/loaders/schema/import-schema.spec.ts index e4fc6d3e..2fb2abdd 100644 --- a/packages/core/tests/loaders/schema/import-schema.spec.ts +++ b/packages/core/tests/loaders/schema/import-schema.spec.ts @@ -1,962 +1,972 @@ import { parseImportLine, parseSDL, loadTypedefs, LoadTypedefsOptions, OPERATION_KINDS } from '@graphql-toolkit/core'; import * as fs from 'fs' -import { print } from 'graphql'; +import { print, DocumentNode, Kind } from 'graphql'; import { JsonFileLoader } from '@graphql-toolkit/json-file-loader'; import { UrlLoader } from '@graphql-toolkit/url-loader'; import { CodeFileLoader } from '@graphql-toolkit/code-file-loader'; import { GraphQLFileLoader } from '@graphql-toolkit/graphql-file-loader'; import { mergeTypeDefs } from '@graphql-toolkit/schema-merging'; +import { parse } from 'graphql'; const importSchema = ( - schema: string, schemas?: { [name: string]: string }, options?: LoadTypedefsOptions -) => - loadTypedefs( - schema, { - loaders: [new UrlLoader(), new JsonFileLoader(), new GraphQLFileLoader(), new CodeFileLoader()], - filterKinds: OPERATION_KINDS, - preresolvedTypeDefs: schemas, - sort: false, - ...options, - }).then(r => print(mergeTypeDefs(r.map(r => r.document), { useSchemaDefinition: false }))); + schema: string, schemas?: { [name: string]: string }, options?: LoadTypedefsOptions +) => + loadTypedefs( + schema, { + loaders: [new UrlLoader(), new JsonFileLoader(), new GraphQLFileLoader(), new CodeFileLoader()], + filterKinds: OPERATION_KINDS, + preresolvedTypeDefs: schemas, + sort: false, + forceGraphQLImport: true, + ...options, + }).then(r => print(mergeTypeDefs(r.map(r => r.document), { useSchemaDefinition: false }))); test('parseImportLine: parse single import', () => { - expect(parseImportLine(`import A from "schema.graphql"`)).toEqual({ - imports: ['A'], - from: 'schema.graphql', - }) + expect(parseImportLine(`import A from "schema.graphql"`)).toEqual({ + imports: ['A'], + from: 'schema.graphql', + }) }) test('parseImportLine: optional semicolon', () => { - expect(parseImportLine(`import A from "schema.graphql";`)).toEqual({ - imports: ['A'], - from: 'schema.graphql', - }); + expect(parseImportLine(`import A from "schema.graphql";`)).toEqual({ + imports: ['A'], + from: 'schema.graphql', + }); }) test('parseImportLine: invalid', async () => { - expect(() => parseImportLine(`import from "schema.graphql"`)).toThrow(); + expect(() => parseImportLine(`import from "schema.graphql"`)).toThrow(); }) test('parseImportLine: invalid 2', async () => { - expect(() => parseImportLine(`import A from ""`)).toThrow(); + expect(() => parseImportLine(`import A from ""`)).toThrow(); }) test('parseImportLine: parse multi import', async () => { - expect(parseImportLine(`import A, B from "schema.graphql"`)).toEqual({ - imports: ['A', 'B'], - from: 'schema.graphql', - }) + expect(parseImportLine(`import A, B from "schema.graphql"`)).toEqual({ + imports: ['A', 'B'], + from: 'schema.graphql', + }) }) test('parseImportLine: parse multi import (weird spacing)', async () => { - expect(parseImportLine(`import A ,B from "schema.graphql"`)).toEqual({ - imports: ['A', 'B'], - from: 'schema.graphql', - }) + expect(parseImportLine(`import A ,B from "schema.graphql"`)).toEqual({ + imports: ['A', 'B'], + from: 'schema.graphql', + }) }) test('parseImportLine: different path', async () => { - expect(parseImportLine(`import A from "../new/schema.graphql"`)).toEqual({ - imports: ['A'], - from: '../new/schema.graphql', - }) + expect(parseImportLine(`import A from "../new/schema.graphql"`)).toEqual({ + imports: ['A'], + from: '../new/schema.graphql', + }) }) test('parseImportLine: module in node_modules', async () => { - expect(parseImportLine(`import A from "module-name"`)).toEqual({ - imports: ['A'], - from: 'module-name', - }) + expect(parseImportLine(`import A from "module-name"`)).toEqual({ + imports: ['A'], + from: 'module-name', + }) }) test('parseSDL: non-import comment', async () => { - expect(parseSDL(`#importent: comment`)).toEqual([]); + expect(parseSDL(`#importent: comment`)).toEqual([]); }) test('parse: multi line import', async () => { - const sdl = `\ -# import A from "a.graphql" -# import * from "b.graphql" - ` - expect(parseSDL(sdl)).toEqual([ - { - imports: ['A'], - from: 'a.graphql', - }, - { - imports: ['*'], - from: 'b.graphql', - }, - ]) + const sdl = `\ + # import A from "a.graphql" + # import * from "b.graphql" + ` + expect(parseSDL(sdl)).toEqual([ + { + imports: ['A'], + from: 'a.graphql', + }, + { + imports: ['*'], + from: 'b.graphql', + }, + ]) }) test('Module in node_modules', async () => { - const b = `\ -# import lower from './lower.graphql' -type B { - id: ID! - nickname: String! @lower -} -` - const lower = `\ -directive @lower on FIELD_DEFINITION -` - const expectedSDL = `\ -type A { - id: ID! - author: B! -} - -type B { - id: ID! - nickname: String! @lower -} - -directive @lower on FIELD_DEFINITION -` - const moduleDir = 'node_modules/graphql-import-test' - if (!fs.existsSync(moduleDir)) { - fs.mkdirSync(moduleDir) - } + const b = `\ + # import lower from './lower.graphql' + type B { + id: ID! + nickname: String! @lower + } + ` + const lower = `\ + directive @lower on FIELD_DEFINITION + ` + const expectedSDL = `\ + type A { + id: ID! + author: B! + } + + type B { + id: ID! + nickname: String! @lower + } + + directive @lower on FIELD_DEFINITION + ` + const moduleDir = 'node_modules/graphql-import-test' + if (!fs.existsSync(moduleDir)) { + fs.mkdirSync(moduleDir) + } - fs.writeFileSync(moduleDir + '/b.graphql', b) - fs.writeFileSync(moduleDir + '/lower.graphql', lower) - expect(await importSchema('tests/loaders/schema/fixtures/import-module/a.graphql')).toBe(expectedSDL) + fs.writeFileSync(moduleDir + '/b.graphql', b) + fs.writeFileSync(moduleDir + '/lower.graphql', lower) + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-module/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: imports only', async () => { - const expectedSDL = `\ -type Query { - first: String - second: Float - third: String -} -` - expect(await importSchema('tests/loaders/schema/fixtures/imports-only/all.graphql')).toBe(expectedSDL); + const expectedSDL = `\ + type Query { + first: String + second: Float + third: String + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/imports-only/all.graphql'))).toBe(normalizeDocumentString(expectedSDL)); }) test('importSchema: import .gql extension', async () => { - const expectedSDL = `\ -type A { - id: ID! -} -` - expect(await importSchema('tests/loaders/schema/fixtures/import-gql/a.gql')).toBe(expectedSDL) + const expectedSDL = `\ + type A { + id: ID! + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-gql/a.gql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: import duplicate', async () => { - const expectedSDL = `\ -type Query { - first: String - second: Float - third: String -} -` - expect(await importSchema('tests/loaders/schema/fixtures/import-duplicate/all.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type Query { + first: String + second: Float + third: String + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-duplicate/all.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: import nested', async () => { - const expectedSDL = `\ -type Query { - first: String - second: Float - third: String -} -` - expect(await importSchema('tests/loaders/schema/fixtures/import-nested/all.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type Query { + first: String + second: Float + third: String + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-nested/all.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: field types', async () => { - const expectedSDL = `\ -type A { - first: String - second: Float - b: B -} - -type B { - c: C - hello: String! -} - -type C { - id: ID! -} -` - expect(await importSchema('tests/loaders/schema/fixtures/field-types/a.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type A { + first: String + second: Float + b: B + } + + type B { + c: C + hello: String! + } + + type C { + id: ID! + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/field-types/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: enums', async () => { - const expectedSDL = `\ -type A { - first: String - second: Float - b: B -} - -enum B { - B1 - B2 - B3 -} -` - expect(await importSchema('tests/loaders/schema/fixtures/enums/a.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type A { + first: String + second: Float + b: B + } + + enum B { + B1 + B2 + B3 + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/enums/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: import all', async () => { - const expectedSDL = `\ -type A { - first: String - second: Float - b: B -} - -type B { - hello: String! - c1: C1 - c2: C2 -} - -type C1 { - id: ID! -} - -type C2 { - id: ID! -} -` - expect(await importSchema('tests/loaders/schema/fixtures/import-all/a.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type A { + first: String + second: Float + b: B + } + + type B { + hello: String! + c1: C1 + c2: C2 + } + + type C1 { + id: ID! + } + + type C2 { + id: ID! + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-all/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: import all from objects', async () => { - const schemaC = ` - type C1 { - id: ID! - } - - type C2 { - id: ID! - } - - type C3 { - id: ID! - } -` - - const schemaB = ` - # import * from 'schemaC' - type B { - hello: String! - c1: C1 - c2: C2 - } -` - - const schemaA = ` - # import B from 'schemaB' - type A { - # test 1 - first: String - second: Float - b: B - } -` - - const schemas = { - schemaA, - schemaB, - schemaC, - } - - const expectedSDL = `\ -type A { - first: String - second: Float - b: B -} - -type B { - hello: String! - c1: C1 - c2: C2 -} - -type C1 { - id: ID! -} + const schemaC = ` + type C1 { + id: ID! + } + + type C2 { + id: ID! + } + + type C3 { + id: ID! + } + ` + + const schemaB = ` + # import * from 'schemaC' + type B { + hello: String! + c1: C1 + c2: C2 + } + ` + + const schemaA = ` + # import B from 'schemaB' + type A { + # test 1 + first: String + second: Float + b: B + } + ` + + const schemas = { + schemaA, + schemaB, + schemaC, + } -type C2 { - id: ID! -} -` - expect(await importSchema(schemaA, schemas)).toBe(expectedSDL) + const expectedSDL = `\ + type A { + first: String + second: Float + b: B + } + + type B { + hello: String! + c1: C1 + c2: C2 + } + + type C1 { + id: ID! + } + + type C2 { + id: ID! + } + ` + expect(normalizeDocumentString(await importSchema(schemaA, schemas))).toBe(normalizeDocumentString(expectedSDL)) }) test(`importSchema: single object schema`, async () => { - const schemaA = ` - type A { - field: String - } -` - - const expectedSDL = `\ -type A { - field: String -} -` + const schemaA = ` + type A { + field: String + } + ` + + const expectedSDL = `\ + type A { + field: String + } + ` - expect(await importSchema(schemaA)).toBe(expectedSDL) + expect(normalizeDocumentString(await importSchema(schemaA))).toBe(normalizeDocumentString(expectedSDL)) }) test(`importSchema: import all mix 'n match`, async () => { - const schemaB = ` - # import C1, C2 from 'tests/loaders/schema/fixtures/import-all/c.graphql' - type B { - hello: String! - c1: C1 - c2: C2 - } -` - - const schemaA = ` - # import * from "schemaB" - type A { - # test 1 - first: String - second: Float - b: B - } -` - - const schemas = { - schemaB, - } - - const expectedSDL = `\ -type A { - first: String - second: Float - b: B -} - -type C1 { - id: ID! -} - -type C2 { - id: ID! -} - -type B { - hello: String! - c1: C1 - c2: C2 -} -` + const schemaB = ` + # import C1, C2 from 'tests/loaders/schema/fixtures/import-all/c.graphql' + type B { + hello: String! + c1: C1 + c2: C2 + } + ` + + const schemaA = ` + # import * from "schemaB" + type A { + # test 1 + first: String + second: Float + b: B + } + ` + + const schemas = { + schemaB, + } - expect(await importSchema(schemaA, schemas)).toBe(expectedSDL) + const expectedSDL = `\ + type A { + first: String + second: Float + b: B + } + + type C1 { + id: ID! + } + + type C2 { + id: ID! + } + + type B { + hello: String! + c1: C1 + c2: C2 + } + ` + + expect(normalizeDocumentString(await importSchema(schemaA, schemas))).toBe(normalizeDocumentString(expectedSDL)) }) test(`importSchema: import all mix 'n match 2`, async () => { - const schemaA = ` - # import * from "tests/loaders/schema/fixtures/import-all/b.graphql" - type A { - # test 1 - first: String - second: Float - b: B - } -` - - const expectedSDL = `\ -type A { - first: String - second: Float - b: B -} - -type B { - hello: String! - c1: C1 - c2: C2 -} - -type C1 { - id: ID! -} - -type C2 { - id: ID! -} -` - expect(await importSchema(schemaA)).toBe(expectedSDL) + const schemaA = ` + # import * from "tests/loaders/schema/fixtures/import-all/b.graphql" + type A { + # test 1 + first: String + second: Float + b: B + } + ` + + const expectedSDL = `\ + type A { + first: String + second: Float + b: B + } + + type B { + hello: String! + c1: C1 + c2: C2 + } + + type C1 { + id: ID! + } + + type C2 { + id: ID! + } + ` + expect(normalizeDocumentString(await importSchema(schemaA))).toBe(normalizeDocumentString(expectedSDL)) }) test(`importSchema: import all - exclude Query/Mutation/Subscription type`, async () => { - const schemaC = ` - type C1 { - id: ID! - } - - type C2 { - id: ID! - } - - type C3 { - id: ID! - } - - type Query { - hello: String! - } - - type Mutation { - hello: String! - } - - type Subscription { - hello: String! - } - - ` - - const schemaB = ` - # import * from 'schemaC' - type B { - hello: String! - c1: C1 - c2: C2 - } -` - - const schemaA = ` - # import B from 'schemaB' - type Query { - greet: String! - } - - type A { - # test 1 - first: String - second: Float - b: B - } -` - - const schemas = { - schemaA, - schemaB, - schemaC, - } - - const expectedSDL = `\ -type Query { - greet: String! -} - -type A { - first: String - second: Float - b: B -} - -type B { - hello: String! - c1: C1 - c2: C2 -} - -type C1 { - id: ID! -} + const schemaC = ` + type C1 { + id: ID! + } + + type C2 { + id: ID! + } + + type C3 { + id: ID! + } + + type Query { + hello: String! + } + + type Mutation { + hello: String! + } + + type Subscription { + hello: String! + } + + ` + + const schemaB = ` + # import * from 'schemaC' + type B { + hello: String! + c1: C1 + c2: C2 + } + ` + + const schemaA = ` + # import B from 'schemaB' + type Query { + greet: String! + } + + type A { + # test 1 + first: String + second: Float + b: B + } + ` + + const schemas = { + schemaA, + schemaB, + schemaC, + } -type C2 { - id: ID! -} -` - expect(await importSchema(schemaA, schemas)).toBe(expectedSDL) + const expectedSDL = `\ + type Query { + greet: String! + } + + type A { + first: String + second: Float + b: B + } + + type B { + hello: String! + c1: C1 + c2: C2 + } + + type C1 { + id: ID! + } + + type C2 { + id: ID! + } + ` + expect(normalizeDocumentString(await importSchema(schemaA, schemas))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: scalar', async () => { - const expectedSDL = `\ -type A { - b: B -} - -scalar B -` - expect(await importSchema('tests/loaders/schema/fixtures/scalar/a.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type A { + b: B + } + + scalar B + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/scalar/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: directive', async () => { - const expectedSDL = `\ -type A { - first: String @upper - second: String @withB @deprecated -} - -scalar B - -directive @upper on FIELD_DEFINITION - -directive @withB(argB: B) on FIELD_DEFINITION -` - expect(await importSchema('tests/loaders/schema/fixtures/directive/a.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type A { + first: String @upper + second: String @withB @deprecated + } + + scalar B + + directive @upper on FIELD_DEFINITION + + directive @withB(argB: B) on FIELD_DEFINITION + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: key directive', async () => { - const expectedSDL = `\ -scalar UPC - -type Product @key(fields: "upc") { - upc: UPC! - name: String -} -` - expect(await importSchema('tests/loaders/schema/fixtures/directive/c.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + scalar UPC + + type Product @key(fields: "upc") { + upc: UPC! + name: String + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/c.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: multiple key directive', async () => { - const expectedSDL = `\ -scalar UPC - -scalar SKU - -type Product @key(fields: "upc") @key(fields: "sku") { - upc: UPC! - sku: SKU! - name: String -} -` - expect(await importSchema('tests/loaders/schema/fixtures/directive/e.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + scalar UPC + + scalar SKU + + type Product @key(fields: "upc") @key(fields: "sku") { + upc: UPC! + sku: SKU! + name: String + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/e.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: external directive', async () => { - const expectedSDL = `\ -type Review @key(fields: "id") { - product: Product @provides(fields: "name") -} - -extend type Product @key(fields: "upc") { - upc: String @external - name: String @external -} -` - expect(await importSchema('tests/loaders/schema/fixtures/directive/f.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type Review @key(fields: "id") { + product: Product @provides(fields: "name") + } + + extend type Product @key(fields: "upc") { + upc: String @external + name: String @external + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/f.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: requires directive', async () => { - const expectedSDL = `\ -type Review { - id: ID -} - -extend type User @key(fields: "id") { - id: ID! @external - email: String @external - reviews: [Review] @requires(fields: "email") -} -` - expect(await importSchema('tests/loaders/schema/fixtures/directive/g.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type Review { + id: ID + } + + extend type User @key(fields: "id") { + id: ID! @external + email: String @external + reviews: [Review] @requires(fields: "email") + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/g.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: interfaces', async () => { - const expectedSDL = `\ -type A implements B { - first: String - second: Float -} - -interface B { - second: Float - c: [C!]! -} - -type C { - c: ID! -} -` - expect(await importSchema('tests/loaders/schema/fixtures/interfaces/a.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type A implements B { + first: String + second: Float + } + + interface B { + second: Float + c: [C!]! + } + + type C { + c: ID! + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/interfaces/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: interfaces-many', async () => { - const expectedSDL = `\ -type A implements B { - first: String - second: Float -} - -interface B { - second: Float - c: [C!]! -} - -type C implements D1 & D2 { - c: ID! -} - -interface D1 { - d1: ID! -} - -interface D2 { - d2: ID! -} -` - expect(await importSchema('tests/loaders/schema/fixtures/interfaces-many/a.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type A implements B { + first: String + second: Float + } + + interface B { + second: Float + c: [C!]! + } + + type C implements D1 & D2 { + c: ID! + } + + interface D1 { + d1: ID! + } + + interface D2 { + d2: ID! + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/interfaces-many/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: interfaces-implements', async () => { - const expectedSDL = `\ -type A implements B { - id: ID! -} - -interface B { - id: ID! -} - -type B1 implements B { - id: ID! -} -` - expect(await importSchema('tests/loaders/schema/fixtures/interfaces-implements/a.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type A implements B { + id: ID! + } + + interface B { + id: ID! + } + + type B1 implements B { + id: ID! + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/interfaces-implements/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: interfaces-implements-many', async () => { - const expectedSDL = `\ -type A implements B { - id: ID! -} - -interface B { - id: ID! -} - -type B1 implements B { - id: ID! -} - -type B2 implements B { - id: ID! -} -` - expect( - await importSchema('tests/loaders/schema/fixtures/interfaces-implements-many/a.graphql') - ).toBe( - expectedSDL, - ) + const expectedSDL = `\ + type A implements B { + id: ID! + } + + interface B { + id: ID! + } + + type B1 implements B { + id: ID! + } + + type B2 implements B { + id: ID! + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/interfaces-implements-many/a.graphql')) + ).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: input types', async () => { - const expectedSDL = `\ -type A { - first(b: B): String - second: Float -} - -input B { - hello: [C!]! -} - -input C { - id: ID! -} -` - expect(await importSchema('tests/loaders/schema/fixtures/input-types/a.graphql')).toBe(expectedSDL) + const expectedSDL = `\ + type A { + first(b: B): String + second: Float + } + + input B { + hello: [C!]! + } + + input C { + id: ID! + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/input-types/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: complex test', async () => { - expect(() => { - importSchema('tests/loaders/schema/fixtures/complex/a.graphql') - }).not.toThrow(); + try { + const a = await importSchema('tests/loaders/schema/fixtures/complex/a.graphql') + expect(a).toBeTruthy(); + } catch(e) { + expect(e).toBeFalsy(); + } }) -test.skip('circular imports', async () => { - const expectedSDL = `\ -type A { - first: String - second: Float - b: B -} - -type C1 { - id: ID! -} - -type C2 { - id: ID! -} - -type B { - hello: String! - c1: C1 - c2: C2 - a: A -} -` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/circular/a.graphql') - expect(actualSDL).toBe(expectedSDL) +test('circular imports', async () => { + const expectedSDL = `\ + type A { + first: String + second: Float + b: B + } + + type C1 { + id: ID! + } + + type C2 { + id: ID! + } + + type B { + hello: String! + c1: C1 + c2: C2 + a: A + } + ` + const actualSDL = await importSchema('tests/loaders/schema/fixtures/circular/a.graphql') + expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) test('related types', async () => { - const expectedSDL = `\ -type A { - first: String - second: Float - b: B -} - -type B { - hello: String! - c1: C -} - -type C { - field: String -} -` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/related-types/a.graphql') - expect(actualSDL).toBe(expectedSDL) + const expectedSDL = `\ + type A { + first: String + second: Float + b: B + } + + type B { + hello: String! + c1: C + } + + type C { + field: String + } + ` + const actualSDL = await importSchema('tests/loaders/schema/fixtures/related-types/a.graphql') + expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) test('relative paths', async () => { - const expectedSDL = `\ -type Query { - feed: [Post!]! -} - -type Mutation { - createDraft(title: String!, text: String): Post - publish(id: ID!): Post -} - -type Post implements Node { - id: ID! - isPublished: Boolean! - title: String! - text: String! -} - -interface Node { - id: ID! -} -` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/relative-paths/src/schema.graphql') - expect(actualSDL).toBe(expectedSDL) + const expectedSDL = `\ + type Query { + feed: [Post!]! + } + + type Mutation { + createDraft(title: String!, text: String): Post + publish(id: ID!): Post + } + + type Post implements Node { + id: ID! + isPublished: Boolean! + title: String! + text: String! + } + + interface Node { + id: ID! + } + ` + const actualSDL = await importSchema('tests/loaders/schema/fixtures/relative-paths/src/schema.graphql') + expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) test('root field imports', async () => { - const expectedSDL = `\ -type Query { - posts(filter: PostFilter): [Post] -} - -type Dummy { - field: String -} - -type Post { - field1: String -} - -input PostFilter { - field3: Int -} -` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/root-fields/a.graphql') - expect(actualSDL).toBe(expectedSDL) + const expectedSDL = `\ + type Query { + posts(filter: PostFilter): [Post] + } + + type Dummy { + field: String + } + + type Post { + field1: String + } + + input PostFilter { + field3: Int + } + ` + const actualSDL = await importSchema('tests/loaders/schema/fixtures/root-fields/a.graphql') + expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) test('extend root field', async () => { - const expectedSDL = `\ -extend type Query { - me: User -} - -type User @key(fields: "id") { - id: ID! - name: String -} -` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/root-fields/c.graphql') - expect(actualSDL).toBe(expectedSDL) + const expectedSDL = `\ + extend type Query { + me: User + } + + type User @key(fields: "id") { + id: ID! + name: String + } + ` + const actualSDL = await importSchema('tests/loaders/schema/fixtures/root-fields/c.graphql') + expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) test('extend root field imports', async () => { - const expectedSDL = `\ -extend type Query { - me: User - post: Post -} - -type Post { - id: ID! -} - -type User @key(fields: "id") { - id: ID! - name: String -} -` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/root-fields/d.graphql') - expect(actualSDL).toBe(expectedSDL) + const expectedSDL = `\ + extend type Query { + me: User + post: Post + } + + type Post { + id: ID! + } + + type User @key(fields: "id") { + id: ID! + name: String + } + ` + const actualSDL = await importSchema('tests/loaders/schema/fixtures/root-fields/d.graphql') + expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) test('merged root field imports', async () => { - 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 = await importSchema('tests/loaders/schema/fixtures/merged-root-fields/a.graphql') - expect(actualSDL).toBe(expectedSDL) + 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 = await importSchema('tests/loaders/schema/fixtures/merged-root-fields/a.graphql') + expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) test('global schema modules', async () => { - const shared = ` - type Shared { - first: String - } - - ` - const expectedSDL = `\ -type A { - first: String - second: Shared -} - -type Shared { - first: String -} -` - expect(await importSchema('tests/loaders/schema/fixtures/global/a.graphql', { shared } )).toBe(expectedSDL) + const shared = ` + type Shared { + first: String + } + + ` + const expectedSDL = `\ + type A { + first: String + second: Shared + } + + type Shared { + first: String + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/global/a.graphql', { shared } ))).toBe(normalizeDocumentString(expectedSDL)) }) test('missing type on type', async () => { - try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/a.graphql'); - throw new Error(); - } catch (e) { - expect(e.message).toBe(`Field test: Couldn't find type Post in any of the schemas.`); - } + try { + await importSchema('tests/loaders/schema/fixtures/type-not-found/a.graphql'); + throw new Error(); + } catch (e) { + expect(e.message).toBe(`Field test: Couldn't find type Post in any of the schemas.`); + } }) test('missing type on interface', async () => { - try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/b.graphql'); - throw new Error(); - } catch (e) { - expect(e.message).toBe(`Field test: Couldn't find type Post in any of the schemas.`) - } + try { + await importSchema('tests/loaders/schema/fixtures/type-not-found/b.graphql'); + throw new Error(); + } catch (e) { + expect(e.message).toBe(`Field test: Couldn't find type Post in any of the schemas.`) + } }) test('missing type on input type', async () => { - try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/c.graphql'); - throw new Error(); - } catch (e) { - expect(e.message).toBe(`Field post: Couldn't find type Post in any of the schemas.`) - } + try { + await importSchema('tests/loaders/schema/fixtures/type-not-found/c.graphql'); + throw new Error(); + } catch (e) { + expect(e.message).toBe(`Field post: Couldn't find type Post in any of the schemas.`) + } }) test('missing interface type', async () => { - try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/d.graphql'); - throw new Error(); - } catch (e) { - expect(e.message).toBe(`Couldn't find interface MyInterface in any of the schemas.`) - } + try { + await importSchema('tests/loaders/schema/fixtures/type-not-found/d.graphql'); + throw new Error(); + } catch (e) { + expect(e.message).toBe(`Couldn't find interface MyInterface in any of the schemas.`) + } }) test('missing union type', async () => { - try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/e.graphql') - throw new Error(); - } catch (e) { - expect(e.message).toBe(`Couldn't find type C in any of the schemas.`) - } + try { + await importSchema('tests/loaders/schema/fixtures/type-not-found/e.graphql') + throw new Error(); + } catch (e) { + expect(e.message).toBe(`Couldn't find type C in any of the schemas.`) + } }) test('missing type on input type', async () => { - try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/f.graphql'); - throw new Error(); - } catch (e) { - expect(e.message).toBe(`Field myfield: Couldn't find type Post in any of the schemas.`) - } + try { + await importSchema('tests/loaders/schema/fixtures/type-not-found/f.graphql'); + throw new Error(); + } catch (e) { + expect(e.message).toBe(`Field myfield: Couldn't find type Post in any of the schemas.`) + } }) test('missing type on directive', async () => { - try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/g.graphql'); - throw new Error(); - } catch (e) { - expect(e.message).toBe(`Directive first: Couldn't find type first in any of the schemas.`) - } + try { + await importSchema('tests/loaders/schema/fixtures/type-not-found/g.graphql'); + throw new Error(); + } catch (e) { + expect(e.message).toBe(`Directive first: Couldn't find type first in any of the schemas.`) + } }) test('import with collision', async () => { - // Local type gets preference over imported type - const expectedSDL = `\ -type User { - id: ID! - name: String! - intro: String -} -` - expect(await importSchema('tests/loaders/schema/fixtures/collision/a.graphql')).toBe(expectedSDL) -}) - -function stripWhitespaces(str: string): string { - return str.replace(/\s+/g, ' ').trim(); + // Local type gets preference over imported type + const expectedSDL = `\ + type User { + id: ID! + name: String! + intro: String + } + ` + expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/collision/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) +}) + +function normalizeDocumentString(doc: any): string { + if(typeof doc === 'string') { + doc = parse(doc.replace(/\s+/g, ' ').trim(), {noLocation: true}); + } + doc.definitions = doc.definitions.sort((a,b) => { + const aStr = 'name' in a ? a.name.value : a.kind; + const bStr = 'name' in b ? b.name.value : b.kind; + return aStr.localeCompare(bStr); + }) + return print(doc); } test('merged custom root fields imports', async () => { - const expectedSDL = stripWhitespaces(`\ - 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 = await importSchema('tests/loaders/schema/fixtures/merged-root-fields/a.graphql') - expect(stripWhitespaces(actualSDL)).toBe(stripWhitespaces(expectedSDL)) + const expectedSDL = normalizeDocumentString(`\ + 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 = await importSchema('tests/loaders/schema/fixtures/merged-root-fields/a.graphql') + expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) \ No newline at end of file diff --git a/packages/loaders/code-file/tests/load-from-code-file.spec.ts b/packages/loaders/code-file/tests/load-from-code-file.spec.ts index 41a6abcc..469bf03e 100644 --- a/packages/loaders/code-file/tests/load-from-code-file.spec.ts +++ b/packages/loaders/code-file/tests/load-from-code-file.spec.ts @@ -1,26 +1,32 @@ import { resolve } from 'path'; import { CodeFileLoader } from '../src'; +import { parse } from 'graphql'; describe('loadFromCodeFile', () => { const loader = new CodeFileLoader(); it('Should throw an error when a document is loaded using AST and the document is not valid', async () => { try { - await loader.load('./tests/test-files/invalid-anon-doc.js', { noRequire: true }); - expect(true).toBeFalsy(); + const loaded = await loader.load('./tests/test-files/invalid-anon-doc.js', { noRequire: true }); + const doc = parse(loaded.rawSDL); + + expect(doc).toBeFalsy(); } catch (e) { expect(e.message).toBe('Syntax Error: Unexpected Name "InvalidGetUser"'); } }); it('should load a vaild file', async () => { - const doc = await loader.load('./tests/test-files/valid-doc.js', { noRequire: true }); + const loaded = await loader.load('./tests/test-files/valid-doc.js', { noRequire: true }); + const doc = parse(loaded.rawSDL); - expect(doc.document.kind).toEqual('Document'); + expect(doc.kind).toEqual('Document'); }); it('should consider options.cwd', async () => { - const doc = await loader.load('valid-doc.js', { noRequire: true, cwd: resolve(__dirname, 'test-files') }); - expect(doc.document.kind).toEqual('Document'); + const loaded = await loader.load('valid-doc.js', { noRequire: true, cwd: resolve(__dirname, 'test-files') }); + const doc = parse(loaded.rawSDL); + + expect(doc.kind).toEqual('Document'); }); }); From 81bb2ad08af7153342132d14d7bca5d53b78cd13 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Sun, 29 Dec 2019 19:29:36 +0300 Subject: [PATCH 4/8] Use cache instead of preresolvedTypeDefs --- packages/core/src/import-parser/index.ts | 4 +- packages/core/src/load-typedefs.ts | 4 - .../loaders/schema/import-schema.spec.ts | 86 ++++++++++--------- 3 files changed, 46 insertions(+), 48 deletions(-) diff --git a/packages/core/src/import-parser/index.ts b/packages/core/src/import-parser/index.ts index 01da1487..223e239d 100644 --- a/packages/core/src/import-parser/index.ts +++ b/packages/core/src/import-parser/index.ts @@ -6,7 +6,7 @@ import { LoadSchemaOptions } from '../schema'; import { completeDefinitionPool, ValidDefinitionNode } from './definition'; import { realpathSync } from 'fs'; -import { join, dirname } from 'path'; +import { join, dirname, resolve } from 'path'; import { Source } from '@graphql-toolkit/common'; /** @@ -194,7 +194,7 @@ export async function collectDefinitions(imports: string[], documentSource: Sour await Promise.all( rawModules.map(async m => { // If it was not yet processed (in case of circular dependencies) - const moduleFilePath = resolveModuleFilePath(documentSource.location, m.from); + const moduleFilePath = resolveModuleFilePath(resolve(options.cwd, documentSource.location), m.from); const processedFile = options.processedFiles.get(moduleFilePath); if (!processedFile || !processedFile.find(rModule => isEqual(rModule, m))) { diff --git a/packages/core/src/load-typedefs.ts b/packages/core/src/load-typedefs.ts index 9dc38d00..585aa9e9 100644 --- a/packages/core/src/load-typedefs.ts +++ b/packages/core/src/load-typedefs.ts @@ -16,7 +16,6 @@ export type LoadTypedefsOptions = SingleFi loaders: Loader[]; filterKinds?: string[]; ignore?: string | string[]; - preresolvedTypeDefs?: { [key: string]: string }; sort?: boolean; skipGraphQLImport?: boolean; forceGraphQLImport?: boolean; @@ -263,9 +262,6 @@ export async function loadSingleFile(pointer: string, options: LoadTypedefsOptio if (pointer in options.cache) { return options.cache[pointer]; } - if (options.preresolvedTypeDefs && pointer in options.preresolvedTypeDefs) { - return parseGraphQLSDL(pointer, options.preresolvedTypeDefs[pointer], options); - } try { for (const loader of options.loaders) { const canLoad = await loader.canLoad(pointer, options); diff --git a/packages/core/tests/loaders/schema/import-schema.spec.ts b/packages/core/tests/loaders/schema/import-schema.spec.ts index 2fb2abdd..b63502e4 100644 --- a/packages/core/tests/loaders/schema/import-schema.spec.ts +++ b/packages/core/tests/loaders/schema/import-schema.spec.ts @@ -1,12 +1,13 @@ import { parseImportLine, parseSDL, loadTypedefs, LoadTypedefsOptions, OPERATION_KINDS } from '@graphql-toolkit/core'; import * as fs from 'fs' -import { print, DocumentNode, Kind } from 'graphql'; +import { print } from 'graphql'; import { JsonFileLoader } from '@graphql-toolkit/json-file-loader'; import { UrlLoader } from '@graphql-toolkit/url-loader'; import { CodeFileLoader } from '@graphql-toolkit/code-file-loader'; import { GraphQLFileLoader } from '@graphql-toolkit/graphql-file-loader'; -import { mergeTypeDefs } from '@graphql-toolkit/schema-merging'; import { parse } from 'graphql'; +import { parseGraphQLSDL } from '@graphql-toolkit/common'; +import { mergeTypeDefs } from '@graphql-toolkit/schema-merging'; const importSchema = ( schema: string, schemas?: { [name: string]: string }, options?: LoadTypedefsOptions @@ -15,9 +16,10 @@ const importSchema = ( schema, { loaders: [new UrlLoader(), new JsonFileLoader(), new GraphQLFileLoader(), new CodeFileLoader()], filterKinds: OPERATION_KINDS, - preresolvedTypeDefs: schemas, + cache: schemas ? Object.keys(schemas).reduce((prev, location) => Object.assign(prev, { [location]: parseGraphQLSDL(location, schemas[location], options)}), {}) : {}, sort: false, forceGraphQLImport: true, + cwd: __dirname, ...options, }).then(r => print(mergeTypeDefs(r.map(r => r.document), { useSchemaDefinition: false }))); @@ -123,7 +125,7 @@ test('Module in node_modules', async () => { fs.writeFileSync(moduleDir + '/b.graphql', b) fs.writeFileSync(moduleDir + '/lower.graphql', lower) - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-module/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/import-module/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: imports only', async () => { @@ -134,7 +136,7 @@ test('importSchema: imports only', async () => { third: String } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/imports-only/all.graphql'))).toBe(normalizeDocumentString(expectedSDL)); + expect(normalizeDocumentString(await importSchema('./fixtures/imports-only/all.graphql'))).toBe(normalizeDocumentString(expectedSDL)); }) test('importSchema: import .gql extension', async () => { @@ -143,7 +145,7 @@ test('importSchema: import .gql extension', async () => { id: ID! } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-gql/a.gql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/import-gql/a.gql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: import duplicate', async () => { @@ -154,7 +156,7 @@ test('importSchema: import duplicate', async () => { third: String } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-duplicate/all.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/import-duplicate/all.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: import nested', async () => { @@ -165,7 +167,7 @@ test('importSchema: import nested', async () => { third: String } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-nested/all.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/import-nested/all.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: field types', async () => { @@ -185,7 +187,7 @@ test('importSchema: field types', async () => { id: ID! } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/field-types/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/field-types/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: enums', async () => { @@ -202,7 +204,7 @@ test('importSchema: enums', async () => { B3 } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/enums/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/enums/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: import all', async () => { @@ -227,7 +229,7 @@ test('importSchema: import all', async () => { id: ID! } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/import-all/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/import-all/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: import all from objects', async () => { @@ -312,7 +314,7 @@ test(`importSchema: single object schema`, async () => { test(`importSchema: import all mix 'n match`, async () => { const schemaB = ` - # import C1, C2 from 'tests/loaders/schema/fixtures/import-all/c.graphql' + # import C1, C2 from './fixtures/import-all/c.graphql' type B { hello: String! c1: C1 @@ -361,7 +363,7 @@ test(`importSchema: import all mix 'n match`, async () => { test(`importSchema: import all mix 'n match 2`, async () => { const schemaA = ` - # import * from "tests/loaders/schema/fixtures/import-all/b.graphql" + # import * from "./fixtures/import-all/b.graphql" type A { # test 1 first: String @@ -487,7 +489,7 @@ test('importSchema: scalar', async () => { scalar B ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/scalar/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/scalar/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: directive', async () => { @@ -503,7 +505,7 @@ test('importSchema: directive', async () => { directive @withB(argB: B) on FIELD_DEFINITION ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/directive/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: key directive', async () => { @@ -515,7 +517,7 @@ test('importSchema: key directive', async () => { name: String } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/c.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/directive/c.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: multiple key directive', async () => { @@ -530,7 +532,7 @@ test('importSchema: multiple key directive', async () => { name: String } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/e.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/directive/e.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: external directive', async () => { @@ -544,7 +546,7 @@ test('importSchema: external directive', async () => { name: String @external } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/f.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/directive/f.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: requires directive', async () => { @@ -559,7 +561,7 @@ test('importSchema: requires directive', async () => { reviews: [Review] @requires(fields: "email") } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/directive/g.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/directive/g.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: interfaces', async () => { @@ -578,7 +580,7 @@ test('importSchema: interfaces', async () => { c: ID! } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/interfaces/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/interfaces/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: interfaces-many', async () => { @@ -605,7 +607,7 @@ test('importSchema: interfaces-many', async () => { d2: ID! } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/interfaces-many/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/interfaces-many/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: interfaces-implements', async () => { @@ -622,7 +624,7 @@ test('importSchema: interfaces-implements', async () => { id: ID! } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/interfaces-implements/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/interfaces-implements/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: interfaces-implements-many', async () => { @@ -643,7 +645,7 @@ test('importSchema: interfaces-implements-many', async () => { id: ID! } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/interfaces-implements-many/a.graphql')) + expect(normalizeDocumentString(await importSchema('./fixtures/interfaces-implements-many/a.graphql')) ).toBe(normalizeDocumentString(expectedSDL)) }) @@ -662,12 +664,12 @@ test('importSchema: input types', async () => { id: ID! } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/input-types/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/input-types/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) test('importSchema: complex test', async () => { try { - const a = await importSchema('tests/loaders/schema/fixtures/complex/a.graphql') + const a = await importSchema('./fixtures/complex/a.graphql') expect(a).toBeTruthy(); } catch(e) { expect(e).toBeFalsy(); @@ -697,7 +699,7 @@ test('circular imports', async () => { a: A } ` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/circular/a.graphql') + const actualSDL = await importSchema('./fixtures/circular/a.graphql') expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) @@ -718,7 +720,7 @@ test('related types', async () => { field: String } ` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/related-types/a.graphql') + const actualSDL = await importSchema('./fixtures/related-types/a.graphql') expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) @@ -744,7 +746,7 @@ test('relative paths', async () => { id: ID! } ` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/relative-paths/src/schema.graphql') + const actualSDL = await importSchema('./fixtures/relative-paths/src/schema.graphql') expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) @@ -766,7 +768,7 @@ test('root field imports', async () => { field3: Int } ` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/root-fields/a.graphql') + const actualSDL = await importSchema('./fixtures/root-fields/a.graphql') expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) @@ -781,7 +783,7 @@ test('extend root field', async () => { name: String } ` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/root-fields/c.graphql') + const actualSDL = await importSchema('./fixtures/root-fields/c.graphql') expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) @@ -801,7 +803,7 @@ test('extend root field imports', async () => { name: String } ` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/root-fields/d.graphql') + const actualSDL = await importSchema('./fixtures/root-fields/d.graphql') expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) @@ -826,7 +828,7 @@ test('merged root field imports', async () => { field3: Int } ` - const actualSDL = await importSchema('tests/loaders/schema/fixtures/merged-root-fields/a.graphql') + const actualSDL = await importSchema('./fixtures/merged-root-fields/a.graphql') expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) @@ -847,12 +849,12 @@ test('global schema modules', async () => { first: String } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/global/a.graphql', { shared } ))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/global/a.graphql', { shared } ))).toBe(normalizeDocumentString(expectedSDL)) }) test('missing type on type', async () => { try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/a.graphql'); + await importSchema('./fixtures/type-not-found/a.graphql'); throw new Error(); } catch (e) { expect(e.message).toBe(`Field test: Couldn't find type Post in any of the schemas.`); @@ -862,7 +864,7 @@ test('missing type on type', async () => { test('missing type on interface', async () => { try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/b.graphql'); + await importSchema('./fixtures/type-not-found/b.graphql'); throw new Error(); } catch (e) { expect(e.message).toBe(`Field test: Couldn't find type Post in any of the schemas.`) @@ -872,7 +874,7 @@ test('missing type on interface', async () => { test('missing type on input type', async () => { try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/c.graphql'); + await importSchema('./fixtures/type-not-found/c.graphql'); throw new Error(); } catch (e) { expect(e.message).toBe(`Field post: Couldn't find type Post in any of the schemas.`) @@ -883,7 +885,7 @@ test('missing type on input type', async () => { test('missing interface type', async () => { try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/d.graphql'); + await importSchema('./fixtures/type-not-found/d.graphql'); throw new Error(); } catch (e) { expect(e.message).toBe(`Couldn't find interface MyInterface in any of the schemas.`) @@ -894,7 +896,7 @@ test('missing interface type', async () => { test('missing union type', async () => { try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/e.graphql') + await importSchema('./fixtures/type-not-found/e.graphql') throw new Error(); } catch (e) { expect(e.message).toBe(`Couldn't find type C in any of the schemas.`) @@ -905,7 +907,7 @@ test('missing union type', async () => { test('missing type on input type', async () => { try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/f.graphql'); + await importSchema('./fixtures/type-not-found/f.graphql'); throw new Error(); } catch (e) { expect(e.message).toBe(`Field myfield: Couldn't find type Post in any of the schemas.`) @@ -916,7 +918,7 @@ test('missing type on input type', async () => { test('missing type on directive', async () => { try { - await importSchema('tests/loaders/schema/fixtures/type-not-found/g.graphql'); + await importSchema('./fixtures/type-not-found/g.graphql'); throw new Error(); } catch (e) { expect(e.message).toBe(`Directive first: Couldn't find type first in any of the schemas.`) @@ -933,7 +935,7 @@ test('import with collision', async () => { intro: String } ` - expect(normalizeDocumentString(await importSchema('tests/loaders/schema/fixtures/collision/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/collision/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) function normalizeDocumentString(doc: any): string { @@ -967,6 +969,6 @@ test('merged custom root fields imports', async () => { field3: Int } `); - const actualSDL = await importSchema('tests/loaders/schema/fixtures/merged-root-fields/a.graphql') + const actualSDL = await importSchema('./fixtures/merged-root-fields/a.graphql') expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) }) \ No newline at end of file From a75ec2cf86f31c50da864ee0038d08a10b9c6fa9 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Mon, 30 Dec 2019 01:18:56 +0300 Subject: [PATCH 5/8] Support schema definition --- packages/core/src/import-parser/definition.ts | 33 +++++++++---- packages/core/src/import-parser/index.ts | 39 ++++++++------- .../fixtures/schema-definition/a.graphql | 7 +++ .../fixtures/schema-definition/b.graphql | 3 ++ .../fixtures/schema-definition/c.graphql | 3 ++ .../loaders/schema/import-schema.spec.ts | 48 +++++++++++++++---- .../src/typedefs-mergers/comments.ts | 4 -- .../src/typedefs-mergers/merge-typedefs.ts | 5 +- 8 files changed, 98 insertions(+), 44 deletions(-) create mode 100644 packages/core/tests/loaders/schema/fixtures/schema-definition/a.graphql create mode 100644 packages/core/tests/loaders/schema/fixtures/schema-definition/b.graphql create mode 100644 packages/core/tests/loaders/schema/fixtures/schema-definition/c.graphql diff --git a/packages/core/src/import-parser/definition.ts b/packages/core/src/import-parser/definition.ts index c2fb3293..005736ae 100644 --- a/packages/core/src/import-parser/definition.ts +++ b/packages/core/src/import-parser/definition.ts @@ -1,11 +1,11 @@ -import { keyBy, uniqBy, includes } from 'lodash'; -import { TypeDefinitionNode, TypeNode, NamedTypeNode, DirectiveNode, DirectiveDefinitionNode, InputValueDefinitionNode, FieldDefinitionNode } from 'graphql'; +import { keyBy, uniqBy, includes, reverse } from 'lodash'; +import { TypeDefinitionNode, TypeNode, NamedTypeNode, DirectiveNode, DirectiveDefinitionNode, InputValueDefinitionNode, FieldDefinitionNode, SchemaDefinitionNode } from 'graphql'; const builtinTypes = ['String', 'Float', 'Int', 'Boolean', 'ID']; const builtinDirectives = ['deprecated', 'skip', 'include', 'key', 'external', 'requires', 'provides']; -export type ValidDefinitionNode = DirectiveDefinitionNode | TypeDefinitionNode; +export type ValidDefinitionNode = DirectiveDefinitionNode | TypeDefinitionNode | SchemaDefinitionNode; export interface DefinitionMap { [key: string]: ValidDefinitionNode; @@ -23,9 +23,9 @@ export interface DefinitionMap { export function completeDefinitionPool(allDefinitions: ValidDefinitionNode[], definitionPool: ValidDefinitionNode[], newTypeDefinitions: ValidDefinitionNode[]): ValidDefinitionNode[] { const visitedDefinitions: { [name: string]: boolean } = {}; while (newTypeDefinitions.length > 0) { - const schemaMap: DefinitionMap = keyBy(allDefinitions, d => d.name.value); + const schemaMap: DefinitionMap = keyBy(reverse(allDefinitions), d => ('name' in d ? d.name.value : 'schema')); const newDefinition = newTypeDefinitions.shift(); - if (visitedDefinitions[newDefinition.name.value]) { + if (visitedDefinitions['name' in newDefinition ? newDefinition.name.value : 'schema']) { continue; } @@ -33,7 +33,7 @@ export function completeDefinitionPool(allDefinitions: ValidDefinitionNode[], de newTypeDefinitions.push(...collectedTypedDefinitions); definitionPool.push(...collectedTypedDefinitions); - visitedDefinitions[newDefinition.name.value] = true; + visitedDefinitions['name' in newDefinition ? newDefinition.name.value : 'schema'] = true; } return uniqBy(definitionPool, 'name.value'); @@ -73,7 +73,7 @@ function collectNewTypeDefinitions(allDefinitions: ValidDefinitionNode[], defini if (newDefinition.kind === 'UnionTypeDefinition') { newDefinition.types.forEach(type => { - if (!definitionPool.some(d => d.name.value === type.name.value)) { + if (!definitionPool.some(d => 'name' in d && d.name.value === type.name.value)) { const typeName = type.name.value; const typeMatch = schemaMap[typeName]; if (!typeMatch) { @@ -87,7 +87,7 @@ function collectNewTypeDefinitions(allDefinitions: ValidDefinitionNode[], defini if (newDefinition.kind === 'ObjectTypeDefinition') { // collect missing interfaces newDefinition.interfaces.forEach(int => { - if (!definitionPool.some(d => d.name.value === int.name.value)) { + if (!definitionPool.some(d => 'name' in d && d.name.value === int.name.value)) { const interfaceName = int.name.value; const interfaceMatch = schemaMap[interfaceName]; if (!interfaceMatch) { @@ -105,6 +105,19 @@ function collectNewTypeDefinitions(allDefinitions: ValidDefinitionNode[], defini }); } + if (newDefinition.kind === 'SchemaDefinition') { + newDefinition.operationTypes.forEach(operationType => { + if (!definitionPool.some(d => 'name' in d && d.name.value === operationType.type.name.value)) { + const typeName = operationType.type.name.value; + const typeMatch = schemaMap[typeName]; + if (!typeMatch) { + throw new Error(`Couldn't find type ${typeName} in any of the schemas.`); + } + newTypeDefinitions.push(schemaMap[operationType.type.name.value]); + } + }); + } + return newTypeDefinitions; function collectNode(node: FieldDefinitionNode | InputValueDefinitionNode) { @@ -112,7 +125,7 @@ function collectNewTypeDefinitions(allDefinitions: ValidDefinitionNode[], defini const nodeTypeName = nodeType.name.value; // collect missing argument input types - if (!definitionPool.some(d => d.name.value === nodeTypeName) && !includes(builtinTypes, nodeTypeName)) { + if (!definitionPool.some(d => 'name' in d && d.name.value === nodeTypeName) && !includes(builtinTypes, nodeTypeName)) { const argTypeMatch = schemaMap[nodeTypeName]; if (!argTypeMatch) { throw new Error(`Field ${node.name.value}: Couldn't find type ${nodeTypeName} in any of the schemas.`); @@ -125,7 +138,7 @@ function collectNewTypeDefinitions(allDefinitions: ValidDefinitionNode[], defini function collectDirective(directive: DirectiveNode) { const directiveName = directive.name.value; - if (!definitionPool.some(d => d.name.value === directiveName) && !includes(builtinDirectives, directiveName)) { + if (!definitionPool.some(d => 'name' in d && d.name.value === directiveName) && !includes(builtinDirectives, directiveName)) { const directive = schemaMap[directiveName] as DirectiveDefinitionNode; if (!directive) { throw new Error(`Directive ${directiveName}: Couldn't find type ${directiveName} in any of the schemas.`); diff --git a/packages/core/src/import-parser/index.ts b/packages/core/src/import-parser/index.ts index 223e239d..1d73c833 100644 --- a/packages/core/src/import-parser/index.ts +++ b/packages/core/src/import-parser/index.ts @@ -70,8 +70,6 @@ export function parseSDL(sdl: string): RawModule[] { * @returns Single bundled schema with all imported types */ export async function processImportSyntax(documentSource: Source, options: LoadSchemaOptions): Promise { - const mergeableTypes = options.mergeableTypes || []; - const allMergeableTypes = [...mergeableTypes, ...rootFields]; let document = documentSource.document; // Recursively process the imports, starting by importing all types from the initial schema @@ -81,24 +79,25 @@ export async function processImportSyntax(documentSource: Source, options: LoadS // Query, Mutation and Subscription should be merged // And should always be in the first set, to make sure they // are not filtered out. - const firstTypes = options.typeDefinitions.flat().filter(d => allMergeableTypes.includes(d.name.value)); - const secondFirstTypes = options.typeDefinitions[0].filter(d => !allMergeableTypes.includes(d.name.value)); - const otherFirstTypes = options.typeDefinitions - .slice(1) - .flat() - .filter(d => !allMergeableTypes.includes(d.name.value)); + const firstTypes = options.typeDefinitions.flat(); + const secondFirstTypes = options.typeDefinitions[0]; + const otherFirstTypes = options.typeDefinitions.slice(1).flat(); const firstSet = firstTypes.concat(secondFirstTypes, otherFirstTypes); const processedTypeNames: string[] = []; const mergedFirstTypes = []; for (const type of firstSet) { - if (!processedTypeNames.includes(type.name.value)) { - processedTypeNames.push(type.name.value); - mergedFirstTypes.push(type); - } else { - const existingType = mergedFirstTypes.find(t => t.name.value === type.name.value) as any; - - existingType.fields = uniqBy(existingType.fields.concat((type as ObjectTypeDefinitionNode).fields), 'name.value'); + if ('name' in type) { + if (!processedTypeNames.includes(type.name.value)) { + processedTypeNames.push(type.name.value); + mergedFirstTypes.push(type); + } else { + const existingType = mergedFirstTypes.find(t => t.name.value === type.name.value); + + if ('fields' in existingType) { + (existingType as any).fields = uniqBy((existingType.fields as any).concat((type as ObjectTypeDefinitionNode).fields), 'name.value'); + } + } } } @@ -226,21 +225,21 @@ function filterImportedDefinitions(imports: string[], typeDefinitions: ReadonlyA allDefinitions .slice(0, allDefinitions.length - 1) .flat() - .filter(def => !rootFields.includes(def.name.value)), - def => def.name.value + .filter(def => 'name' in def && !rootFields.includes(def.name.value)), + def => 'name' in def && def.name.value ); return typeDefinitions.filter(typeDef => typeDef.kind === 'ObjectTypeDefinition' && previousTypeDefinitions[typeDef.name.value]) as ObjectTypeDefinitionNode[]; } return filteredDefinitions; } else { const importedTypes = imports.map(i => i.split('.')[0]); - const result = filteredDefinitions.filter(d => importedTypes.includes(d.name.value)); + const result = filteredDefinitions.filter(d => 'name' in d && importedTypes.includes(d.name.value)); const fieldImports = imports.filter(i => i.split('.').length > 1); const groupedFieldImports = groupBy(fieldImports, x => x.split('.')[0]); for (const rootType in groupedFieldImports) { const fields = groupedFieldImports[rootType].map(x => x.split('.')[1]); - const objectTypeDefinition: any = filteredDefinitions.find(def => def.name.value === rootType); + const objectTypeDefinition: any = filteredDefinitions.find(def => 'name' in def && def.name.value === rootType); if (objectTypeDefinition && 'fields' in objectTypeDefinition && !fields.includes('*')) { objectTypeDefinition.fields = objectTypeDefinition.fields.filter((f: any) => fields.includes(f.name.value) || fields.includes('*')); @@ -260,4 +259,4 @@ function filterImportedDefinitions(imports: string[], typeDefinitions: ReadonlyA export function filterTypeDefinitions(definitions: ReadonlyArray): ValidDefinitionNode[] { return definitions.filter(d => validKinds.includes(d.kind)).map(d => d as ValidDefinitionNode); } -const validKinds = ['DirectiveDefinition', 'ScalarTypeDefinition', 'ObjectTypeDefinition', 'ObjectTypeExtension', 'InterfaceTypeDefinition', 'EnumTypeDefinition', 'UnionTypeDefinition', 'InputObjectTypeDefinition']; +const validKinds = ['DirectiveDefinition', 'ScalarTypeDefinition', 'ObjectTypeDefinition', 'ObjectTypeExtension', 'InterfaceTypeDefinition', 'EnumTypeDefinition', 'UnionTypeDefinition', 'InputObjectTypeDefinition', 'SchemaDefinition']; diff --git a/packages/core/tests/loaders/schema/fixtures/schema-definition/a.graphql b/packages/core/tests/loaders/schema/fixtures/schema-definition/a.graphql new file mode 100644 index 00000000..1cf6fc24 --- /dev/null +++ b/packages/core/tests/loaders/schema/fixtures/schema-definition/a.graphql @@ -0,0 +1,7 @@ +# import MyQuery from './b.graphql' +# import MyMutation from './c.graphql' + +schema { + query: MyQuery + mutation: MyMutation +} diff --git a/packages/core/tests/loaders/schema/fixtures/schema-definition/b.graphql b/packages/core/tests/loaders/schema/fixtures/schema-definition/b.graphql new file mode 100644 index 00000000..8464455c --- /dev/null +++ b/packages/core/tests/loaders/schema/fixtures/schema-definition/b.graphql @@ -0,0 +1,3 @@ +type MyQuery { + b: String +} diff --git a/packages/core/tests/loaders/schema/fixtures/schema-definition/c.graphql b/packages/core/tests/loaders/schema/fixtures/schema-definition/c.graphql new file mode 100644 index 00000000..550355c1 --- /dev/null +++ b/packages/core/tests/loaders/schema/fixtures/schema-definition/c.graphql @@ -0,0 +1,3 @@ +type MyMutation { + c: String +} diff --git a/packages/core/tests/loaders/schema/import-schema.spec.ts b/packages/core/tests/loaders/schema/import-schema.spec.ts index b63502e4..1e21f123 100644 --- a/packages/core/tests/loaders/schema/import-schema.spec.ts +++ b/packages/core/tests/loaders/schema/import-schema.spec.ts @@ -10,18 +10,18 @@ import { parseGraphQLSDL } from '@graphql-toolkit/common'; import { mergeTypeDefs } from '@graphql-toolkit/schema-merging'; const importSchema = ( - schema: string, schemas?: { [name: string]: string }, options?: LoadTypedefsOptions + schema: string, schemas?: { [name: string]: string }, options?: LoadTypedefsOptions & Parameters[1] ) => loadTypedefs( schema, { loaders: [new UrlLoader(), new JsonFileLoader(), new GraphQLFileLoader(), new CodeFileLoader()], filterKinds: OPERATION_KINDS, - cache: schemas ? Object.keys(schemas).reduce((prev, location) => Object.assign(prev, { [location]: parseGraphQLSDL(location, schemas[location], options)}), {}) : {}, + cache: schemas ? Object.keys(schemas).reduce((prev, location) => Object.assign(prev, { [location]: parseGraphQLSDL(location, schemas[location], options) }), {}) : {}, sort: false, forceGraphQLImport: true, cwd: __dirname, ...options, - }).then(r => print(mergeTypeDefs(r.map(r => r.document), { useSchemaDefinition: false }))); + }).then(r => print(mergeTypeDefs(r.map(r => r.document), { useSchemaDefinition: false, ...options }))); test('parseImportLine: parse single import', () => { expect(parseImportLine(`import A from "schema.graphql"`)).toEqual({ @@ -671,7 +671,7 @@ test('importSchema: complex test', async () => { try { const a = await importSchema('./fixtures/complex/a.graphql') expect(a).toBeTruthy(); - } catch(e) { + } catch (e) { expect(e).toBeFalsy(); } }) @@ -849,7 +849,7 @@ test('global schema modules', async () => { first: String } ` - expect(normalizeDocumentString(await importSchema('./fixtures/global/a.graphql', { shared } ))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/global/a.graphql', { shared }))).toBe(normalizeDocumentString(expectedSDL)) }) test('missing type on type', async () => { @@ -939,10 +939,10 @@ test('import with collision', async () => { }) function normalizeDocumentString(doc: any): string { - if(typeof doc === 'string') { - doc = parse(doc.replace(/\s+/g, ' ').trim(), {noLocation: true}); + if (typeof doc === 'string') { + doc = parse(doc.replace(/\s+/g, ' ').trim(), { noLocation: true }); } - doc.definitions = doc.definitions.sort((a,b) => { + doc.definitions = doc.definitions.sort((a, b) => { const aStr = 'name' in a ? a.name.value : a.kind; const bStr = 'name' in b ? b.name.value : b.kind; return aStr.localeCompare(bStr); @@ -971,4 +971,36 @@ test('merged custom root fields imports', async () => { `); const actualSDL = await importSchema('./fixtures/merged-root-fields/a.graphql') expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)) +}) + +test('respect schema definition', async () => { + const expectedSDL = normalizeDocumentString(`\ + schema { + query: MyQuery + mutation: MyMutation + } + + type MyQuery { + b: String + } + + type MyMutation { + c: String + } + `); + const actualSDL = await importSchema('./fixtures/schema-definition/a.graphql') + expect(normalizeDocumentString(actualSDL)).toBe(normalizeDocumentString(expectedSDL)); +}); + +test('import schema with shadowed type', async () => { + const expectedSDL = `\ + type Query { + b: B! + } + type B { + x: X + } + scalar X +` + expect(normalizeDocumentString(await importSchema('fixtures/import-shadowed/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) \ No newline at end of file diff --git a/packages/schema-merging/src/typedefs-mergers/comments.ts b/packages/schema-merging/src/typedefs-mergers/comments.ts index 020d9cb7..7e09dcd8 100644 --- a/packages/schema-merging/src/typedefs-mergers/comments.ts +++ b/packages/schema-merging/src/typedefs-mergers/comments.ts @@ -67,10 +67,6 @@ export function printComment(comment: string): string { return '\n# ' + comment.replace(/\n/g, '\n # '); } -export function printWithComments(doc: DocumentNode): string { - return print(doc); -} - /** * Copyright (c) 2015-present, Facebook, Inc. * diff --git a/packages/schema-merging/src/typedefs-mergers/merge-typedefs.ts b/packages/schema-merging/src/typedefs-mergers/merge-typedefs.ts index 4cd716f4..006512dd 100644 --- a/packages/schema-merging/src/typedefs-mergers/merge-typedefs.ts +++ b/packages/schema-merging/src/typedefs-mergers/merge-typedefs.ts @@ -18,7 +18,7 @@ import { } from 'graphql'; import { isGraphQLSchema, isSourceTypes, isStringTypes, isSchemaDefinition } from './utils'; import { MergedResultMap, mergeGraphQLNodes } from './merge-nodes'; -import { resetComments, printWithComments } from './comments'; +import { resetComments } from './comments'; import { fixSchemaAst } from '@graphql-toolkit/common'; type Omit = Pick>; @@ -105,7 +105,7 @@ export function mergeTypeDefs(types: Array Date: Mon, 30 Dec 2019 01:30:03 +0300 Subject: [PATCH 6/8] Fix comments --- packages/schema-merging/src/typedefs-mergers/comments.ts | 2 +- .../schema-merging/src/typedefs-mergers/merge-typedefs.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/schema-merging/src/typedefs-mergers/comments.ts b/packages/schema-merging/src/typedefs-mergers/comments.ts index 7e09dcd8..753ced5f 100644 --- a/packages/schema-merging/src/typedefs-mergers/comments.ts +++ b/packages/schema-merging/src/typedefs-mergers/comments.ts @@ -145,7 +145,7 @@ function printBlockString(value: string, isDescription: boolean) { * Converts an AST into a string, using one set of reasonable * formatting rules. */ -function print(ast: ASTNode) { +export function printWithComments(ast: ASTNode) { return visit(ast, { leave: { Name: node => node.value, diff --git a/packages/schema-merging/src/typedefs-mergers/merge-typedefs.ts b/packages/schema-merging/src/typedefs-mergers/merge-typedefs.ts index 006512dd..46aff29f 100644 --- a/packages/schema-merging/src/typedefs-mergers/merge-typedefs.ts +++ b/packages/schema-merging/src/typedefs-mergers/merge-typedefs.ts @@ -18,7 +18,7 @@ import { } from 'graphql'; import { isGraphQLSchema, isSourceTypes, isStringTypes, isSchemaDefinition } from './utils'; import { MergedResultMap, mergeGraphQLNodes } from './merge-nodes'; -import { resetComments } from './comments'; +import { resetComments, printWithComments } from './comments'; import { fixSchemaAst } from '@graphql-toolkit/common'; type Omit = Pick>; @@ -105,7 +105,7 @@ export function mergeTypeDefs(types: Array Date: Mon, 30 Dec 2019 01:38:56 +0300 Subject: [PATCH 7/8] Add tests for shadowed variable --- packages/core/package.json | 1 - packages/core/src/load-typedefs.ts | 5 +++-- .../tests/loaders/schema/fixtures/import-shadowed/a.graphql | 5 +++++ .../tests/loaders/schema/fixtures/import-shadowed/b.graphql | 5 +++++ .../tests/loaders/schema/fixtures/import-shadowed/c.graphql | 4 ++++ packages/core/tests/loaders/schema/import-schema.spec.ts | 2 +- 6 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 packages/core/tests/loaders/schema/fixtures/import-shadowed/a.graphql create mode 100644 packages/core/tests/loaders/schema/fixtures/import-shadowed/b.graphql create mode 100644 packages/core/tests/loaders/schema/fixtures/import-shadowed/c.graphql diff --git a/packages/core/package.json b/packages/core/package.json index 59f14765..99b19102 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -46,7 +46,6 @@ "@graphql-toolkit/schema-merging": "0.7.5", "aggregate-error": "3.0.1", "globby": "10.0.1", - "graphql-import": "0.7.1", "is-glob": "4.0.1", "tslib": "1.10.0", "valid-url": "1.0.9", diff --git a/packages/core/src/load-typedefs.ts b/packages/core/src/load-typedefs.ts index 585aa9e9..d80835f8 100644 --- a/packages/core/src/load-typedefs.ts +++ b/packages/core/src/load-typedefs.ts @@ -1,4 +1,4 @@ -import { GraphQLSchema, parse, Kind, Source as GraphQLSource, print } from 'graphql'; +import { GraphQLSchema, parse, Kind, Source as GraphQLSource } from 'graphql'; import { Source, asArray, isDocumentString, debugLog, fixWindowsPath, printSchemaWithDirectives, parseGraphQLSDL, fixSchemaAst, SingleFileOptions, Loader } from '@graphql-toolkit/common'; import { join } from 'path'; import isGlob from 'is-glob'; @@ -6,6 +6,7 @@ import globby from 'globby'; import { filterKind } from './filter-document-kind'; import { RawModule, processImportSyntax, isEmptySDL } from './import-parser'; import { ValidDefinitionNode } from './import-parser/definition'; +import { printWithComments } from '@graphql-toolkit/schema-merging'; export type LoadTypedefsOptions = SingleFileOptions & ExtraConfig & { @@ -237,7 +238,7 @@ export async function loadTypedefs(pointerOrPointers: Unn resultSource.document = filterKind(resultSource.document, options.filterKinds); } if (!resultSource.rawSDL) { - resultSource.rawSDL = print(resultSource.document); + resultSource.rawSDL = printWithComments(resultSource.document); } if (options.forceGraphQLImport || (!options.skipGraphQLImport && /^\#.*import /i.test(resultSource.rawSDL.trimLeft()))) { await processImportSyntax(resultSource, options); diff --git a/packages/core/tests/loaders/schema/fixtures/import-shadowed/a.graphql b/packages/core/tests/loaders/schema/fixtures/import-shadowed/a.graphql new file mode 100644 index 00000000..2112f155 --- /dev/null +++ b/packages/core/tests/loaders/schema/fixtures/import-shadowed/a.graphql @@ -0,0 +1,5 @@ +# import B from "b.graphql" + +type Query { + b: B! +} \ No newline at end of file diff --git a/packages/core/tests/loaders/schema/fixtures/import-shadowed/b.graphql b/packages/core/tests/loaders/schema/fixtures/import-shadowed/b.graphql new file mode 100644 index 00000000..e5cceb0b --- /dev/null +++ b/packages/core/tests/loaders/schema/fixtures/import-shadowed/b.graphql @@ -0,0 +1,5 @@ +# import X from './c.graphql' + +type B { + x: X +} diff --git a/packages/core/tests/loaders/schema/fixtures/import-shadowed/c.graphql b/packages/core/tests/loaders/schema/fixtures/import-shadowed/c.graphql new file mode 100644 index 00000000..cb83162e --- /dev/null +++ b/packages/core/tests/loaders/schema/fixtures/import-shadowed/c.graphql @@ -0,0 +1,4 @@ +scalar X +type B { + private: Int +} diff --git a/packages/core/tests/loaders/schema/import-schema.spec.ts b/packages/core/tests/loaders/schema/import-schema.spec.ts index 1e21f123..f299c741 100644 --- a/packages/core/tests/loaders/schema/import-schema.spec.ts +++ b/packages/core/tests/loaders/schema/import-schema.spec.ts @@ -1002,5 +1002,5 @@ test('import schema with shadowed type', async () => { } scalar X ` - expect(normalizeDocumentString(await importSchema('fixtures/import-shadowed/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) + expect(normalizeDocumentString(await importSchema('./fixtures/import-shadowed/a.graphql'))).toBe(normalizeDocumentString(expectedSDL)) }) \ No newline at end of file From b0fd1798c396817722bd1520ea26103dd64b1b74 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Mon, 30 Dec 2019 01:42:32 +0300 Subject: [PATCH 8/8] Use absolute: true --- packages/file-loading/src/file-scanner.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/file-loading/src/file-scanner.ts b/packages/file-loading/src/file-scanner.ts index 42a73912..75fa3ce8 100644 --- a/packages/file-loading/src/file-scanner.ts +++ b/packages/file-loading/src/file-scanner.ts @@ -60,7 +60,9 @@ const LoadFilesDefaultOptions: LoadFilesOptions = { extensions: DEFAULT_EXTENSIONS, useRequire: false, requireMethod: null, - globOptions: {}, + globOptions: { + absolute: true, + }, exportNames: DEFAULT_EXPORT_NAMES, recursive: true, ignoreIndex: false, @@ -103,7 +105,7 @@ export function loadFiles(path: string, options: LoadFilesOptions = LoadFilesDef } function scanForFilesAsync(globStr: string, globOptions: import('globby').GlobbyOptions = {}): Promise { - return globby(globStr, { absolute: true, ...globOptions }); + return globby(globStr, { absolute: true, ...globOptions, ignore: [] }); } const checkExtension = (path: string, { extensions, ignoredExtensions }: { extensions?: string[]; ignoredExtensions?: string[] }) => {