Skip to content

Commit

Permalink
fix(gatsby): content sync connection and static query page tracking (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
TylerBarnes committed Jul 20, 2022
1 parent 3952ac9 commit 028b1de
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,38 @@ describe(`Node Manifest API in "gatsby ${gatsbyCommandName}"`, () => {

expect(recentlyUpdatedNodeManifest.node.id).toBe(recentlyUpdatedNodeId)
})

it(`Creates a correct node manifest for nodes in connection list queries`, async () => {
const manifestFileContents1 = await getManifestContents(
`connection-list-query-node`
)

expect(manifestFileContents1.node.id).toBe(`connection-list-query-node`)
expect(manifestFileContents1.page.path).toBe(`/connection-list-query-page/`)

const manifestFileContents2 = await getManifestContents(
`connection-list-query-node-2`
)

expect(manifestFileContents2.node.id).toBe(`connection-list-query-node-2`)
expect(manifestFileContents2.page.path).toBe(`/connection-list-query-page/`)
})

it(`Creates a correct node manifest for nodes in connection list queries using staticQuery()`, async () => {
const manifestFileContents1 = await getManifestContents(
`static-query-list-query-node`
)

expect(manifestFileContents1.node.id).toBe(`static-query-list-query-node`)
expect(manifestFileContents1.page.path).toBe(`/static-query-list-query/`)

const manifestFileContents2 = await getManifestContents(
`static-query-list-query-node-2`
)

expect(manifestFileContents2.node.id).toBe(`static-query-list-query-node-2`)
expect(manifestFileContents2.page.path).toBe(`/static-query-list-query/`)
})
})

describe(`Node Manifest API in "gatsby ${gatsbyCommandName}"`, () => {
Expand Down
60 changes: 59 additions & 1 deletion integration-tests/node-manifest/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ exports.sourceNodes = ({ actions }) => {
const updatedAtUTC = new Date(
randomIntFromInterval(
LOWER_CREATED_AT_TIME_LIMIT,
UPPER_CREATED_AT_TIME_LIMIT,
UPPER_CREATED_AT_TIME_LIMIT
)
).toUTCString()

Expand Down Expand Up @@ -113,6 +113,64 @@ exports.sourceNodes = ({ actions }) => {
node: nodeUpdated2,
updatedAtUTC: nodeUpdated2.updatedAt,
})

const nodeForConnectionListQuery1 = {
id: `connection-list-query-node`,
title: `First connection list query node`,
internal: {
type: `TestConnectionListQueryType`,
contentDigest: `1`,
},
}
const nodeForConnectionListQuery2 = {
id: `connection-list-query-node-2`,
title: `Second connection list query node`,
internal: {
type: `TestConnectionListQueryType`,
contentDigest: `2`,
},
}

actions.createNode(nodeForConnectionListQuery1)
actions.unstable_createNodeManifest({
manifestId: createManifestId(nodeForConnectionListQuery1.id),
node: nodeForConnectionListQuery1,
})

actions.createNode(nodeForConnectionListQuery2)
actions.unstable_createNodeManifest({
manifestId: createManifestId(nodeForConnectionListQuery2.id),
node: nodeForConnectionListQuery2,
})

const nodeForStaticQueryList1 = {
id: `static-query-list-query-node`,
title: `First static query list query node`,
internal: {
type: `TestConnectionStaticQueryListQueryType`,
contentDigest: `1`,
},
}
const nodeForStaticQueryList2 = {
id: `static-query-list-query-node-2`,
title: `Second static query list query node`,
internal: {
type: `TestConnectionStaticQueryListQueryType`,
contentDigest: `2`,
},
}

actions.createNode(nodeForStaticQueryList1)
actions.unstable_createNodeManifest({
manifestId: createManifestId(nodeForStaticQueryList1.id),
node: nodeForStaticQueryList1,
})

actions.createNode(nodeForStaticQueryList2)
actions.unstable_createNodeManifest({
manifestId: createManifestId(nodeForStaticQueryList2.id),
node: nodeForStaticQueryList2,
})
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react"
import { graphql } from "gatsby"

export default function ConnectionListQueryPage({ data }) {
return (
<div>
<h1>ConnectionListQueryPage</h1>
{data.allTestConnectionListQueryType.nodes.map(({ title }) => (
<h2>{title}</h2>
))}
</div>
)
}

export const query = graphql`
query ConnectionListQueryPage {
allTestConnectionListQueryType {
nodes {
title
}
}
}
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react"
import { graphql } from "gatsby"
import { useStaticQuery } from "gatsby"

export default function TestConnectionStaticQueryListQueryType() {
const data = useStaticQuery(graphql`
query TestConnectionStaticQueryListQueryType {
allTestConnectionStaticQueryListQueryType {
nodes {
title
}
}
}
`)

return (
<div>
<h1>TestConnectionStaticQueryListQueryType</h1>
{data.allTestConnectionStaticQueryListQueryType.nodes.map(({ title }) => (
<h2>{title}</h2>
))}
</div>
)
}
2 changes: 1 addition & 1 deletion packages/gatsby/src/query/query-watcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ export const updateStateAndRunQueries = async (

if (process.env.NODE_ENV === `development`) {
/**
* only process node manifests here in develop. we want this to run every time queries are updated. for gatsby build we process node manifests in src/services/run-page-queries.ts after all queries are run and pages are created. If we process node manifests in this location for gatsby build we wont have all the information needed to create the manifests. If we don't process manifests in this location during gatsby develop manifests will only be written once and never again when more manifests are created.
* only process node manifests here in develop. we want this to run every time queries are updated. for gatsby build we process node manifests in src/utils/page-data.ts after all queries are run and pages are created. If we process node manifests in this location for gatsby build we wont have all the information needed to create the manifests. If we don't process manifests in this location during gatsby develop manifests will only be written once and never again when more manifests are created.
*/
await processNodeManifests()
}
Expand Down
46 changes: 39 additions & 7 deletions packages/gatsby/src/utils/node-manifest.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ErrorId } from "gatsby-cli/lib/structured-errors/error-map"
import { getNode } from "./../datastore"
import { IGatsbyPage, INodeManifest } from "./../redux/types"
import { IGatsbyNode, IGatsbyPage, INodeManifest } from "./../redux/types"
import reporter from "gatsby-cli/lib/reporter"
import { store } from "../redux/"
import { internalActions } from "../redux/actions"
Expand Down Expand Up @@ -60,21 +60,52 @@ const NODE_MANIFEST_FILE_LIMIT = getNodeManifestFileLimit()
*/
async function findPageOwnedByNode({
nodeId,
fullNode,
slug,
}: {
nodeId: string
fullNode: IGatsbyNode
slug?: string
}): Promise<{
page: INodeManifestPage
foundPageBy: FoundPageBy
}> {
const state = store.getState()
const { pages, nodes } = state
const { byNode } = state.queries

// the default page path is the first page found in
// node id to page query tracking
let pagePath = byNode?.get(nodeId)?.values()?.next()?.value
const { pages, nodes, staticQueryComponents } = state
const { byNode, byConnection, trackedComponents } = state.queries

const nodeType = fullNode?.internal?.type

const firstPagePathWithNodeAsDataDependency =
// the first page found in node id to page query path tracking
byNode?.get(nodeId)?.values()?.next()?.value

const firstPagePathWithNodeInGraphQLListField =
// the first page that queries for a list of this node type.
// we don't currently store a list of node ids for connection fields to queries
// we just store the query id or page path mapped to the connected GraphQL typename.
byConnection?.get(nodeType)?.values()?.next()?.value

let pagePath =
firstPagePathWithNodeAsDataDependency ||
firstPagePathWithNodeInGraphQLListField

// for static queries, we can only find the first page using that static query
// the reason we would find `sq--` here is because byConnection (above) can return a page path or a static query ID (which starts with `sq--`)
if (pagePath?.startsWith(`sq--`)) {
const staticQueryComponentPath =
staticQueryComponents?.get(pagePath)?.componentPath

const firstPagePathUsingStaticQueryComponent: string | null =
staticQueryComponentPath
? trackedComponents
?.get(staticQueryComponentPath)
?.pages?.values()
?.next()?.value
: null

pagePath = firstPagePathUsingStaticQueryComponent
}

let foundPageBy: FoundPageBy = pagePath ? `queryTracking` : `none`

Expand Down Expand Up @@ -250,6 +281,7 @@ export async function processNodeManifest(
// map the node to a page that was created
const { page: nodeManifestPage, foundPageBy } = await findPageOwnedByNode({
nodeId,
fullNode,
// querying by node.slug in GraphQL queries is common enough that we can search for it as a fallback after ownerNodeId, filesystem routes, and context.id
slug: fullNode?.slug as string,
})
Expand Down

0 comments on commit 028b1de

Please sign in to comment.