gramps-graphql / gramps--legacy

The core data source combination engine of GrAMPS.

Home Page:https://gramps.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add extraContext to each data source context

jlengstorf opened this issue · comments

Developers need to be able to add extra context to each data source via the extraContext prop:

const GraphQLOptions = gramps({
  dataSources: [/* ... */],
  extraContext: req => ({
    headers: req.headers,
  }),
});

However, when we scoped context to data source namespaces, we made it impossible to access that extra context:

const wrapFn = namespace => (fn, fieldName) => {
  checkFn(fn, fieldName);
  return (root, args, context, info) =>
    fn(root, args, context[namespace], info);
};

One solution could be to put the extra context in under a extraContext prop, then merge in wrapFn:

  const wrapFn = namespace => (fn, fieldName) => {
    checkFn(fn, fieldName);
    return (root, args, context, info) =>
-     fn(root, args, context[namespace], info);
+     fn(root, args, { ...context.extraContext, ...context[namespace] }, info);
  };

I'm not married to that solution, but it seems safe and fast. Anyone want to add the PR and tests for it?

Implemented in #56

I do, however, want to express my concerns about using extraContext. The only reason for extraContext is if data sources use what's made available in extraContext. This puts the onus on the gateway author to make sure that it's there.

I would argue that it makes more sense to say to a data source developer "If you need something to be in context then put it in context yourself so you know it's there for sure"

I see where you're coming from, and I think any public data source should follow that pattern. However, I think there's a use-case for extraContext on internal projects where things like session management are handled in a central place.

At IBM, for example, we have internal APIs that require special tokens and privileges to operate. These are used by multiple data sources. If we didn't pass them in as extra context, we'd need to install and manage those internal APIs as dependencies in each data source rather than managing them at the gateway level and passing them down to all data sources.

We could always attach it to req, but I like the idea of being more explicit about it.

Does that all make sense? I've been staring at this for a long time, so it's possible there's a simpler solution I'm not seeing.