Skip to content
This repository has been archived by the owner on Apr 15, 2020. It is now read-only.

Commit

Permalink
feat(graphql): interfaces implementing interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacovCR committed Feb 16, 2020
1 parent a165f40 commit b0241b7
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 10 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ install:
- npm install graphql@$GRAPHQL_CHANNEL

script:
- npm test
- if [ $GRAPHQL_CHANNEL == 'rc' ];
then npm test && npm run lint && npm run prettier-check;
else npm test;
fi
- npm run coverage
- coveralls < ./coverage/lcov.info || true # if coveralls doesn't have it covered

Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"compile": "tsc",
"pretest": "npm run clean && npm run compile",
"test": "npm run testonly",
"posttest": "npm run lint && npm run prettier:check",
"lint": "eslint --ext .js,.ts src",
"lint:watch": "esw --watch --cache --ext .js,.ts src",
"watch": "tsc -w",
Expand All @@ -20,9 +19,9 @@
"coverage": "istanbul cover _mocha -- --reporter dot --full-trace ./dist/test/**.js",
"postcoverage": "remap-istanbul --input coverage/coverage.json --type lcovonly --output coverage/lcov.info",
"prepublishOnly": "npm run compile",
"prerelease": "npm test",
"prettier": "prettier --trailing-comma all --single-quote --write src/**/*.ts",
"prettier:check": "prettier --trailing-comma all --single-quote --check src/**/*.ts",
"prerelease": "npm test && npm run lint && npm run prettier:check",
"release": "npm run releaseonly",
"releaseonly": "standard-version"
},
Expand Down Expand Up @@ -84,7 +83,7 @@
"eslint-watch": "^6.0.1",
"express": "^4.17.1",
"express-graphql": "^0.9.0",
"graphql": "^14.6.0",
"graphql": "^15.0.0-rc.2",
"graphql-subscriptions": "^1.1.0",
"graphql-type-json": "^0.3.1",
"graphql-upload": "^9.0.0",
Expand Down
12 changes: 10 additions & 2 deletions src/generate/extendResolversFromInterfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { GraphQLObjectType, GraphQLSchema } from 'graphql';
import {
GraphQLObjectType,
GraphQLSchema,
versionInfo,
GraphQLInterfaceType,
} from 'graphql';

import { IResolvers } from '../Interfaces';

Expand All @@ -15,7 +20,10 @@ function extendResolversFromInterfaces(
typeNames.forEach(typeName => {
const typeResolvers = resolvers[typeName];
const type = schema.getType(typeName);
if (type instanceof GraphQLObjectType) {
if (
type instanceof GraphQLObjectType ||
(versionInfo.major >= 15 && type instanceof GraphQLInterfaceType)
) {
const interfaceResolvers = type
.getInterfaces()
.map(iFace => resolvers[iFace.name]);
Expand Down
9 changes: 9 additions & 0 deletions src/stitching/mergeSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
GraphQLUnionType,
GraphQLEnumType,
ASTNode,
versionInfo,
} from 'graphql';

import {
Expand Down Expand Up @@ -361,6 +362,14 @@ function merge(
}),
{},
),
interfaces:
versionInfo.major >= 15
? candidates.reduce((acc, candidate) => {
const interfaces = (candidate.type as GraphQLInterfaceType).toConfig()
.interfaces;
return interfaces != null ? acc.concat(interfaces) : acc;
}, [])
: undefined,
});
} else if (initialCandidateType instanceof GraphQLUnionType) {
return new GraphQLUnionType({
Expand Down
12 changes: 12 additions & 0 deletions src/stitching/typeFromAST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
DirectiveLocation,
GraphQLFieldConfig,
StringValueNode,
versionInfo,
} from 'graphql';

import { createNamedStub } from '../utils/stub';
Expand Down Expand Up @@ -87,6 +88,17 @@ function makeInterfaceType(
return new GraphQLInterfaceType({
name: node.name.value,
fields: () => makeFields(node.fields),
interfaces:
versionInfo.major >= 15
? () =>
node.interfaces.map(
iface =>
createNamedStub(
iface.name.value,
'interface',
) as GraphQLInterfaceType,
)
: undefined,
description: getDescription(node, backcompatOptions),
resolveType: parent => resolveFromParentTypename(parent),
});
Expand Down
11 changes: 10 additions & 1 deletion src/test/testingSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
ExecutionResult,
Source,
GraphQLResolveInfo,
versionInfo,
} from 'graphql';
import { forAwaitEach } from 'iterall';

Expand Down Expand Up @@ -272,7 +273,15 @@ const propertyRootTypeDefs = `
foo: String
}
type TestImpl2 implements TestInterface {
${
versionInfo.major >= 15
? `interface TestNestedInterface implements TestInterface {
kind: TestInterfaceKind
testString: String
}
type TestImpl2 implements TestNestedInterface & TestInterface {`
: 'type TestImpl2 implements TestInterface'
}
kind: TestInterfaceKind
testString: String
bar: String
Expand Down
8 changes: 7 additions & 1 deletion src/utils/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
GraphQLScalarType,
GraphQLSchema,
GraphQLUnionType,
versionInfo,
} from 'graphql';

import { healTypes } from './heal';
Expand All @@ -25,7 +26,12 @@ export function cloneType(type: GraphQLNamedType): GraphQLNamedType {
interfaces: config.interfaces.slice(),
});
} else if (type instanceof GraphQLInterfaceType) {
return new GraphQLInterfaceType(type.toConfig());
const config = type.toConfig();
return new GraphQLInterfaceType({
...config,
interfaces:
versionInfo.major >= 15 ? config.interfaces.slice() : undefined,
});
} else if (type instanceof GraphQLUnionType) {
const config = type.toConfig();
return new GraphQLUnionType({
Expand Down
11 changes: 9 additions & 2 deletions src/utils/heal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
GraphQLSchema,
GraphQLInputType,
GraphQLOutputType,
versionInfo,
} from 'graphql';

import each from './each';
Expand Down Expand Up @@ -123,6 +124,9 @@ export function healTypes(
return;
} else if (type instanceof GraphQLInterfaceType) {
healFields(type);
if (versionInfo.major >= 15) {
healInterfaces(type);
}
return;
} else if (type instanceof GraphQLUnionType) {
healUnderlyingTypes(type);
Expand Down Expand Up @@ -151,7 +155,7 @@ export function healTypes(
});
}

function healInterfaces(type: GraphQLObjectType) {
function healInterfaces(type: GraphQLObjectType | GraphQLInterfaceType) {
updateEachKey(type.getInterfaces(), iface => {
const healedType = healType(iface) as GraphQLInterfaceType;
return healedType;
Expand Down Expand Up @@ -209,7 +213,10 @@ function pruneTypes(
) {
const implementedInterfaces = {};
each(typeMap, namedType => {
if (namedType instanceof GraphQLObjectType) {
if (
namedType instanceof GraphQLObjectType ||
(versionInfo.major >= 15 && namedType instanceof GraphQLInterfaceType)
) {
each(namedType.getInterfaces(), iface => {
implementedInterfaces[iface.name] = true;
});
Expand Down

0 comments on commit b0241b7

Please sign in to comment.