Skip to content

Commit

Permalink
refactor(contentful): get latest content types on every schema custom…
Browse files Browse the repository at this point in the history
…ization and node sourcing
  • Loading branch information
axe312ger committed Sep 17, 2021
1 parent 8078617 commit a607dd1
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 50 deletions.
15 changes: 4 additions & 11 deletions packages/gatsby-source-contentful/src/__tests__/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ const restrictedContentTypeFixture = require(`../__fixtures__/restricted-content

const defaultPluginOptions = { spaceId: `testSpaceId` }

fetchContentTypes.mockImplementation(() =>
startersBlogFixture.contentTypeItems()
)

const createMockCache = () => {
const actualCacheMap = new Map()
return {
Expand Down Expand Up @@ -66,7 +62,7 @@ describe(`gatsby-node`, () => {
await gatsbyNode.onPreBootstrap({ store })

await gatsbyNode.createSchemaCustomization(
{ schema, actions, cache, reporter },
{ schema, actions, reporter },
pluginOptions
)

Expand Down Expand Up @@ -293,6 +289,7 @@ describe(`gatsby-node`, () => {
beforeEach(() => {
fetchContent.mockClear()
fetchContentTypes.mockClear()
fetchContentTypes.mockImplementation(startersBlogFixture.contentTypeItems)
currentNodeMap = new Map()
actions.createNode = jest.fn(async node => {
node.internal.owner = `gatsby-source-contentful`
Expand Down Expand Up @@ -340,9 +337,6 @@ describe(`gatsby-node`, () => {
Array [
"contentful-sync-token-testSpaceId-master",
],
Array [
"contentful-content-types-testSpaceId-master",
],
Array [
"contentful-sync-data-testSpaceId-master",
],
Expand Down Expand Up @@ -370,7 +364,6 @@ describe(`gatsby-node`, () => {

expect(cache.set.mock.calls.map(v => v[0])).toMatchInlineSnapshot(`
Array [
"contentful-content-types-testSpaceId-master",
"contentful-sync-data-testSpaceId-master",
"contentful-sync-token-testSpaceId-master",
]
Expand Down Expand Up @@ -581,7 +574,7 @@ describe(`gatsby-node`, () => {

it(`stores rich text as raw with references attached`, async () => {
fetchContent.mockImplementationOnce(richTextFixture.initialSync)
fetchContentTypes.mockImplementationOnce(richTextFixture.contentTypeItems)
fetchContentTypes.mockImplementation(richTextFixture.contentTypeItems)

// initial sync
await simulateGatsbyBuild()
Expand Down Expand Up @@ -624,7 +617,7 @@ describe(`gatsby-node`, () => {
fetchContent.mockImplementationOnce(
restrictedContentTypeFixture.initialSync
)
fetchContentTypes.mockImplementationOnce(
fetchContentTypes.mockImplementation(
restrictedContentTypeFixture.contentTypeItems
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// @ts-check
const _ = require(`lodash`)

const { normalizeContentTypeItems } = require(`./normalize`)
const { createPluginConfig } = require(`./plugin-options`)
const { fetchContentTypes } = require(`./fetch`)
const { CODES } = require(`./report`)

export async function createSchemaCustomization(
{ schema, actions, reporter, cache },
{ schema, actions, reporter },
pluginOptions
) {
const { createTypes } = actions
Expand All @@ -16,42 +16,13 @@ export async function createSchemaCustomization(
// Get content type items from Contentful
const contentTypeItems = await fetchContentTypes({ pluginConfig, reporter })

// Check for restricted content type names and set id based on useNameForId
const useNameForId = pluginConfig.get(`useNameForId`)
const restrictedContentTypes = [`entity`, `reference`, `asset`]

if (pluginConfig.get(`enableTags`)) {
restrictedContentTypes.push(`tags`)
}

contentTypeItems.forEach(contentTypeItem => {
// Establish identifier for content type
// Use `name` if specified, otherwise, use internal id (usually a natural-language constant,
// but sometimes a base62 uuid generated by Contentful, hence the option)
let contentTypeItemId
if (useNameForId) {
contentTypeItemId = contentTypeItem.name.toLowerCase()
} else {
contentTypeItemId = contentTypeItem.sys.id.toLowerCase()
}

if (restrictedContentTypes.includes(contentTypeItemId)) {
reporter.panic({
id: CODES.FetchContentTypes,
context: {
sourceMessage: `Restricted ContentType name found. The name "${contentTypeItemId}" is not allowed.`,
},
})
}
// Prepare content types
normalizeContentTypeItems({
contentTypeItems,
pluginConfig,
reporter,
})

// Store processed content types in cache for sourceNodes
const sourceId = `${pluginConfig.get(`spaceId`)}-${pluginConfig.get(
`environment`
)}`
const CACHE_CONTENT_TYPES = `contentful-content-types-${sourceId}`
await cache.set(CACHE_CONTENT_TYPES, contentTypeItems)

createTypes(`
interface ContentfulEntry implements Node {
contentful_id: String!
Expand Down
37 changes: 37 additions & 0 deletions packages/gatsby-source-contentful/src/normalize.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const _ = require(`lodash`)
const stringify = require(`json-stringify-safe`)

const { CODES } = require(`./report`)

const typePrefix = `Contentful`
const makeTypeName = type => _.upperFirst(_.camelCase(`${typePrefix} ${type}`))

Expand Down Expand Up @@ -179,6 +181,41 @@ exports.buildForeignReferenceMap = ({
return foreignReferenceMap
}

// Check for restricted content type names and set id based on useNameForId
exports.normalizeContentTypeItems = ({
contentTypeItems,
pluginConfig,
reporter,
}) => {
const useNameForId = pluginConfig.get(`useNameForId`)
const restrictedContentTypes = [`entity`, `reference`, `asset`]

if (pluginConfig.get(`enableTags`)) {
restrictedContentTypes.push(`tags`)
}

contentTypeItems.forEach(contentTypeItem => {
// Establish identifier for content type
// Use `name` if specified, otherwise, use internal id (usually a natural-language constant,
// but sometimes a base62 uuid generated by Contentful, hence the option)
let contentTypeItemId
if (useNameForId) {
contentTypeItemId = contentTypeItem.name.toLowerCase()
} else {
contentTypeItemId = contentTypeItem.sys.id.toLowerCase()
}

if (restrictedContentTypes.includes(contentTypeItemId)) {
reporter.panic({
id: CODES.FetchContentTypes,
context: {
sourceMessage: `Restricted ContentType name found. The name "${contentTypeItemId}" is not allowed.`,
},
})
}
})
}

function prepareTextNode(id, node, key, text) {
const str = _.isString(text) ? text : ``
const textNode = {
Expand Down
13 changes: 10 additions & 3 deletions packages/gatsby-source-contentful/src/source-nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { createClient } = require(`contentful`)

import normalize from "./normalize"
const { createPluginConfig } = require(`./plugin-options`)
const { fetchContent } = require(`./fetch`)
const { fetchContent, fetchContentTypes } = require(`./fetch`)
const { CODES } = require(`./report`)
import { downloadContentfulAssets } from "./download-contentful-assets"

Expand Down Expand Up @@ -105,7 +105,6 @@ export async function sourceNodes(

const CACHE_SYNC_TOKEN = `contentful-sync-token-${sourceId}`
const CACHE_SYNC_DATA = `contentful-sync-data-${sourceId}`
const CACHE_CONTENT_TYPES = `contentful-content-types-${sourceId}`

/*
* Subsequent calls of Contentfuls sync API return only changed data.
Expand All @@ -128,7 +127,15 @@ export async function sourceNodes(
space,
} = await fetchContent({ syncToken, pluginConfig, reporter })

const contentTypeItems = await cache.get(CACHE_CONTENT_TYPES)
// Get content type items from Contentful
const contentTypeItems = await fetchContentTypes({ pluginConfig, reporter })

// Prepare content types
normalize.normalizeContentTypeItems({
contentTypeItems,
pluginConfig,
reporter,
})

const locales = allLocales.filter(pluginConfig.get(`localeFilter`))
reporter.verbose(
Expand Down

0 comments on commit a607dd1

Please sign in to comment.