Skip to content

Commit

Permalink
Go
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Aug 9, 2022
1 parent 1f5c69f commit 7510162
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 187 deletions.
4 changes: 4 additions & 0 deletions .changeset/fifty-experts-unite.md
Expand Up @@ -4,6 +4,8 @@

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;
Expand Down Expand Up @@ -66,3 +68,5 @@ makeExecutableSchema({
assumeValid: true
})
```

`extractExtensionsFromSchema` moved from `@graphql-tools/merge` to `@graphql-tools/schema`.
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
1 change: 0 additions & 1 deletion packages/load/package.json
Expand Up @@ -57,7 +57,6 @@
"dependencies": {
"@graphql-tools/utils": "8.9.0",
"@graphql-tools/schema": "8.5.1",
"@graphql-tools/merge": "8.3.1",
"p-limit": "3.1.0",
"tslib": "^2.4.0"
},
Expand Down
5 changes: 2 additions & 3 deletions packages/load/src/schema.ts
@@ -1,9 +1,8 @@
import { loadTypedefs, LoadTypedefsOptions, UnnormalizedTypeDefPointer, loadTypedefsSync } from './load-typedefs';
import { GraphQLSchema, BuildSchemaOptions, Source as GraphQLSource, print, lexicographicSortSchema } from 'graphql';
import { OPERATION_KINDS } from './documents';
import { IExecutableSchemaDefinition, mergeSchemas } from '@graphql-tools/schema';
import { getResolversFromSchema, IResolvers, Source, TypeSource } from '@graphql-tools/utils';
import { extractExtensionsFromSchema, SchemaExtensions } from '@graphql-tools/merge';
import { IExecutableSchemaDefinition, mergeSchemas, extractExtensionsFromSchema } from '@graphql-tools/schema';
import { getResolversFromSchema, IResolvers, SchemaExtensions, Source, TypeSource } from '@graphql-tools/utils';

export type LoadSchemaOptions = BuildSchemaOptions &
LoadTypedefsOptions &
Expand Down
181 changes: 2 additions & 179 deletions packages/merge/src/extensions.ts
@@ -1,143 +1,5 @@
import {
GraphQLSchema,
isObjectType,
isInterfaceType,
isInputObjectType,
GraphQLField,
GraphQLInputField,
isUnionType,
isScalarType,
isEnumType,
isSpecifiedScalarType,
isIntrospectionType,
GraphQLObjectType,
GraphQLInputObjectType,
GraphQLUnionType,
GraphQLScalarType,
GraphQLArgument,
GraphQLEnumType,
GraphQLEnumValue,
GraphQLInterfaceType,
} from 'graphql';
import { Maybe, mergeDeep } from '@graphql-tools/utils';

export type ExtensionsObject = Record<string, any>;

export type ObjectTypeExtensions = {
type: 'object';
fields: Record<string, { extensions: ExtensionsObject; arguments: Record<string, ExtensionsObject> }>;
};

export type InputTypeExtensions = {
type: 'input';
fields: Record<string, { extensions: ExtensionsObject }>;
};

export type InterfaceTypeExtensions = {
type: 'interface';
fields: Record<string, { extensions: ExtensionsObject; arguments: Record<string, ExtensionsObject> }>;
};

export type UnionTypeExtensions = {
type: 'union';
};

export type ScalarTypeExtensions = {
type: 'scalar';
};

export type EnumTypeExtensions = {
type: 'enum';
values: Record<string, ExtensionsObject>;
};

export type PossibleTypeExtensions =
| InputTypeExtensions
| InterfaceTypeExtensions
| ObjectTypeExtensions
| UnionTypeExtensions
| ScalarTypeExtensions
| EnumTypeExtensions;
export type SchemaExtensions = {
schemaExtensions: ExtensionsObject;
types: Record<string, { extensions: ExtensionsObject } & PossibleTypeExtensions>;
};

export function travelSchemaPossibleExtensions(
schema: GraphQLSchema,
hooks: {
onSchema: (schema: GraphQLSchema) => any;
onObjectType: (type: GraphQLObjectType) => any;
onObjectField: (type: GraphQLObjectType, field: GraphQLField<any, any>) => any;
onObjectFieldArg: (type: GraphQLObjectType, field: GraphQLField<any, any>, arg: GraphQLArgument) => any;
onInterface: (type: GraphQLInterfaceType) => any;
onInterfaceField: (type: GraphQLInterfaceType, field: GraphQLField<any, any>) => any;
onInterfaceFieldArg: (type: GraphQLInterfaceType, field: GraphQLField<any, any>, arg: GraphQLArgument) => any;
onInputType: (type: GraphQLInputObjectType) => any;
onInputFieldType: (type: GraphQLInputObjectType, field: GraphQLInputField) => any;
onUnion: (type: GraphQLUnionType) => any;
onScalar: (type: GraphQLScalarType) => any;
onEnum: (type: GraphQLEnumType) => any;
onEnumValue: (type: GraphQLEnumType, value: GraphQLEnumValue) => any;
}
) {
hooks.onSchema(schema);
const typesMap = schema.getTypeMap();

for (const [, type] of Object.entries(typesMap)) {
const isPredefinedScalar = isScalarType(type) && isSpecifiedScalarType(type);
const isIntrospection = isIntrospectionType(type);

if (isPredefinedScalar || isIntrospection) {
continue;
}

if (isObjectType(type)) {
hooks.onObjectType(type);

const fields = type.getFields();
for (const [, field] of Object.entries(fields)) {
hooks.onObjectField(type, field);

const args = field.args || [];

for (const arg of args) {
hooks.onObjectFieldArg(type, field, arg);
}
}
} else if (isInterfaceType(type)) {
hooks.onInterface(type);

const fields = type.getFields();
for (const [, field] of Object.entries(fields)) {
hooks.onInterfaceField(type, field);

const args = field.args || [];

for (const arg of args) {
hooks.onInterfaceFieldArg(type, field, arg);
}
}
} else if (isInputObjectType(type)) {
hooks.onInputType(type);

const fields = type.getFields();
for (const [, field] of Object.entries(fields)) {
hooks.onInputFieldType(type, field);
}
} else if (isUnionType(type)) {
hooks.onUnion(type);
} else if (isScalarType(type)) {
hooks.onScalar(type);
} else if (isEnumType(type)) {
hooks.onEnum(type);

for (const value of type.getValues()) {
hooks.onEnumValue(type, value);
}
}
}
}
import { GraphQLSchema, GraphQLObjectType, GraphQLEnumType } from 'graphql';
import { ExtensionsObject, Maybe, mergeDeep, SchemaExtensions } from '@graphql-tools/utils';

export function mergeExtensions(extensions: SchemaExtensions[]): SchemaExtensions {
return mergeDeep(extensions);
Expand Down Expand Up @@ -194,42 +56,3 @@ export function applyExtensions(schema: GraphQLSchema, extensions: SchemaExtensi

return schema;
}

export function extractExtensionsFromSchema(schema: GraphQLSchema): SchemaExtensions {
const result: SchemaExtensions = {
schemaExtensions: {},
types: {},
};

travelSchemaPossibleExtensions(schema, {
onSchema: schema => (result.schemaExtensions = schema.extensions || {}),
onObjectType: type => (result.types[type.name] = { fields: {}, type: 'object', extensions: type.extensions || {} }),
onObjectField: (type, field) =>
((result.types[type.name] as ObjectTypeExtensions).fields[field.name] = {
arguments: {},
extensions: field.extensions || {},
}),
onObjectFieldArg: (type, field, arg) =>
((result.types[type.name] as ObjectTypeExtensions).fields[field.name].arguments[arg.name] = arg.extensions || {}),
onInterface: type =>
(result.types[type.name] = { fields: {}, type: 'interface', extensions: type.extensions || {} }),
onInterfaceField: (type, field) =>
((result.types[type.name] as InterfaceTypeExtensions).fields[field.name] = {
arguments: {},
extensions: field.extensions || {},
}),
onInterfaceFieldArg: (type, field, arg) =>
((result.types[type.name] as InterfaceTypeExtensions).fields[field.name].arguments[arg.name] =
arg.extensions || {}),
onEnum: type => (result.types[type.name] = { values: {}, type: 'enum', extensions: type.extensions || {} }),
onEnumValue: (type, value) =>
((result.types[type.name] as EnumTypeExtensions).values[value.name] = value.extensions || {}),
onScalar: type => (result.types[type.name] = { type: 'scalar', extensions: type.extensions || {} }),
onUnion: type => (result.types[type.name] = { type: 'union', extensions: type.extensions || {} }),
onInputType: type => (result.types[type.name] = { fields: {}, type: 'input', extensions: type.extensions || {} }),
onInputFieldType: (type, field) =>
((result.types[type.name] as InputTypeExtensions).fields[field.name] = { extensions: field.extensions || {} }),
});

return result;
}
3 changes: 2 additions & 1 deletion packages/merge/tests/extract-extensions-from-schema.spec.ts
Expand Up @@ -8,7 +8,8 @@ import {
assertGraphQLScalerType,
} from '../../testing/assertion.js';
import { assertSome } from '@graphql-tools/utils';
import { extractExtensionsFromSchema, mergeExtensions, applyExtensions } from '../src/extensions.js';
import { mergeExtensions, applyExtensions } from '../src/extensions.js';
import { extractExtensionsFromSchema } from '@graphql-tools/schema';

describe('extensions', () => {
let schema: GraphQLSchema;
Expand Down
143 changes: 143 additions & 0 deletions packages/schema/src/extractExtensionsFromSchema.ts
@@ -0,0 +1,143 @@
import {
SchemaExtensions,
ObjectTypeExtensions,
InterfaceTypeExtensions,
EnumTypeExtensions,
InputTypeExtensions,
} from '@graphql-tools/utils';
import {
GraphQLArgument,
GraphQLEnumType,
GraphQLEnumValue,
GraphQLField,
GraphQLInputField,
GraphQLInputObjectType,
GraphQLInterfaceType,
GraphQLObjectType,
GraphQLScalarType,
GraphQLSchema,
GraphQLUnionType,
isEnumType,
isInputObjectType,
isInterfaceType,
isIntrospectionType,
isObjectType,
isScalarType,
isSpecifiedScalarType,
isUnionType,
} from 'graphql';

export function travelSchemaPossibleExtensions(
schema: GraphQLSchema,
hooks: {
onSchema: (schema: GraphQLSchema) => any;
onObjectType: (type: GraphQLObjectType) => any;
onObjectField: (type: GraphQLObjectType, field: GraphQLField<any, any>) => any;
onObjectFieldArg: (type: GraphQLObjectType, field: GraphQLField<any, any>, arg: GraphQLArgument) => any;
onInterface: (type: GraphQLInterfaceType) => any;
onInterfaceField: (type: GraphQLInterfaceType, field: GraphQLField<any, any>) => any;
onInterfaceFieldArg: (type: GraphQLInterfaceType, field: GraphQLField<any, any>, arg: GraphQLArgument) => any;
onInputType: (type: GraphQLInputObjectType) => any;
onInputFieldType: (type: GraphQLInputObjectType, field: GraphQLInputField) => any;
onUnion: (type: GraphQLUnionType) => any;
onScalar: (type: GraphQLScalarType) => any;
onEnum: (type: GraphQLEnumType) => any;
onEnumValue: (type: GraphQLEnumType, value: GraphQLEnumValue) => any;
}
) {
hooks.onSchema(schema);
const typesMap = schema.getTypeMap();

for (const [, type] of Object.entries(typesMap)) {
const isPredefinedScalar = isScalarType(type) && isSpecifiedScalarType(type);
const isIntrospection = isIntrospectionType(type);

if (isPredefinedScalar || isIntrospection) {
continue;
}

if (isObjectType(type)) {
hooks.onObjectType(type);

const fields = type.getFields();
for (const [, field] of Object.entries(fields)) {
hooks.onObjectField(type, field);

const args = field.args || [];

for (const arg of args) {
hooks.onObjectFieldArg(type, field, arg);
}
}
} else if (isInterfaceType(type)) {
hooks.onInterface(type);

const fields = type.getFields();
for (const [, field] of Object.entries(fields)) {
hooks.onInterfaceField(type, field);

const args = field.args || [];

for (const arg of args) {
hooks.onInterfaceFieldArg(type, field, arg);
}
}
} else if (isInputObjectType(type)) {
hooks.onInputType(type);

const fields = type.getFields();
for (const [, field] of Object.entries(fields)) {
hooks.onInputFieldType(type, field);
}
} else if (isUnionType(type)) {
hooks.onUnion(type);
} else if (isScalarType(type)) {
hooks.onScalar(type);
} else if (isEnumType(type)) {
hooks.onEnum(type);

for (const value of type.getValues()) {
hooks.onEnumValue(type, value);
}
}
}
}

export function extractExtensionsFromSchema(schema: GraphQLSchema): SchemaExtensions {
const result: SchemaExtensions = {
schemaExtensions: {},
types: {},
};

travelSchemaPossibleExtensions(schema, {
onSchema: schema => (result.schemaExtensions = schema.extensions || {}),
onObjectType: type => (result.types[type.name] = { fields: {}, type: 'object', extensions: type.extensions || {} }),
onObjectField: (type, field) =>
((result.types[type.name] as ObjectTypeExtensions).fields[field.name] = {
arguments: {},
extensions: field.extensions || {},
}),
onObjectFieldArg: (type, field, arg) =>
((result.types[type.name] as ObjectTypeExtensions).fields[field.name].arguments[arg.name] = arg.extensions || {}),
onInterface: type =>
(result.types[type.name] = { fields: {}, type: 'interface', extensions: type.extensions || {} }),
onInterfaceField: (type, field) =>
((result.types[type.name] as InterfaceTypeExtensions).fields[field.name] = {
arguments: {},
extensions: field.extensions || {},
}),
onInterfaceFieldArg: (type, field, arg) =>
((result.types[type.name] as InterfaceTypeExtensions).fields[field.name].arguments[arg.name] =
arg.extensions || {}),
onEnum: type => (result.types[type.name] = { values: {}, type: 'enum', extensions: type.extensions || {} }),
onEnumValue: (type, value) =>
((result.types[type.name] as EnumTypeExtensions).values[value.name] = value.extensions || {}),
onScalar: type => (result.types[type.name] = { type: 'scalar', extensions: type.extensions || {} }),
onUnion: type => (result.types[type.name] = { type: 'union', extensions: type.extensions || {} }),
onInputType: type => (result.types[type.name] = { fields: {}, type: 'input', extensions: type.extensions || {} }),
onInputFieldType: (type, field) =>
((result.types[type.name] as InputTypeExtensions).fields[field.name] = { extensions: field.extensions || {} }),
});

return result;
}
1 change: 1 addition & 0 deletions packages/schema/src/index.ts
Expand Up @@ -6,3 +6,4 @@ export { extendResolversFromInterfaces } from './extendResolversFromInterfaces.j
export * from './makeExecutableSchema.js';
export * from './types.js';
export * from './merge-schemas.js';
export * from './extractExtensionsFromSchema.js';

0 comments on commit 7510162

Please sign in to comment.