Skip to content

Instantly share code, notes, and snippets.

@erebus1
Last active November 8, 2019 13:29
Show Gist options
  • Save erebus1/6bf67ad04d34d449de706b8fc74dd18b to your computer and use it in GitHub Desktop.
Save erebus1/6bf67ad04d34d449de706b8fc74dd18b to your computer and use it in GitHub Desktop.
GQL Schema Stitcher
const monolith_url: string = process.env.APOLLO_URL
const file_manager_url: string = process.env.FILE_MANAGER_URL
async function run() {
// logic on how extract files from file microservice
function getBatchFiles(context) {
return function batchFiles(keys: string[]): Promise<Array<{} | null>> {
return new Promise(function (resolve, reject) {
const query = `
query($ids: [Int!]!) {
files(ids: $ids){
id
name
url
previewUrl
}
}
`;
graphql(fileSchema, query, null, context, {ids: keys})
.then((result) => {
const fileMap = {};
_.get(result, 'data.files', []).forEach((file) => {
fileMap[file.id] = file
});
resolve(keys.map((id) => fileMap[id]))
}, (error) => {
console.error(error);
resolve(keys.map((id) => null))
});
})
}
}
const createRemoteSchema = async (uri: string) => {
const http = new HttpLink({ uri, fetch });
const link = setContext((request, previousContext) => ({
headers: (previousContext.graphqlContext || {}).headers
})).concat(http);
try {
return makeRemoteExecutableSchema({
schema: await introspectSchema(link),
link
});
}catch (e) {
console.error(e);
}
};
const monolithSchema = await createRemoteSchema(apollo_url);
const fileSchema = await createRemoteSchema(file_manager_url);
let schemas:any = [];
schemas.push(monolithSchema);
if (fileSchema) {
schemas.push(fileSchema)
}
const linkSchemaDefs = `
extend type MessageNode {
file: [FileNode]
}
`;
const resolvers = {};
// define how 2 schemas of monolith and filemanager will be combined
if (fileSchema && monolithSchema) {
schemas.push(linkSchemaDefs);
if (typeof(resolvers['MessageNode']) == "undefined") {
resolvers['MessageNode'] = {}
}
resolvers['MessageNode'].file = {
fragment: `fragment MessageNodeF on MessageNode {id, files{id}}`,
resolve(parent: any, args: any, context: any, info: any) {
return context.fileLoader.loadMany(
parent.files.map((val) => val.id)
);
}
}
}
let schema = mergeSchemas({
schemas: schemas,
resolvers: mergeInfo => (resolvers)
});
const app = express();
const server = new ApolloServer({
schema,
context: function({req, res}) {
let context = {
headers: req.headers,
};
let batchFiles = getBatchFiles(context);
context["fileLoader"] = new DataLoader(batchFiles);
return context
},
playground: true,
});
server.applyMiddleware({app});
app.listen(3000);
console.log('Server running. Open http://localhost:3000/graphql to run queries.');
}
run().catch(e => {
console.error(e, e.message, e.stack);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment