Skip to content

Commit

Permalink
enhance(code-file-loader): return one source for each code file
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Aug 12, 2021
1 parent 67691b7 commit 1c6fb01
Show file tree
Hide file tree
Showing 19 changed files with 553 additions and 154 deletions.
11 changes: 9 additions & 2 deletions .changeset/short-ladybugs-develop.md
@@ -1,9 +1,16 @@
---
'@graphql-tools/merge': major
'@graphql-tools/schema': minor
'@graphql-tools/stitch': minor
'@graphql-tools/utils': minor
'@graphql-tools/code-file-loader': major
---

Breaking Change;
`schemaExtensions` option has been added to `mergeSchemas`, `makeExecutableSchema` and `stitchSchemas` configurations

Move `mergeSchemas` from `@graphql-tools/merge` to `@graphql-tools/schema` package to prevent circular dependency between them.
Breaking Changes;

- Move `mergeSchemas` and `MergeSchemasConfig` from `@graphql-tools/merge` to `@graphql-tools/schema` package to prevent circular dependency between them.
- `mergeSchemasAsync` has been removed.
- Move `NamedDefinitionNode`, `resetComments`, `collectComment`, `pushComment` and `printComment` from `@graphql-tools/merge` to `@graphql-tools/utils`.
- Code File Loader no more returns multiple sources for each plucked GraphQL SDL. This breaks other tools such as GraphQL Code Generator.
1 change: 0 additions & 1 deletion packages/load/package.json
Expand Up @@ -35,7 +35,6 @@
},
"dependencies": {
"@graphql-tools/utils": "8.0.2",
"@graphql-tools/merge": "7.0.0",
"@graphql-tools/schema": "8.0.3",
"p-limit": "3.1.0",
"tslib": "~2.3.0"
Expand Down
10 changes: 8 additions & 2 deletions packages/load/src/load-typedefs/parse.ts
@@ -1,5 +1,11 @@
import { Source, printSchemaWithDirectives, fixSchemaAst, parseGraphQLSDL } from '@graphql-tools/utils';
import { printWithComments, resetComments } from '@graphql-tools/merge';
import {
Source,
printSchemaWithDirectives,
fixSchemaAst,
parseGraphQLSDL,
printWithComments,
resetComments,
} from '@graphql-tools/utils';
import { filterKind } from '../filter-document-kind';

type Options = any;
Expand Down
4 changes: 2 additions & 2 deletions packages/load/src/schema.ts
@@ -1,7 +1,7 @@
import { loadTypedefs, LoadTypedefsOptions, UnnormalizedTypeDefPointer, loadTypedefsSync } from './load-typedefs';
import { GraphQLSchema, BuildSchemaOptions, DocumentNode, Source as GraphQLSource, print } from 'graphql';
import { OPERATION_KINDS } from './documents';
import { mergeSchemasAsync, mergeSchemas, MergeSchemasConfig } from '@graphql-tools/schema';
import { mergeSchemas, MergeSchemasConfig } from '@graphql-tools/schema';
import { Source } from '@graphql-tools/utils';

export type LoadSchemaOptions = BuildSchemaOptions &
Expand Down Expand Up @@ -36,7 +36,7 @@ export async function loadSchema(
typeDefs,
};

const schema = await mergeSchemasAsync(mergeSchemasOptions);
const schema = mergeSchemas(mergeSchemasOptions);

if (options?.includeSources) {
includeSources(schema, sources);
Expand Down
Expand Up @@ -56,7 +56,7 @@ describe('documentsFromGlob', () => {
loaders: [new CodeFileLoader()]
});

expect(result).toHaveLength(2);
expect(result).toHaveLength(1);
});

test(`Should load GraphQL operations that match custom settings`, async () => {
Expand Down Expand Up @@ -166,7 +166,7 @@ describe('documentsFromGlob', () => {
});
// 1 from 2.graphql
// 2 from tags.js
expect(result.length).toEqual(3);
expect(result.length).toEqual(2);
})
})
});
33 changes: 24 additions & 9 deletions packages/loaders/code-file/src/index.ts
@@ -1,6 +1,14 @@
import type { GlobbyOptions } from 'globby';

import { isSchema, GraphQLSchema, DocumentNode, parse } from 'graphql';
import {
isSchema,
GraphQLSchema,
DocumentNode,
parse,
concatAST,
Source as GraphQLSource,
ParseOptions,
} from 'graphql';
import {
Source,
asArray,
Expand Down Expand Up @@ -162,11 +170,12 @@ export class CodeFileLoader implements Loader<CodeFileLoaderOptions> {
const sources = await gqlPluckFromCodeString(normalizedFilePath, content, options.pluckConfig);

if (sources.length) {
return sources.map(source => ({
document: parse(source, options),
const mergedDocument = flattenSources(sources, options);
const mergedSource = {
document: mergedDocument,
location,
rawSDL: source.body,
}));
};
return [mergedSource];
}
} catch (e) {
if (env['DEBUG']) {
Expand Down Expand Up @@ -215,11 +224,12 @@ export class CodeFileLoader implements Loader<CodeFileLoaderOptions> {
const sources = gqlPluckFromCodeStringSync(normalizedFilePath, content, options.pluckConfig);

if (sources.length) {
return sources.map(source => ({
document: parse(source, options),
const mergedDocument = flattenSources(sources, options);
const mergedSource = {
document: mergedDocument,
location,
rawSDL: source.body,
}));
};
return [mergedSource];
}
} catch (e) {
if (env['DEBUG']) {
Expand Down Expand Up @@ -257,6 +267,11 @@ export class CodeFileLoader implements Loader<CodeFileLoaderOptions> {
}
}

function flattenSources(sources: GraphQLSource[], options: ParseOptions) {
const documents = sources.map(source => parse(source, options));
return concatAST(documents);
}

function resolveSource(
pointer: string,
value: GraphQLSchema | DocumentNode | string | null,
Expand Down
77 changes: 41 additions & 36 deletions packages/loaders/code-file/tests/load-from-code-file.spec.ts
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
import * as path from 'path';
import { CodeFileLoader } from '../src';
import { parse } from 'graphql';
import { parse, print } from 'graphql';

describe('loadFromCodeFile', () => {
const loader = new CodeFileLoader();
Expand Down Expand Up @@ -128,40 +128,33 @@ describe('loadFromCodeFileSync', () => {
});

it('should support loading many in same file', () => {
const loaded = loader.loadSync('./test-files/multiple-from-file.ts', {
const loadedSources = loader.loadSync('./test-files/multiple-from-file.ts', {
cwd: __dirname,
pluckConfig: {
skipIndent: true,
},
});
expect(loaded?.length).toEqual(3);
expect(loaded?.[0].rawSDL).toBeDefined();
expect(loaded?.[0].rawSDL).toMatchInlineSnapshot(`
"
query Foo {
Tweets {
id
}
}
"
`);
expect(loaded?.[1].rawSDL).toBeDefined();
expect(loaded?.[1].rawSDL).toMatchInlineSnapshot(`
"
fragment Lel on Tweet {
expect(loadedSources?.length).toEqual(1);
const loadedSource = loadedSources![0];
expect(loadedSource.document).toBeDefined();
const rawSDL = print(loadedSource.document!);
expect(rawSDL).toMatchInlineSnapshot(`
"query Foo {
Tweets {
id
body
}
"
`);
expect(loaded?.[2].rawSDL).toBeDefined();
expect(loaded?.[2].rawSDL).toMatchInlineSnapshot(`
"
query Bar {
Tweets {
...Lel
}
}
fragment Lel on Tweet {
id
body
}
query Bar {
Tweets {
...Lel
}
}
"
`);
});
Expand All @@ -172,18 +165,30 @@ describe('loadFromCodeFileSync', () => {
skipIndent: true
}
})
const loaded = loader.loadSync('./test-files/multiple-from-file.ts', {
const loadedSources = loader.loadSync('./test-files/multiple-from-file.ts', {
cwd: __dirname,
});
expect(loaded?.length).toEqual(3);
expect(loaded?.[0].rawSDL).toBeDefined();
expect(loaded?.[0].rawSDL).toMatchInlineSnapshot(`
"
query Foo {
Tweets {
id
}
expect(loadedSources?.length).toEqual(1);
const loadedSource = loadedSources![0];
expect(loadedSource.document).toBeDefined();
const rawSDL = print(loadedSource.document!);
expect(rawSDL).toMatchInlineSnapshot(`
"query Foo {
Tweets {
id
}
}
fragment Lel on Tweet {
id
body
}
query Bar {
Tweets {
...Lel
}
}
"
`);
})
Expand Down
23 changes: 17 additions & 6 deletions packages/loaders/git/src/index.ts
Expand Up @@ -122,7 +122,7 @@ export class GitLoader implements Loader<GitLoaderOptions> {
return resolved;
}

private async _load(pointer: string, options: GitLoaderOptions): Promise<Source[]> {
private async handleSingularPointerAsync(pointer: string, options: GitLoaderOptions): Promise<Source[]> {
const result = extractData(pointer);
if (result === null) {
return [];
Expand Down Expand Up @@ -157,17 +157,22 @@ export class GitLoader implements Loader<GitLoaderOptions> {
await Promise.all(
resolvedPaths.map(async path => {
const results = await this.load(path, options);
finalResult.push(...results);
for (const result of results) {
finalResult.push(result);
}
})
);
} else if (await this.canLoad(pointer)) {
finalResult.push(...(await this._load(pointer, options)));
const results = await this.handleSingularPointerAsync(pointer, options);
for (const result of results) {
finalResult.push(result);
}
}

return finalResult;
}

private _loadSync(pointer: string, options: GitLoaderOptions): Source[] {
private handleSingularPointerSync(pointer: string, options: GitLoaderOptions): Source[] {
const result = extractData(pointer);
if (result === null) {
return [];
Expand Down Expand Up @@ -202,11 +207,17 @@ export class GitLoader implements Loader<GitLoaderOptions> {
const finalResult: Source[] = [];
for (const path of resolvedPaths) {
if (this.canLoadSync(path)) {
finalResult.push(...this.loadSync(path, options));
const results = this.loadSync(path, options);
for (const result of results) {
finalResult.push(result);
}
}
}
} else if (this.canLoadSync(pointer)) {
finalResult.push(...this._loadSync(pointer, options));
const results = this.handleSingularPointerSync(pointer, options);
for (const result of results) {
finalResult.push(result);
}
}

return finalResult;
Expand Down
4 changes: 2 additions & 2 deletions packages/merge/src/typedefs-mergers/merge-nodes.ts
@@ -1,5 +1,5 @@
import { Config } from './merge-typedefs';
import { DefinitionNode, Kind, NameNode, SchemaDefinitionNode, SchemaExtensionNode } from 'graphql';
import { DefinitionNode, Kind, SchemaDefinitionNode, SchemaExtensionNode } from 'graphql';
import { mergeType } from './type';
import { mergeEnum } from './enum';
import { mergeScalar } from './scalar';
Expand All @@ -9,13 +9,13 @@ import { mergeInterface } from './interface';
import { mergeDirective } from './directives';
import { collectComment } from './comments';
import { mergeSchemaDefs } from './schema-def';
import { NamedDefinitionNode } from '@graphql-tools/utils';

export const schemaDefSymbol = 'SCHEMA_DEF_SYMBOL';

export type MergedResultMap = Record<string, NamedDefinitionNode> & {
[schemaDefSymbol]: SchemaDefinitionNode | SchemaExtensionNode;
};
export type NamedDefinitionNode = DefinitionNode & { name?: NameNode };

export function isNamedDefinitionNode(definitionNode: DefinitionNode): definitionNode is NamedDefinitionNode {
return 'name' in definitionNode;
Expand Down
1 change: 0 additions & 1 deletion packages/mock/package.json
Expand Up @@ -33,7 +33,6 @@
},
"dependencies": {
"@graphql-tools/schema": "^8.0.3",
"@graphql-tools/merge": "7.0.0",
"@graphql-tools/utils": "8.0.2",
"fast-json-stable-stringify": "^2.1.0",
"tslib": "~2.3.0"
Expand Down
24 changes: 12 additions & 12 deletions packages/mock/src/mockServer.ts
@@ -1,6 +1,6 @@
import { TypeSource } from '@graphql-tools/utils';
import { GraphQLSchema, isSchema, graphql, buildASTSchema } from 'graphql';
import { mergeTypeDefs } from '@graphql-tools/merge';
import { isSchema, graphql } from 'graphql';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { addMocksToSchema } from './addMocksToSchema';
import { IMockServer, IMocks } from './types';

Expand All @@ -17,15 +17,15 @@ import { IMockServer, IMocks } from './types';
* server and not others.
*/
export function mockServer(schema: TypeSource, mocks: IMocks, preserveResolvers = false): IMockServer {
let mySchema: GraphQLSchema;
if (!isSchema(schema)) {
// TODO: provide useful error messages here if this fails
mySchema = buildASTSchema(mergeTypeDefs(schema));
} else {
mySchema = schema;
}
const mockedSchema = addMocksToSchema({
schema: isSchema(schema)
? schema
: makeExecutableSchema({
typeDefs: schema,
}),
mocks,
preserveResolvers,
});

mySchema = addMocksToSchema({ schema: mySchema, mocks, preserveResolvers });

return { query: (query, vars) => graphql(mySchema, query, {}, {}, vars) };
return { query: (query, vars) => graphql(mockedSchema, query, {}, {}, vars) };
}

0 comments on commit 1c6fb01

Please sign in to comment.