Skip to content
This repository has been archived by the owner on Oct 25, 2021. It is now read-only.

Commit

Permalink
encapsulate the document data loader better
Browse files Browse the repository at this point in the history
  • Loading branch information
wheresrhys committed Dec 4, 2020
1 parent 4f9516e commit 20be954
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 52 deletions.
25 changes: 2 additions & 23 deletions packages/tc-api-graphql/lib/get-apollo-middleware.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const { ApolloServer } = require('apollo-server-express');
const DataLoader = require('dataloader');
const {
logger,
getContextByRequestId,
Expand All @@ -8,20 +7,10 @@ const { driver } = require('@financial-times/tc-api-db-manager');
const { getAugmentedSchema } = require('./get-augmented-schema');
const { Tracer } = require('./request-tracer');

const getApolloMiddleware = ({
documentStore,
typeDefs,
resolvers,
excludeTypes,
}) => {
const getApolloMiddleware = options => {
const apollo = new ApolloServer({
subscriptions: false,
schema: getAugmentedSchema({
documentStore,
typeDefs,
resolvers,
excludeTypes,
}),
schema: getAugmentedSchema(options),
context: ({
req: { headers },
res: {
Expand All @@ -33,16 +22,6 @@ const getApolloMiddleware = ({
headers,
trace: new Tracer(getContextByRequestId(requestId)),
};

if (documentStore) {
context.documentStoreDataLoader = new DataLoader(async keys => {
const responses = await Promise.all(
keys.map(key => documentStore.get(...key.split('/'))),
);
return responses.map(({ body }) => body);
});
}

return context;
},
introspection: true,
Expand Down
71 changes: 42 additions & 29 deletions packages/tc-api-graphql/lib/get-augmented-schema.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,59 @@
const logger = require('@financial-times/n-logger').default;
const DataLoader = require('dataloader');
const { makeAugmentedSchema } = require('neo4j-graphql-js');
const { applyMiddleware } = require('graphql-middleware');
const { parse } = require('graphql');
const { getGraphqlDefs, getTypes } = require('@financial-times/tc-schema-sdk');
const merge = require('lodash.merge');
const { middleware: requestTracer } = require('./request-tracer');

const resolveDocumentProperty = async ({ code }, args, context, info) => {
if (!code) {
throw new Error(
'Must include code in body of query that requests any Document properties',
);
}
const key = `${info.parentType.name}/${code}`;
const record = await context.documentStoreDataLoader.load(key);
return record[info.fieldName];
};

const getDocumentResolvers = () => {
const typeResolvers = {};
const types = getTypes();
types.forEach(type => {
const nodeProperties = type.properties;
const documentResolvers = {};
Object.keys(nodeProperties).forEach(prop => {
if (nodeProperties[prop].type === 'Document') {
documentResolvers[prop] = resolveDocumentProperty;
}
});
if (Object.keys(documentResolvers).length) {
typeResolvers[type.name] = documentResolvers;
}
});
return typeResolvers;
};

const getAugmentedSchema = ({
documentStore,
typeDefs: extendedTypeDefs,
resolvers: extendedResolvers,
excludeTypes,
}) => {
const getDocumentDataLoader = () =>
new DataLoader(async keys => {
const responses = await Promise.all(
keys.map(key => documentStore.get(...key.split('/'))),
);
return responses.map(({ body }) => body);
});

const resolveDocumentProperty = async ({ code }, args, context, info) => {
if (!code) {
throw new Error(
'Must include code in body of query that requests any Document properties',
);
}
const key = `${info.parentType.name}/${code}`;

context.documentStoreDataLoader =
context.documentStoreDataLoader || getDocumentDataLoader();

const record = await context.documentStoreDataLoader.load(key);
return record[info.fieldName];
};

const getDocumentResolvers = () => {
const typeResolvers = {};
const types = getTypes();
types.forEach(type => {
const nodeProperties = type.properties;
const documentResolvers = {};
Object.keys(nodeProperties).forEach(prop => {
if (nodeProperties[prop].type === 'Document') {
documentResolvers[prop] = resolveDocumentProperty;
}
});
if (Object.keys(documentResolvers).length) {
typeResolvers[type.name] = documentResolvers;
}
});
return typeResolvers;
};

const resolvers = documentStore ? getDocumentResolvers() : {};
const typeDefs = getGraphqlDefs();

Expand Down

0 comments on commit 20be954

Please sign in to comment.