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

refactor(contentful): migrate to schema customization API #32351

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions packages/gatsby-core-utils/src/fetch-remote-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,28 @@ const requestRemoteNode = (
})
})

const fetchCache = new Map()

export async function fetchRemoteFileWithCache(
args: IFetchRemoteFileOptions
): Promise<string> {
// If we are already fetching the file, return the unresolved promise
const inFlight = fetchCache.get(args.url)
if (inFlight) {
return inFlight
}

// Create file fetch promise and store it into cache
const fetchPromise = fetchRemoteFile(args)
fetchCache.set(args.url, fetchPromise)
const result = await fetchPromise

// When the file is fetched, replace the promise with the result
fetchCache.set(args.url, result)

return result
}

export async function fetchRemoteFile({
url,
cache,
Expand Down
6 changes: 5 additions & 1 deletion packages/gatsby-core-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ export { createRequireFromPath } from "./create-require-from-path"
export { getConfigStore } from "./get-config-store"
export { getGatsbyVersion } from "./get-gatsby-version"
export { getTermProgram } from "./get-term-program"
export { fetchRemoteFile, IFetchRemoteFileOptions } from "./fetch-remote-file"
export {
fetchRemoteFile,
fetchRemoteFileWithCache,
IFetchRemoteFileOptions,
} from "./fetch-remote-file"
export { isTruthy } from "./is-truthy"
export { getMatchPath } from "./match-path"
export * from "./service-lock"
Expand Down
85 changes: 0 additions & 85 deletions packages/gatsby-source-contentful/src/cache-image.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const _ = require(`lodash`)

const { createPluginConfig } = require(`./plugin-options`)

export async function createSchemaCustomization(
{ schema, actions, cache },
pluginOptions
) {
const { createTypes } = actions

const pluginConfig = createPluginConfig(pluginOptions)
const sourceId = `${pluginConfig.get(`spaceId`)}-${pluginConfig.get(
`environment`
)}`

const { contentTypeItems } = await cache.get(
`contentful-sync-result-${sourceId}`
)

createTypes(`
interface ContentfulEntry implements Node {
contentful_id: String!
id: ID!
node_locale: String!
}
`)

createTypes(`
interface ContentfulReference {
contentful_id: String!
id: ID!
}
`)

createTypes(
schema.buildObjectType({
name: `ContentfulAsset`,
fields: {
contentful_id: { type: `String!` },
id: { type: `ID!` },
},
interfaces: [`ContentfulReference`, `Node`],
})
)

// Create types for each content type
const gqlTypes = contentTypeItems.map(contentTypeItem =>
schema.buildObjectType({
name: _.upperFirst(
_.camelCase(
`Contentful ${
pluginConfig.get(`useNameForId`)
? contentTypeItem.name
: contentTypeItem.sys.id
}`
)
),
fields: {
contentful_id: { type: `String!` },
id: { type: `ID!` },
node_locale: { type: `String!` },
},
interfaces: [`ContentfulReference`, `ContentfulEntry`, `Node`],
})
)

createTypes(gqlTypes)
}
66 changes: 52 additions & 14 deletions packages/gatsby-source-contentful/src/extend-node-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ const {
GraphQLJSON,
GraphQLList,
} = require(`gatsby/graphql`)
const qs = require(`qs`)
const { fetchRemoteFileWithCache } = require(`gatsby-core-utils`)

const { stripIndent } = require(`common-tags`)
const qs = require(`qs`)

const cacheImage = require(`./cache-image`)
const downloadWithRetry = require(`./download-with-retry`).default
const {
ImageFormatType,
Expand All @@ -32,9 +33,6 @@ const {
// cache is more likely to go stale than the images (which never go stale)
// Note that the same image might be requested multiple times in the same run

// Supported Image Formats from https://www.contentful.com/developers/docs/references/images-api/#/reference/changing-formats/image-format
const validImageFormats = new Set([`jpg`, `png`, `webp`, `gif`])

if (process.env.GATSBY_REMOTE_CACHE) {
console.warn(
`Note: \`GATSBY_REMOTE_CACHE\` will be removed soon because it has been renamed to \`GATSBY_CONTENTFUL_EXPERIMENTAL_REMOTE_CACHE\``
Expand All @@ -60,10 +58,20 @@ const resolvedBase64Cache = new Map()
// @see https://www.contentful.com/developers/docs/references/images-api/#/reference/resizing-&-cropping/specify-width-&-height
const CONTENTFUL_IMAGE_MAX_SIZE = 4000

const isImage = image =>
[`image/jpeg`, `image/jpg`, `image/png`, `image/webp`, `image/gif`].includes(
image?.file?.contentType
)
// Supported Image Formats from https://www.contentful.com/developers/docs/references/images-api/#/reference/changing-formats/image-format
const validImageFormats = new Set([`jpg`, `png`, `webp`, `gif`])

const mimeTypeExtensions = new Map([
[`image/jpeg`, `.jpg`],
[`image/jpg`, `.jpg`],
[`image/gif`, `.gif`],
[`image/png`, `.png`],
[`image/webp`, `.webp`],
])

exports.mimeTypeExtensions = mimeTypeExtensions

const isImage = image => mimeTypeExtensions.has(image?.file?.contentType)

// Note: this may return a Promise<body>, body (sync), or null
const getBase64Image = (imageProps, reporter) => {
Expand Down Expand Up @@ -666,7 +674,7 @@ const fluidNodeType = ({ name, getTracedSVG, reporter }) => {
}
}

exports.extendNodeType = ({ type, store, reporter }) => {
exports.extendNodeType = ({ type, cache, reporter }) => {
if (type.name !== `ContentfulAsset`) {
return {}
}
Expand All @@ -676,15 +684,23 @@ exports.extendNodeType = ({ type, store, reporter }) => {

const { image, options } = args
const {
file: { contentType },
file: { contentType, url: imgUrl, fileName },
} = image

if (contentType.indexOf(`image/`) !== 0) {
return null
}

const absolutePath = await cacheImage(store, image, options, reporter)
const extension = path.extname(absolutePath)
const extension = mimeTypeExtensions.get(contentType)
const url = `https:` + createUrl(imgUrl, options)
const name = path.basename(fileName, extension)

const absolutePath = await fetchRemoteFileWithCache({
url,
name,
cache,
ext: extension,
})

return traceSVG({
file: {
Expand Down Expand Up @@ -712,7 +728,29 @@ exports.extendNodeType = ({ type, store, reporter }) => {
}

try {
const absolutePath = await cacheImage(store, image, options, reporter)
const {
file: { contentType, url: imgUrl, fileName },
} = image

if (contentType.indexOf(`image/`) !== 0) {
return null
}

// 256px should be enough to properly detect the dominant color
if (!options.width) {
options.width = 256
}

const extension = mimeTypeExtensions.get(contentType)
const url = `https:` + createUrl(imgUrl, options)
const name = path.basename(fileName, extension)

const absolutePath = await fetchRemoteFileWithCache({
url,
name,
cache,
ext: extension,
})

if (!(`getDominantColor` in pluginSharp)) {
console.error(
Expand Down
Loading