aeb-labs / graphql-weaver Goto Github PK
View Code? Open in Web Editor NEWA tool to combine, link and transform GraphQL schemas
License: MIT License
A tool to combine, link and transform GraphQL schemas
License: MIT License
The optimistic-response mechanism of apollo-client wants a __type for every queried type
This might be useful in general, e.g. for things like introspection queries
myNamespace: {
__type: 'Namespace',
myData: [...]
},
someOtherNamespace: {
__type: 'Namespace',
...
}
Typename 'Namespace' could also be 'WeaverNamespace', I'm not sure what would fit best.
Is there a particular reason why directives are duplicated. Given the Facebook Reference implementation, there is no way to specify a resolve function for a directive. Furthermore all attempts to do so, do so by wrapping all field resolvers with additional logic that checks the astNodes for attached directives.
Can we dedupe the directives?
Hello.
Did you try/had success to use weaver together with uploads?
I have such gateway (it fetches backends per request โ this is needed by design):
import {HttpLink} from 'apollo-link-http';
import fetch from 'node-fetch';
import express from 'express'
import * as bodyParser from 'body-parser-graphql'
import { apolloUploadExpress, GraphQLUpload } from 'apollo-upload-server'
import {graphiqlExpress, graphqlExpress} from 'apollo-server-express'
import {
introspectSchema,
makeRemoteExecutableSchema,
} from 'graphql-tools'
import {weaveSchemas} from "graphql-weaver";
import jwt from 'jsonwebtoken';
import createLocaleMiddleware from 'express-locale';
import fetchServices from "./utils/fetchServices";
require('dotenv').config();
const cors = require('cors');
const start = async function () {
const app = express();
const PORT = process.env.PORT || 3000;
app.use(cors());
app.post('/graphql', bodyParser.graphql());
app.post('/graphql', apolloUploadExpress());
app.use('/graphql', async function (req, res, next) {
// should to fetch this dynamically
const services = await fetchServices();
const serviceContainers = await Promise.all(services.map(async (service) => {
const dosvitMeta = req._dosvit;
const headers = {};
// ... some magic with headers
const link = new HttpLink({uri: service.url, fetch, headers});
const remoteSchema = makeRemoteExecutableSchema({
schema: await introspectSchema(link),
link
});
return {service, remoteSchema};
}));
const transformedSchema = await weaveSchemas({
endpoints: serviceContainers.map(s => {
return {
typePrefix: s.service.prefix,
namespace: s.service.namespace,
schema: s.remoteSchema
}
})
});
return graphqlExpress({schema: transformedSchema})(req, res, next);
});
app.use('/graphiql',
graphiqlExpress({
endpointURL: '/graphql',
}),
);
app.listen(PORT);
};
start();
When I try to upload a file server fails with error:
FileStreamDisconnectUploadError: Request disconnected during file upload stream parsing.
at IncomingMessage.request.on (.../local-gateway/node_modules/apollo-upload-server/lib/middleware.js:151:15)
at IncomingMessage.emit (events.js:182:13)
at resOnFinish (_http_server.js:564:7)
at ServerResponse.emit (events.js:182:13)
at onFinish (_http_outgoing.js:683:10)
at onCorkedFinish (_stream_writable.js:666:5)
at afterWrite (_stream_writable.js:480:3)
at process._tickCallback (internal/process/next_tick.js:63:19)
Emitted 'error' event at:
at IncomingMessage.request.on (.../local-gateway/node_modules/apollo-upload-server/lib/middleware.js:149:32)
at IncomingMessage.emit (events.js:182:13)
[... lines matching original stack trace ...]
at process._tickCallback (internal/process/next_tick.js:63:19)
Absolutely undebugable :(
First thought is that apollo-upload-server
needs an Upload
scalar type, and after weaveSchemas โ it is prefixed (to NewsUpload
for example).
To begin with: Is there a way to not prefix scalars or certain types?
Or in general did you use this with uploads?
My case is that I have some common types and interfaces between apis. But when trying to merge the schemas I get schema must contain unique named types but contains multiple types named "Node"
for example, which makes sense. I've been trying to replace the common types with a local value, so all 'node' usage in each api uses local 'node' type.
I've tried the transformSchema method, which works to a point but it looks like you need to replace the field types also with this new type, which would then involve descending through non null lists etc to find the type to replace also.
Am I missing something, is there a simpler way?
introspectionQuery
has been deleted and replaced with getIntrospectionQuery
so, please update to working for graphql 15.4.0
I run into some issue on production enviroment.
Is the parse function meant to filter null or undefined value ? If that's the case, when the value is number 0, the returned value will be false.
graphql-weaver/src/pipeline/custom-scalar-types-serialization.ts
Lines 28 to 31 in 0885029
I'm currently putting together an example but I'm unsure how graphql-weaver works.
const schema = await weaveSchemas({
endpoints: [
{
namespace: 'properties',
typePrefix: 'Property',
url: 'https://v7l45qkw3.lp.gql.zone/graphql',
fieldMetadata: {
'PropertyProperty.booking': {
link: {
field: 'bookings.bookingsByPropertyId', // field Song in namespace library
argument: 'propertyId', // argument of library.Song
batchMode: true,
keyField: 'propertyId'
}
},
'Query.properties.properties': {
join: {
linkField: 'bookings'
}
}
}
},
{
namespace: 'bookings',
typePrefix: 'Booking',
url: 'https://41p4j4309.lp.gql.zone/graphql'
},
{
namespace: 'weather',
typePrefix: 'Weather',
url: 'https://5rrx10z19.lp.gql.zone/graphql'
}
]
});
would love some help fleshing this out.
I really wanted to use this because the plumbing seems extensive enough and because you've solved several features like custom scalars; that being said, I have spent too many days both converting TypeScript to JavaScript in my head (not a super big deal, but causes some issues), reading through code that has far too few comments, and all this because the documentation is lacking.
Please provide better docs. For now we are using Apollo's schema stitching until this becomes a bit more fleshed out.
Wish list
Before weave schema:
_implementations:
{ _Document: [ Navigation, Page, Page_template, Test ],
_Linkable:
[ Navigation,
Page,
Page_template,
Test,
_ExternalLink,
_FileLink,
_ImageLink ],
Running:
weaveSchema = await weaveSchemas({
endpoints: [
{
namespace: 'cms',
typePrefix: 'CMS',
schema: anotherSchema,
},
{
schema: localSchema,
},
],
});
Result:
_implementations:
{ CMS_Document: [ CMSNavigation, CMSPage, CMSPage_template, CMSTest ],
CMS_Linkable: [ CMSNavigation, CMSPage, CMSPage_template, CMSTest ],
Below fields are missing:
_ExternalLink,
_FileLink,
_ImageLink
Expected:
_implementations:
{ CMS_Document: [ CMSNavigation, CMSPage, CMSPage_template, CMSTest ],
CMS_Linkable: [ CMSNavigation, CMSPage, CMSPage_template, CMSTest,
CMS_ExternalLink, CMS_FileLink, CMS_ImageLink ],
To be able to publish new versions ;o)
is there a way to merge all duplicate types into 1?
e.g. 2 query types into 1, and any other type?
Hi! I've tried weaving two schemas, one of which was queried before using graphql-js' rootValue argument. The resulting schema however does not seem to be getting the rootValue that is set.
Steps to reproduce:
Run one of the following examples:
const {
graphql,
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
} = require('graphql');
const { weaveSchemas } = require('graphql-weaver');
const beverageSchema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'beverage',
fields: {
beverage: {
resolve: (root, args, ctx, ast) => {
if (
(root && root.bar) ||
(ast && ast.rootValue && ast.rootValue.bar)
) {
return '๐บ';
}
return '๐ง';
},
type: GraphQLString
}
},
})
});
const foodSchema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'food',
fields: {
food: {
resolve: () => '๐',
type: GraphQLString
}
},
})
});
// http://graphql.org/graphql-js/graphql/#graphql
graphql(
beverageSchema,
'{ beverage }'
).then(result => {
console.assert(
result.data.beverage == '๐ง',
'beverage schema without root did not return ๐ง'
);
}).catch(e => {
console.log(e);
});
graphql(
beverageSchema,
'{ beverage }',
{ bar: true }
).then(result => {
console.assert(
result.data.beverage == '๐บ',
'beverage schema with root did not return ๐บ'
);
}).catch(e => {
console.log(e);
});
graphql(
foodSchema,
'{ food }'
).then(result => {
console.assert(
result.data.food == '๐',
'food schema did not return the ๐'
);
}).catch(e => {
console.log(e);
});
weaveSchemas({endpoints: [
{ schema: beverageSchema },
{ schema: foodSchema },
]}).then(theGrandSchema => {
graphql(
theGrandSchema,
'{ beverage }'
).then(result => {
console.assert(
result.data.beverage == '๐ง',
'the grand schema without root did not return ๐ง'
);
});
graphql(
theGrandSchema,
'{ beverage }',
{ bar: true }
).then(result => {
console.assert(
result.data.beverage == '๐บ',
'the grand schema with root did not return ๐บ'
);
}).catch(e => {
console.log(e);
});
graphql(
theGrandSchema,
'{ food }'
).then(result => {
console.assert(
result.data.food == '๐',
'the grand schema did not return the ๐'
);
}).catch(e => {
console.log(e);
});
});
Expected behaviour:
Queries on the beverage
root with a { bar: true }
set as root should return "๐บ "
.
Actual behaviour
Queries on the beverage
root with a { bar: true }
set return "๐ง "
.
I need to pass the token to the server in my situation.
In my local server I want to create a schema that is a merge of:
This runs into an error:
Failed: Schema must contain unique named types but contains multiple types named "_FieldJoin".
(on my local server the error was on _ExtendedIntrospection, but probably the same problem?)
Says SyntaxError: Unexpected token I in JSON at position 0 at https://launchpad.graphql.com/static/js/main.8ecc894c.js:1:741833
when using in Launchpad, and cannot be connected to by GraphiQL, returns the following error:
Invalid options provided to ApolloServer: Cannot use GraphQLSchema "[object Object]" from another module or realm.
Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.
https://yarnpkg.com/en/docs/selective-version-resolutions
Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results.
For some reason some virtual fields are returning null for me, while others are working. When I specify the linkFieldName, the endpoint for lc
doesn't even get hit to resolve the query. However, if I don't use a linkFieldName, it does hit the lc
endpoint, and returns the correct data.
This library is amazing, and I love it, so I'm hoping there is a way to get this to work.
I also have another unrelated question: Is it possible to create more than one link for a field, to support polymorphic relations?
const schema = await weaveSchemas({
endpoints: [{
namespace: 'cw',
typePrefix: 'Courseware',
url: 'http://localhost:2000',
fieldMetadata: {
'Assignment.id': {
link: {
field: 'rls.rls_resource', // field location in namespace go
argument: 'external_id', // argument of geo.location,
linkFieldName: 'resource',
}
},
}
}, {
namespace: 'lc',
typePrefix: 'LearningCurve',
url: 'http://localhost:2001'
}, {
namespace: 'rls',
typePrefix: 'RLS',
url: 'http://localhost:2003',
fieldMetadata: {
'rlsResource.id': {
link: {
field: 'lc.assignment',
argument: 'assignment_id',
linkFieldName: 'activity',
batchMode: false,
}
},
}
}]
});
query {
cw {
course(id:"15968801-643e-48df-83ca-da275bf4acdd") {
id
name
assignments {
id
name
resource {
id
external_id
activity {
activity_title
}
}
}
}
}
}
{
"data": {
"cw": {
"course": {
"id": "15968801-643e-48df-83ca-da275bf4acdd",
"name": "LC Test",
"assignments": [
{
"id": "2d5d1eda-9322-46fa-ad58-9b34558e18fe",
"name": " Appendix B: Work/Life Satisfaction; I-O Psychology; Motivating Achievement; Leadership",
"resource": {
"id": "4340af8d-77bf-40c4-b7a5-83113a576034",
"external_id": "2d5d1eda-9322-46fa-ad58-9b34558e18fe",
"activity": null
}
},
{
"id": "8af965b3-bfbc-4c69-9d93-3fd0b61ea0fe",
"name": " Appendix B: Career Fields in Psychology",
"resource": null
},
{
"id": "a783ff43-86c7-4a5e-b863-9c991244cd92",
"name": " Appendix A: Psychology at Work",
"resource": null
},
{
"id": "c1f6cdc1-1b71-4113-95ee-aa614a7d075c",
"name": " Appendix A: Psychology at Work",
"resource": null
},
{
"id": "5905dd3b-70b8-4b6b-b98f-236656c8f026",
"name": " 4a. An Introduction to Consciousness and Sleep",
"resource": {
"id": "c50f80d4-cfce-47c9-a328-a613e9036aad",
"external_id": "5905dd3b-70b8-4b6b-b98f-236656c8f026",
"activity": null
}
}
]
}
}
}
}
Notice how all of the activity fields are null
const schema = await weaveSchemas({
endpoints: [{
namespace: 'cw',
typePrefix: 'Courseware',
url: 'http://localhost:2000',
fieldMetadata: {
'Assignment.id': {
link: {
field: 'rls.rls_resource',
argument: 'external_id',
linkFieldName: 'resource',
}
},
}
}, {
namespace: 'lc',
typePrefix: 'LearningCurve',
url: 'http://localhost:2001'
}, {
namespace: 'rls',
typePrefix: 'RLS',
url: 'http://localhost:2003',
fieldMetadata: {
'rlsResource.id': {
link: {
field: 'lc.assignment',
argument: 'assignment_id',
batchMode: false,
// linkFieldName removed
}
},
}
}]
});
query {
cw {
course(id:"15968801-643e-48df-83ca-da275bf4acdd") {
id
name
assignments {
id
name
resource {
id {
activity_title
}
external_id
}
}
}
}
}
{
"data": {
"cw": {
"course": {
"id": "15968801-643e-48df-83ca-da275bf4acdd",
"name": "LC Test",
"assignments": [
{
"id": "2d5d1eda-9322-46fa-ad58-9b34558e18fe",
"name": " Appendix B: Work/Life Satisfaction; I-O Psychology; Motivating Achievement; Leadership",
"resource": {
"id": {
"activity_title": "Appendix B: Work/Life Satisfaction; I-O Psychology; Motivating Achievement; Leadership"
},
"external_id": "2d5d1eda-9322-46fa-ad58-9b34558e18fe"
}
},
{
"id": "8af965b3-bfbc-4c69-9d93-3fd0b61ea0fe",
"name": " Appendix B: Career Fields in Psychology",
"resource": null
},
{
"id": "a783ff43-86c7-4a5e-b863-9c991244cd92",
"name": " Appendix A: Psychology at Work",
"resource": null
},
{
"id": "c1f6cdc1-1b71-4113-95ee-aa614a7d075c",
"name": " Appendix A: Psychology at Work",
"resource": null
},
{
"id": "5905dd3b-70b8-4b6b-b98f-236656c8f026",
"name": " 4a. An Introduction to Consciousness and Sleep",
"resource": {
"id": {
"activity_title": "4a. An Introduction to Consciousness and Sleep"
},
"external_id": "5905dd3b-70b8-4b6b-b98f-236656c8f026"
}
}
]
}
}
}
}
Error: Unexpected reference to type Ride
at Transformer.findType (/Users/gengjiawen/Documents/schema-stitching-demo/node_modules/[email protected]@graphql-weaver/src/graphql/schema-transformer.ts:249:19)
at Transformer.mapType (/Users/gengjiawen/Documents/schema-stitching-demo/node_modules/[email protected]@graphql-weaver/src/graphql/schema-transformer.ts:269:24)
at /Users/gengjiawen/Documents/schema-stitching-demo/node_modules/[email protected]@graphql-weaver/src/graphql/schema-transformer.ts:487:59
at Array.map (<anonymous>)
at Transformer.transformUnionType (/Users/gengjiawen/Documents/schema-stitching-demo/node_modules/[email protected]@graphql-weaver/src/graphql/schema-transformer.ts:487:36)
at Transformer.copyType (/Users/gengjiawen/Documents/schema-stitching-demo/node_modules/[email protected]@graphql-weaver/src/graphql/schema-transformer.ts:315:25)
at Transformer.transformType (/Users/gengjiawen/Documents/schema-stitching-demo/node_modules/[email protected]@graphql-weaver/src/graphql/schema-transformer.ts:297:21)
at Transformer.processType (/Users/gengjiawen/Documents/schema-stitching-demo/node_modules/[email protected]@graphql-weaver/src/graphql/schema-transformer.ts:290:40)
at Transformer.transform (/Users/gengjiawen/Documents/schema-stitching-demo/node_modules/[email protected]@graphql-weaver/src/graphql/schema-transformer.ts:210:18)
at Object.transformSchema (/Users/gengjiawen/Documents/schema-stitching-demo/node_modules/[email protected]@graphql-weaver/src/graphql/schema-transformer.ts:185:24)
Let there be two schemas:
A
->A1: TypeA
->A2: TypeA
B
->B1: TypeB
When joining B1 on A1 AND A2, the filter type TypeAWithTypeBFilter will be generated two times and not re-used.
I'm planning to have a look at it next week.
I want to camelize field and argument names, I thought it was simple, just renaming the snake-style fields to camel-style. So I wrote a custom module as the following:
export class SnakeToCamelFieldModule implements PipelineModule {
private snakeToCamelFieldSchema = new SnakeToCamelFieldSchema();
transformSchema(schema: GraphQLSchema): GraphQLSchema {
return transformSchema(schema, this.snakeToCamelFieldSchema);
}
}
function isSpecificCase(s: string, converter: (value: string, locale?: string) => string ) {
return s === converter(s);
}
class SnakeToCamelFieldSchema implements SchemaTransformer {
private convertMap: { [key: string]: string; } = {};
transformField(field: GraphQLNamedFieldConfig<any, any>, context: any) {
// Rename a field in a type
if (isSpecificCase(field.name, snakeCase)) {
const camelName = camelCase(field.name);
this.convertMap[camelName] = field.name;
return {
...field,
name: camelName
};
}
return field;
}
renameField(name: string): string {
return this.convertMap[name] || name;
}
}
The schema was exactly what I want, but I also need to rename the query back. Then I updated FieldNode
's name
, but it failed and I got Failed to determine type of SelectionSet node
. It seems like some validations called before executing the query.
Then I thought maybe graphql aliases
could help, so I updated the code as the following:
export class SnakeToCamelFieldModule implements PipelineModule {
private snakeToCamelFieldSchema = new SnakeToCamelFieldSchema();
transformSchema(schema: GraphQLSchema): GraphQLSchema {
return transformSchema(schema, this.snakeToCamelFieldSchema);
}
transformQuery(query: Query): Query {
const definitions: Array<OperationDefinitionNode> = query.document.definitions.filter(
(e: DefinitionNode): e is OperationDefinitionNode => e.kind === "OperationDefinition");
const fieldNodes = flatten(definitions.map(def => collectFieldNodes(def)));
fieldNodes.map((field: any) => {
const originalName = this.snakeToCamelFieldSchema.renameField(field.name.value);
if (originalName !== field.name.value) {
field.alias = {
kind: "Name",
value: field.name.value
};
field.name.value = originalName;
}
});
return query;
}
}
It only partly succeeded, no errors occured this time, some queries like { getUsername }
succeeded, it returned { "data": { "getUsername": "haofuxin" } }
. But some queries like
{
relay {
routes {
edges {
node {
isActive
id
}
}
}
}
returned
{
"data": {
"relay": {
"routes": {
"edges": [
{
"node": {
"id": "Um91dGUtYXNjZW5kXzE2NA=="
}
}
]
}
}
}
}
isActive
was missing. After diving in for a while, I found that isActive
was filtered out in https://github.com/graphql/graphql-js/blob/ed74228dc8540e3d2681cb6da473e7ce5edb7850/src/execution/execute.js#L649-L655 . fieldName
is is_active
rather than isActive
.
Can you please refresh the graphql endpoint examples and namespacing examples on launchpad?
Hi! Thank you so very kindly for the work! This is a tremendous piece of work!
However, I'd one question regarding "production-ready" status of the project.
Does graphql-weaver support Relay?
I just spent a little time updating the type descriptions on one of by back-end graphql services and I noticed that these descriptions don't appear to be displayed in the weaved schema on my gateway server.
I'm looking to provide a self serve graphql API to my consumers so these type descriptions would be pretty valuable.
I'm going to see if I can get some time to work on this myself if you're open to pull requests.
Root types (query, mutation, etc) should be merged, yes?
But I am trying to do the following: combining apollo server with schema stiching and weaver like this (a demo):
const link = new HttpLink({uri: 'https://graphql-demo.azurewebsites.net/graphql', fetch});
const remoteSchema = await introspectSchema(link);
const executableSchema = makeRemoteExecutableSchema({
schema: remoteSchema,
link,
});
const transformedSchema = await weaveSchemas({
endpoints: [{
// typePrefix: 'Demo__',
namespace: 'demo',
schema: executableSchema
}]
});
And I get:
(node:5997) UnhandledPromiseRejectionWarning: Error: Schema must contain unique named types but contains multiple types named "Query".
Even without apollo's tooling, like this:
const transformedSchema = await weaveSchemas({
endpoints: [{
namespace: 'demo',
url: 'https://graphql-demo.azurewebsites.net/graphql'
}]
});
I get the same.
If I add typePrefix, schema becomes strange:
Query โ demo โ Demo__Query โ ... stuff
While queries perform correctly, I don't understand, why this conflict in root types appears (especially if to consider that I try it with one endpoint)
I'm not able to call link
without getting the error "Cannot read property 'map' of undefined" in graphql-tools AddArgumentsAsVariables (in addVariablesToRootFields
, which calls operation.variableDefinitions.map()
).
The issue seems to originate from here -- https://github.com/AEB-labs/graphql-weaver/blob/master/src/pipeline/links.ts#L301 -- if I change undefined
to []
that solves the error.
I've tried it with graphql-tools 4.0.0 (from your lock file) and 4.0.4 (the latest in 4.0) and get the same error in both. Quite honestly I don't know nearly enough about GraphQL query evaluation to understand what's causing this.
const schema = await weaveSchemas({
endpoints: [
{
namespace: 'account',
typePrefix: 'Account',
schema: auth0,
},
/* Wordpress post schemas */
{
namespace: 'blog',
typePrefix: 'Blog',
schema: createWordpressSchema('https://wp-int.codeday.org/graphql'),
fieldMetadata: {
'User.slug': {
link: {
field: 'account.user',
argument: 'where.username',
batchMode: false,
linkFieldName: 'account',
},
},
},
},
]
});
(auth0
is using makeExecutableSchema({ typeDefs, resolvers });
-- is there something special I'd need to do since it's not a remote schema?)
const schema: GraphQLSchema = await weaveSchemas({
endpoints: [{
namespace: 'library',
typePrefix: "Library",
url: 'http://example.com/library/graphql'
}, {
namespace: 'recommendations',
typePrefix: "Recommendations",
url: 'http://example.com/recommendations/graphql',
fieldMetadata: {
'Recommendation.song': { // Field song in type Recommendation
link: {
field: 'library.Song', // field Song in namespace library
argument: 'id', // argument of library.Song
batchMode: false,
}
}
}
}]
});
When I tried to use this schema, I got an error that includes Unexpected reference to type LibrarySong
.
Traceback:
Error: Unexpected reference to type LibrarySong
at Transformer.findType (/Users/haofuxin/shundaojia/graphql-gateway2/node_modules/graphql-transformer/src/schema-transformer.ts:247:19)
at TypeResolversTransformer.<anonymous> (/Users/haofuxin/shundaojia/graphql-gateway2/node_modules/graphql-weaver/src/pipeline/abstract-types.ts:115:34)
at step (/Users/haofuxin/shundaojia/graphql-gateway2/node_modules/graphql-weaver/dist/src/pipeline/abstract-types.js:40:23)
at Object.next (/Users/haofuxin/shundaojia/graphql-gateway2/node_modules/graphql-weaver/dist/src/pipeline/abstract-types.js:21:53)
at /Users/haofuxin/shundaojia/graphql-gateway2/node_modules/graphql-weaver/dist/src/pipeline/abstract-types.js:15:71
at new Promise (<anonymous>)
at /Users/haofuxin/shundaojia/graphql-gateway2/node_modules/graphql-weaver/dist/src/pipeline/abstract-types.js:11:12
at /Users/haofuxin/shundaojia/graphql-gateway2/node_modules/graphql-weaver/src/pipeline/abstract-types.ts:108:25
at /Users/haofuxin/shundaojia/graphql-gateway2/node_modules/graphql-transformer/src/schema-transformer.ts:524:28
at /Users/haofuxin/shundaojia/graphql-gateway2/node_modules/graphql-transformer/src/schema-transformer.ts:524:28
I am trying to build an API Gateway with GraphQL for my microservices architecture. Here's how I am trying to implement this:
Following are the expected API Gateway features:
Following are the things is not expected from the API Gateway:
This framework is all cool, but I don't find any examples or methods through which I can achieve this. Maybe someone can guide me through.
Perhaps @Yogu you can help me.
Thanks
Are you guys in touch with the Apollo community on their schema stiching initiative? Both projects seem to have much to benefit from each other.
I think it would be super useful if one could include headers when defining the endpoints.
Something like:
endpoints: [{
namespace: 'model',
typePrefix: 'Model',
url: 'http://localhost:8080/graphql' // url to a GraphQL endpoint,
headers: {
'Authorization': 'Bearer **********************',
'content-type': 'application/json'
}
}
#6 explains how to implement this by extending the HttpGraphQLClient
, but I think it'll be a great addition to the core lib.
When building a schema from SDL or any other source, the astNodes are present. The schema that is returned does not seem to have this field specified. Is there any way to preserve this info if it is present already?
Should this package work fine with GraphQL 15? I'm encountering some issues since upgrading but haven't managed to figure out precisely what the issues are yet.
Are there fundamental changes in GraphQL 15 that make weaver unworkable? We've been using weaver for a couple of years and have recently investigated moving to graphql-tool's WrapType but that only seems to support queries and not mutations.
Thanks in advance.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.