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

[1.0] Questions about the Node API and ___NODE in particular #1220

Closed
0x80 opened this issue Jun 21, 2017 · 8 comments
Closed

[1.0] Questions about the Node API and ___NODE in particular #1220

0x80 opened this issue Jun 21, 2017 · 8 comments
Labels
type: question or discussion Issue discussing or asking a question about Gatsby

Comments

@0x80
Copy link
Contributor

0x80 commented Jun 21, 2017

I have my site content pulled in via JSON files. Some of those JSON fields contain Markdown. The following snippet creates a MarkdownField node when it finds a JSON object with a field that matches the given name. Because this MarkdownField gets the markdown mediaType, the remark plugin picks it up to generate a childMarkdownRemark on that node with the rendered HTML.

  matchedFields.map(field => {
    const markdownStr = node[field]

    invariant(
      typeof markdownStr === 'string',
      `JSON markdown field ${field} is not a string`
    )

    const fieldNodeId = makeNodeId(node.id, field)

    const fieldNode = {
      id: fieldNodeId,
      parent: node.id,
      children: [],
      text: markdownStr,
      internal: {
        type: `MarkdownField`,
        mediaType: `text/x-markdown`,
        content: markdownStr,
        contentDigest: digest(markdownStr),
      },
    }

    node[`${field}___NODE`] = fieldNodeId
    delete node[field]
    node.children = node.children.concat([fieldNodeId])
    createNode(fieldNode)
  })

It works but I'm not 100% sure this is the right approach. I took bits from looking at other plugins but I think the documentation is currently lacking some info so I'm left with some questions.

  • The use of ___NODE is not documented. node[${field}___NODE] = fieldNodeId seems to replace the field of an existing node with a reference to another node. I'm not sure if delete node[field] after that is required. Not all plugins seem to do this consistently. Is ___NODE something specific to Gatsby or is it internal to Relay or GraphQL?
  • I'm not sure why/if node.children = node.children.concat([fieldNodeId]) is required, when node[${field}___NODE] = fieldNodeId is already linking a field to the node in question.
  • I could have used createParentChildLink({ parent: node, child: fieldNode }) instead if a JSON node only ever contained one markdown field, but since there can be multiple I think this ___NODE api is the way to go, right, or could I also use the new plugin fields API for this?
  • Since [1.0] Make nodes fully immutable by adding API for allowing plugins to add fields #1035, Nodes are considered immutable, but what I am doing here very much feels like mutation. I would expect to have to call an action to replace the parent or something.
@0x80 0x80 added API/Plugins type: question or discussion Issue discussing or asking a question about Gatsby labels Jun 21, 2017
@jbolda jbolda added the v1 label Jun 21, 2017
@KyleAMathews
Copy link
Contributor

This is a really helpful list of questions :-) Lemme turn answers to this into a new docs page on advanced data modeling or whatever.

@0x80
Copy link
Contributor Author

0x80 commented Jun 30, 2017

@KyleAMathews Did anything substantial change in this API recently? With the current HEAD my plugin stopped working. It was fine about a week ago.

I'll investigate further, but maybe you know something obvious from the top of your head.

With stopped working I mean the markdown field is left as the original string and is not transformed to remark / markdown node anymore. The original node seems to be untouched.

@KyleAMathews
Copy link
Contributor

@0x80 hmmm I did break things temporarily yesterday afternoon but #1303 fixed it. So you're saying that MarkdownRemark nodes aren't being created anymore?

@KyleAMathews
Copy link
Contributor

There's also #1299

@0x80
Copy link
Contributor Author

0x80 commented Jun 30, 2017

I think it fails before MarkdownRemark. In my plugin code above the node[field] of the original JSON node is replaced with a reference to a newly created fieldNode which gets a markdown mediaType.

Gatsby now tells me that node[field] is still the original string it was in the JSON node.

Do you see anything funny or outdated about the code above maybe?

@0x80
Copy link
Contributor Author

0x80 commented Jun 30, 2017

Ah I see where things go wrong.

At the top of my plugin I have

if (node.internal.owner !== `gatsby-transformer-json`) return null
if (node.internal.mediaType !== `application/json`) return null

But the json files picked up by the filesystem source plugin are not set as application/json anymore. There's now a lot of nodes which don't have a mediaType, like you pointed out.

I think it makes sense to have the filesystem source plugin set media types always. What do you think?

@KyleAMathews
Copy link
Contributor

The filesystem source plugin does (should?) always set a media/type. A lot of other plugins don't now though.

@0x80
Copy link
Contributor Author

0x80 commented Jun 30, 2017

Ah yes sorry it is the gatsby-transformer-json plugin of course. I'll figure it out :) Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: question or discussion Issue discussing or asking a question about Gatsby
3 participants