Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Merge Schemas behavior and remove legacy signature in addResolversToSchema #4463

Merged
merged 7 commits into from Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
76 changes: 76 additions & 0 deletions .changeset/fifty-experts-unite.md
@@ -0,0 +1,76 @@
---
'@graphql-tools/schema': major
---

Thanks @mattkrick and @borisno2!

## Breaking changes

`addResolversToSchema`;

If you are using the legacy parameters like below, you should update them to the new usage. Other than that, there is no functional change;

```ts
// From
addResolversToSchema(schema, resolvers, resolverValidationOptions)

// To
addResolversToSchema({
schema,
resolvers,
resolverValidationOptions
})
```

`mergeSchemas`;

The provided `resolver` overrides the resolvers in the `schema` with the same name;

The `hello` resolver in the `schema` would be overridden by the `hello` resolver in the `resolvers`. Before it was opposite which is not expected.

```ts
const schema = makeExecutableSchema({
typeDefs: `
type Query {
hello: String
}
`,
resolvers: {
Query: {
hello: () => 'Hello world!'
}
}
})

mergeSchemas({
schemas: [schema],
resolvers: {
Query: {
hello: () => 'New hello world'
}
}
})
```

`makeExecutableSchema` no longer takes `parseOptions` and you can pass those options directly;

```ts
makeExecutableSchema({
typeDefs: ``,
parseOptions: {
assumeValid: true
}
})

// After
makeExecutableSchema({
typeDefs: ``,
assumeValid: true
})
```

`makeExecutableSchema` no longer does pruning and it doesn't take `pruningOptions` anymore.
You can use `pruneSchema` from `@graphql-tools/utils` if you need.

`extractExtensionsFromSchema` moved from `@graphql-tools/merge` to `@graphql-tools/schema`.
And `travelSchemaPossibleExtensions` has been dropped in favor of `mapSchema`.
2 changes: 1 addition & 1 deletion .changeset/tiny-zoos-dance.md
Expand Up @@ -3,7 +3,7 @@
'@graphql-tools/wrap': major
---

Breaking changes;
## Breaking changes

**Schema generation optimization by removing `transfomedSchema` parameter**

Expand Down
90 changes: 41 additions & 49 deletions packages/load/src/schema.ts
@@ -1,19 +1,12 @@
import { loadTypedefs, LoadTypedefsOptions, UnnormalizedTypeDefPointer, loadTypedefsSync } from './load-typedefs.js';
import {
GraphQLSchema,
BuildSchemaOptions,
DocumentNode,
Source as GraphQLSource,
print,
lexicographicSortSchema,
} from 'graphql';
import { OPERATION_KINDS } from './documents.js';
import { mergeSchemas, MergeSchemasConfig } from '@graphql-tools/schema';
import { Source } from '@graphql-tools/utils';
import { GraphQLSchema, BuildSchemaOptions, Source as GraphQLSource, print, lexicographicSortSchema } from 'graphql';
import { OPERATION_KINDS } from './documents';
import { IExecutableSchemaDefinition, mergeSchemas, extractExtensionsFromSchema } from '@graphql-tools/schema';
import { getResolversFromSchema, IResolvers, SchemaExtensions, Source, TypeSource } from '@graphql-tools/utils';

export type LoadSchemaOptions = BuildSchemaOptions &
LoadTypedefsOptions &
Partial<MergeSchemasConfig> & {
Partial<IExecutableSchemaDefinition> & {
/**
* Adds a list of Sources in to `extensions.sources`
*
Expand All @@ -35,22 +28,7 @@ export async function loadSchema(
...options,
filterKinds: OPERATION_KINDS,
});

const { schemas, typeDefs } = collectSchemasAndTypeDefs(sources);
schemas.push(...(options.schemas ?? []));
const mergeSchemasOptions: MergeSchemasConfig = {
...options,
schemas: schemas.concat(options.schemas ?? []),
typeDefs,
};

const schema = typeDefs?.length === 0 && schemas?.length === 1 ? schemas[0] : mergeSchemas(mergeSchemasOptions);

if (options?.includeSources) {
includeSources(schema, sources);
}

return options.sort ? lexicographicSortSchema(schema) : schema;
return getSchemaFromSources(sources, options);
}

/**
Expand All @@ -66,20 +44,7 @@ export function loadSchemaSync(
filterKinds: OPERATION_KINDS,
...options,
});

const { schemas, typeDefs } = collectSchemasAndTypeDefs(sources);

const schema = mergeSchemas({
schemas,
typeDefs,
...options,
});

if (options?.includeSources) {
includeSources(schema, sources);
}

return options.sort ? lexicographicSortSchema(schema) : schema;
return getSchemaFromSources(sources, options);
}

function includeSources(schema: GraphQLSchema, sources: Source[]) {
Expand All @@ -98,20 +63,47 @@ function includeSources(schema: GraphQLSchema, sources: Source[]) {
};
}

function collectSchemasAndTypeDefs(sources: Source[]) {
const schemas: GraphQLSchema[] = [];
const typeDefs: DocumentNode[] = [];
function getSchemaFromSources(sources: Source[], options: LoadSchemaOptions) {
if (sources.length === 1 && sources[0].schema != null && options.typeDefs == null && options.resolvers == null) {
return options.sort ? lexicographicSortSchema(sources[0].schema) : sources[0].schema;
}
const { typeDefs, resolvers, schemaExtensions } = collectSchemaParts(sources);

const schema = mergeSchemas({
...options,
typeDefs,
resolvers,
schemaExtensions,
});

if (options?.includeSources) {
includeSources(schema, sources);
}

return options.sort ? lexicographicSortSchema(schema) : schema;
}

function collectSchemaParts(sources: Source[]) {
const typeDefs: TypeSource[] = [];
const resolvers: IResolvers[] = [];
const schemaExtensions: SchemaExtensions[] = [];

for (const source of sources) {
if (source.schema) {
schemas.push(source.schema);
} else if (source.document) {
typeDefs.push(source.document);
typeDefs.push(source.schema);
resolvers.push(getResolversFromSchema(source.schema));
schemaExtensions.push(extractExtensionsFromSchema(source.schema));
} else {
const typeDef = source.document || source.rawSDL;
if (typeDef) {
typeDefs.push(typeDef);
}
}
}

return {
schemas,
typeDefs,
resolvers,
schemaExtensions,
};
}