Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gatsby): Allow proxying field values from nested fields #16149

Merged
merged 11 commits into from
Aug 12, 2019

Conversation

stefanprobst
Copy link
Contributor

Currently we can proxy field values from other fields with the @proxy(from: "somefield") extension. Additionally, the @link and @fileByRelativePath extensions also accept a from argument.

However, proxying is limited to the same nesting level, i.e. on Markdown.frontmatter.somefield it is only possible to proxy to other frontmatter fields, but not one level up/down.

This PR adds that. Example:

type MarkdownRemark implements Node {
  frontmatter: Frontmatter
  slug: String @proxy(from: "frontmatter.slug")
}
type Frontmatter {
  slug: String
  # fromNode resolves the 'from' path from the root of the node
  raw: String @proxy(from: "internal.content", fromNode: true)
}

We do this with a custom defaultFieldResolver on context - because we cannot modify info.fieldName like we do now in @proxy (we cannot put a dotted path there), and we can also not resolve the fieldValue in @proxy and modify the first resolver argument, because this interferes with node tracking. The advantage of context.defaultFieldResolver is that @link and other field extensions now also understand dotted from paths.

@stefanprobst stefanprobst requested review from a team as code owners July 27, 2019 09:44
@stefanprobst stefanprobst changed the title Allow proxying field values from nested fields Jul 27, 2019
@stefanprobst
Copy link
Contributor Author

stefanprobst commented Aug 5, 2019

Changed: pass options via info not args, merge with current master.


One thing to note (after seeing today's twitch stream): this does not call any field resolvers, which means that proxying to fields on nodes that are linked via foreign-key relation does not work out of the box.

Specifically, proxying to a field on a parent node will not work if the parent field has not been resolved to a full Node but just holds the string id.

If we want this, we could either add another extension option, or -- what i prefer -- compose @proxy with a directive that injects the parent node. This test shows an example how this can be done by combining a @parent and @proxy directive.

EDIT: Ok, thinking some more on this, maybe we actually should resolve from.

@freiksenet
Copy link
Contributor

@stefanprobst Yeah, let's resolve from. It makes sense in this case because parent use case is going to be so common.

@stefanprobst
Copy link
Contributor Author

Some more thoughts on this:

  • we cannot by default resolve from because this would be breaking current behavior. E.g. something I have done personally is
date: Date @dateformat(formatString: "MMM, DD YYYY")
isoDate: Date @proxy(from: "date")

to set a default format for the date field but still have the raw iso date available. If we call the date field resolver when proxying, this won't work anymore.

  • so we would have to either use another directive option, or do this somewhere else (I'm not yet 100% convinced that proxy itself is the best place to add that complexity)
  • one advantage of resolving from though would be that linking from a proxied/virtual field would work
  • wrt to proxying from the parent node being a common scenario: do you mean because of data abstractions going through a "proxy type"? one alternative approach that i'd like to explore here is not going through a "proxy type" but creating a new type implementing the interface, which uses functionality made available through context, i.e. gatsby-plugin-mdx puts genMdx on context, and when creating MdxBlogPost we use that directly instead of from a parent Mdx type
@freiksenet
Copy link
Contributor

wrt to proxying from the parent node being a common scenario: do you mean because of data abstractions going through a "proxy type"? one alternative approach that i'd like to explore here is not going through a "proxy type" but creating a new type implementing the interface, which uses functionality made available through context, i.e. gatsby-plugin-mdx puts genMdx on context, and when creating MdxBlogPost we use that directly instead of from a parent Mdx type

I think proxy child types work well because they allow one to keep all the existing ecosystem without the change. You can attach child to any source plugin generated type. While I really like context idea, it would require all the plugins to provide that functionality, which is a much higher migration cost.

we cannot by default resolve from because this would be breaking current behavior.

Right. We could add "noResolve" arg to proxy. I know it's hacky :/ Not sure what is a better way to do it.

@stefanprobst
Copy link
Contributor Author

Right. We could add "noResolve" arg to proxy. I know it's hacky :/ Not sure what is a better way to do it.

I think the alternative is extension composition. This does not necessarily have to look like the @parent extension i linked to above, that's just one approach. Mainly I worry about mixing two concerns into proxy. Currently all it does is point to a field value. I think resolving fields so they are available to point to (either because they are computed/virtual fields, they apply formatting, or link to other nodes etc.) should be done by a different extension.

@freiksenet freiksenet self-requested a review August 12, 2019 11:21
@freiksenet freiksenet merged commit d2128ab into gatsbyjs:master Aug 12, 2019
@stefanprobst stefanprobst deleted the proxy-extension branch August 12, 2019 12:29
@fshowalter
Copy link
Contributor

One thing to note (after seeing today's twitch stream): this does not call any field resolvers, which means that proxying to fields on nodes that are linked via foreign-key relation does not work out of the box.

Is this still true? I.E. I'd like to proxy to an @link'd foreign key relation to flatten my response, but it looks like Gatsby still doesn't resolve @link'd nodes when referenced via @proxy. Or am I missing something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants