Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add compiled Subschema class for use with delegation outside of stitching context to ensure that transformSchema methods are called for all transforms closes #1565 * reorganize subschema functions into subschema file
- Loading branch information
Showing
9 changed files
with
188 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { GraphQLSchema } from 'graphql'; | ||
|
||
import { Transform, applySchemaTransforms } from '@graphql-tools/utils'; | ||
|
||
import { SubschemaConfig, MergedTypeConfig, CreateProxyingResolverFn, Subscriber, Executor } from './types'; | ||
|
||
import { FIELD_SUBSCHEMA_MAP_SYMBOL, OBJECT_SUBSCHEMA_SYMBOL } from './symbols'; | ||
|
||
export function getSubschema(result: any, responseKey: string): GraphQLSchema | SubschemaConfig { | ||
const subschema = result[FIELD_SUBSCHEMA_MAP_SYMBOL] && result[FIELD_SUBSCHEMA_MAP_SYMBOL][responseKey]; | ||
return subschema || result[OBJECT_SUBSCHEMA_SYMBOL]; | ||
} | ||
|
||
export function setObjectSubschema(result: any, subschema: GraphQLSchema | SubschemaConfig) { | ||
result[OBJECT_SUBSCHEMA_SYMBOL] = subschema; | ||
} | ||
|
||
export function isSubschemaConfig(value: any): value is SubschemaConfig { | ||
return Boolean((value as SubschemaConfig).schema); | ||
} | ||
|
||
export function isSubschema(value: any): value is Subschema { | ||
return Boolean((value as Subschema).transformedSchema); | ||
} | ||
|
||
export class Subschema { | ||
public schema: GraphQLSchema; | ||
public rootValue?: Record<string, any>; | ||
public executor?: Executor; | ||
public subscriber?: Subscriber; | ||
public createProxyingResolver?: CreateProxyingResolverFn; | ||
public transforms: Array<Transform>; | ||
public transformedSchema: GraphQLSchema; | ||
public merge?: Record<string, MergedTypeConfig>; | ||
|
||
constructor(config: SubschemaConfig) { | ||
this.schema = config.schema; | ||
this.executor = config.executor; | ||
this.subscriber = config.subscriber; | ||
this.createProxyingResolver = config.createProxyingResolver; | ||
this.transforms = config.transforms ?? []; | ||
this.merge = config.merge; | ||
|
||
this.transformedSchema = applySchemaTransforms(this.schema, this.transforms); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import { Subschema, delegateToSchema } from '@graphql-tools/delegate'; | ||
import { makeExecutableSchema } from '@graphql-tools/schema'; | ||
import { RenameRootFields, RenameObjectFields } from '@graphql-tools/wrap'; | ||
import { graphql, GraphQLSchema } from 'graphql'; | ||
|
||
describe('can delegate to subschema with transforms', () => { | ||
let sourceSchema: GraphQLSchema; | ||
|
||
beforeAll(() => { | ||
const ITEM = { | ||
id: '123', | ||
// eslint-disable-next-line camelcase | ||
camel_case: "I'm a camel!", | ||
}; | ||
|
||
const targetSchema = makeExecutableSchema({ | ||
typeDefs: ` | ||
type Item { | ||
id: ID! | ||
camel_case: String | ||
} | ||
type ItemConnection { | ||
edges: [ItemEdge!]! | ||
} | ||
type ItemEdge { | ||
node: Item! | ||
} | ||
type Query { | ||
item: Item | ||
allItems: ItemConnection! | ||
} | ||
`, | ||
resolvers: { | ||
Query: { | ||
item: () => ITEM, | ||
allItems: () => ({ | ||
edges: [ | ||
{ | ||
node: ITEM, | ||
}, | ||
], | ||
}), | ||
}, | ||
}, | ||
}); | ||
|
||
const subschema = new Subschema({ | ||
schema: targetSchema, | ||
transforms: [ | ||
new RenameRootFields((_operation, fieldName) => { | ||
if (fieldName === 'allItems') { | ||
return 'items'; | ||
} | ||
return fieldName; | ||
}), | ||
new RenameObjectFields((_typeName, fieldName) => { | ||
if (fieldName === 'camel_case') { | ||
return 'camelCase'; | ||
} | ||
return fieldName; | ||
}), | ||
] | ||
}); | ||
|
||
sourceSchema = makeExecutableSchema({ | ||
typeDefs: ` | ||
type Item { | ||
id: ID! | ||
camelCase: String | ||
} | ||
type ItemConnection { | ||
edges: [ItemEdge!]! | ||
} | ||
type ItemEdge { | ||
node: Item! | ||
} | ||
type Query { | ||
item: Item | ||
items: ItemConnection! | ||
} | ||
`, | ||
resolvers: { | ||
Query: { | ||
item: (_root, _args, _context, info) => delegateToSchema({ | ||
schema: subschema, | ||
info, | ||
}), | ||
items: (_root, _args, _context, info) => delegateToSchema({ | ||
schema: subschema, | ||
info, | ||
}), | ||
} | ||
} | ||
}) | ||
}); | ||
|
||
test('renaming should work', async () => { | ||
const result = await graphql( | ||
sourceSchema, | ||
` | ||
query { | ||
item { | ||
camelCase | ||
} | ||
items { | ||
edges { | ||
node { | ||
camelCase | ||
} | ||
} | ||
} | ||
} | ||
`, | ||
); | ||
|
||
const TRANSFORMED_ITEM = { | ||
camelCase: "I'm a camel!", | ||
}; | ||
|
||
expect(result).toEqual({ | ||
data: { | ||
item: TRANSFORMED_ITEM, | ||
items: { | ||
edges: [ | ||
{ | ||
node: TRANSFORMED_ITEM, | ||
}, | ||
], | ||
}, | ||
}, | ||
}); | ||
}); | ||
}); |