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-source-drupal): drupal langcode as notlangcode #37445

Merged
merged 13 commits into from
Jan 11, 2023
2 changes: 1 addition & 1 deletion packages/gatsby-source-drupal/.babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"presets": [["babel-preset-gatsby-package"]]
"presets": [["babel-preset-gatsby-package"], "@babel/preset-typescript"]
}
8 changes: 8 additions & 0 deletions packages/gatsby-source-drupal/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"rules": {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/consistent-type-definitions": "off"
}
}
10 changes: 9 additions & 1 deletion packages/gatsby-source-drupal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,15 @@ module.exports = {
baseUrl: `https://live-contentacms.pantheonsite.io/`,
languageConfig: {
defaultLanguage: `en`,
enabledLanguages: [`en`, `fil`],
enabledLanguages: [
`en`,
`fil`,
// add an object here if you've renamed a langcode in Drupal
{
langCode: `en-gb`,
as: `uk`,
},
],
translatableEntities: [`node--article`],
nonTranslatableEntities: [`file--file`],
},
Expand Down
7 changes: 5 additions & 2 deletions packages/gatsby-source-drupal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"devDependencies": {
"@babel/cli": "^7.20.7",
"@babel/core": "^7.20.7",
"@babel/preset-typescript": "^7.18.6",
"babel-preset-gatsby-package": "^3.5.0-next.0",
"cross-env": "^7.0.3"
},
Expand All @@ -48,8 +49,10 @@
"directory": "packages/gatsby-source-drupal"
},
"scripts": {
"build": "babel src --out-dir . --ignore \"**/__tests__\"",
"build": "babel src --out-dir . --ignore \"**/__tests__\" --extensions \".ts,.js\"",
"prepare": "cross-env NODE_ENV=production npm run build",
"watch": "babel -w src --out-dir . --ignore \"**/__tests__\""
"watch": "babel -w src --out-dir . --ignore \"**/__tests__\" --extensions \".ts,.js\"",
"test": "npx jest ./src/__tests__ --runInBand",
"test:watch": "npx jest --watch ./src/__tests__ --runInBand"
}
}
8 changes: 7 additions & 1 deletion packages/gatsby-source-drupal/src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,13 @@ describe(`gatsby-source-drupal`, () => {
apiBase,
languageConfig: {
defaultLanguage: `en_US`,
enabledLanguages: [`en_US`, `i18n-test`],
enabledLanguages: [
`en_US`,
{
langCode: `en-gb`,
as: `i18n-test`,
},
],
translatableEntities: [`node--article`],
nonTranslatableEntities: [],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const got = require(`got`)
const _ = require(`lodash`)
const urlJoin = require(`url-join`)
import HttpAgent from "agentkeepalive"

// const http2wrapper = require(`http2-wrapper`)
const opentracing = require(`opentracing`)
const { SemanticAttributes } = require(`@opentelemetry/semantic-conventions`)
Expand All @@ -15,12 +16,13 @@ const { HttpsAgent } = HttpAgent

const { setOptions, getOptions } = require(`./plugin-options`)

const {
import {
nodeFromData,
downloadFile,
isFileNode,
imageCDNState,
} = require(`./normalize`)
} from "./normalize"

const {
handleReferences,
handleWebhookUpdate,
Expand Down Expand Up @@ -567,15 +569,19 @@ ${JSON.stringify(webhookBody, null, 4)}`
throw error
}
}

if (d.body.data) {
dataArray.push(...d.body.data)
// @ts-ignore
dataArray.push(...(d.body.data || []))
}

// Add support for includes. Includes allow entity data to be expanded
// based on relationships. The expanded data is exposed as `included`
// in the JSON API response.
// See https://www.drupal.org/docs/8/modules/jsonapi/includes
if (d.body.included) {
dataArray.push(...d.body.included)
// @ts-ignore
dataArray.push(...(d.body.included || []))
}

// If JSON:API extras is configured to add the resource count, we can queue
Expand All @@ -593,8 +599,8 @@ ${JSON.stringify(webhookBody, null, 4)}`

// Get count of API requests
// We round down as we've already gotten the first page at this point.
const pageSize = new URL(d.body.links.next.href).searchParams.get(
`page[limit]`
const pageSize = Number(
new URL(d.body.links.next.href).searchParams.get(`page[limit]`)
)
const requestsCount = Math.floor(d.body.meta.count / pageSize)

Expand All @@ -604,11 +610,14 @@ ${JSON.stringify(webhookBody, null, 4)}`

const newUrl = new URL(d.body.links.next.href)
await Promise.all(
_.range(requestsCount).map(pageOffset => {
_.range(requestsCount).map((pageOffset: number) => {
// We're starting 1 ahead.
pageOffset += 1
// Construct URL with new pageOffset.
newUrl.searchParams.set(`page[offset]`, pageOffset * pageSize)
newUrl.searchParams.set(
`page[offset]`,
String(pageOffset * pageSize)
)
return getNext(newUrl.toString(), currentLanguage)
})
)
Expand All @@ -626,6 +635,7 @@ ${JSON.stringify(webhookBody, null, 4)}`
const urlPath = url.href.split(`${apiBase}/`).pop()
const baseUrlWithoutTrailingSlash = baseUrl.replace(/\/$/, ``)
// The default language's JSON API is at the root.

if (
currentLanguage === getOptions().languageConfig.defaultLanguage ||
baseUrlWithoutTrailingSlash.slice(-currentLanguage.length) ==
Expand Down Expand Up @@ -869,7 +879,15 @@ exports.pluginOptionsSchema = ({ Joi }) =>
),
languageConfig: Joi.object({
defaultLanguage: Joi.string().required(),
enabledLanguages: Joi.array().items(Joi.string()).required(),
enabledLanguages: Joi.array()
.items(
Joi.string(),
Joi.object({
langCode: Joi.string().required(),
as: Joi.string().required(),
})
)
.required(),
translatableEntities: Joi.array().items(Joi.string()).required(),
nonTranslatableEntities: Joi.array().items(Joi.string()).required(),
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,20 @@ const { createRemoteFileNode } = require(`gatsby-source-filesystem`)
const path = require(`path`)
const probeImageSize = require(`probe-image-size`)

const { getOptions } = require(`./plugin-options`)
const getHref = link => {
import { getOptions } from "./plugin-options"

export const getHref = link => {
if (typeof link === `object`) {
return link.href
}
return link
}

exports.getHref = getHref

const imageCDNState = {
export const imageCDNState = {
foundPlaceholderStyle: false,
hasLoggedNoPlaceholderStyle: false,
}

exports.imageCDNState = imageCDNState

let four04WarningCount = 0
let corruptFileWarningCount = 0
/**
Expand Down Expand Up @@ -142,17 +139,20 @@ const getGatsbyImageCdnFields = async ({
return {}
}

const nodeFromData = async (
export const nodeFromData = async (
datum,
createNodeId,
entityReferenceRevisions = [],
pluginOptions,
fileNodesExtendedData,
reporter
) => {
const { attributes: { id: attributeId, ...attributes } = {} } = datum
const { attributes: { id: attributeId, ...attributes } = { id: null } } =
datum

const preservedId =
typeof attributeId !== `undefined` ? { _attributes_id: attributeId } : {}

const langcode = attributes.langcode || `und`
const type = datum.type.replace(/-|__|:|\.|\s/g, `_`)

Expand All @@ -164,16 +164,18 @@ const nodeFromData = async (
reporter,
})

const versionedId = createNodeIdWithVersion(
datum.id,
datum.type,
langcode,
attributes.drupal_internal__revision_id,
entityReferenceRevisions
)

const gatsbyId = createNodeId(versionedId)

return {
id: createNodeId(
createNodeIdWithVersion(
datum.id,
datum.type,
langcode,
attributes.drupal_internal__revision_id,
entityReferenceRevisions
)
),
id: gatsbyId,
drupal_id: datum.id,
parent: null,
drupal_parent_menu_item: attributes.parent,
Expand All @@ -189,52 +191,68 @@ const nodeFromData = async (
}
}

exports.nodeFromData = nodeFromData

const isEntityReferenceRevision = (type, entityReferenceRevisions = []) =>
entityReferenceRevisions.findIndex(
revisionType => type.indexOf(revisionType) === 0
) !== -1

const createNodeIdWithVersion = (
id,
type,
langcode,
revisionId,
export const createNodeIdWithVersion = (
id: string,
type: string,
langcode: string,
revisionId: string,
entityReferenceRevisions = []
) => {
const options = getOptions()

// Fallback to default language for entities that don't translate.
if (getOptions()?.languageConfig?.nonTranslatableEntities.includes(type)) {
langcode = getOptions().languageConfig.defaultLanguage
if (
options?.languageConfig?.nonTranslatableEntities?.includes(type) &&
options.languageConfig.defaultLanguage
) {
langcode = options.languageConfig.defaultLanguage
}

// If the source plugin hasn't enabled `translation` then always just set langcode
// to "undefined".
let langcodeNormalized = getOptions().languageConfig ? langcode : `und`
let langcodeNormalized = options.languageConfig ? langcode : `und`

const renamedCode = options?.languageConfig?.renamedEnabledLanguages?.find(
lang => lang.langCode === langcodeNormalized
)

if (renamedCode) {
langcodeNormalized = renamedCode.as
}

if (
getOptions().languageConfig &&
!getOptions().languageConfig?.enabledLanguages.includes(langcodeNormalized)
!renamedCode &&
options.languageConfig &&
options.languageConfig.defaultLanguage &&
!options?.languageConfig?.enabledLanguages?.includes(langcodeNormalized)
) {
langcodeNormalized = getOptions().languageConfig.defaultLanguage
langcodeNormalized = options.languageConfig.defaultLanguage
}

const isReferenceRevision = isEntityReferenceRevision(
type,
entityReferenceRevisions
)

// The relationship between an entity and another entity also depends on the revision ID if the field is of type
// entity reference revision such as for paragraphs.
return isEntityReferenceRevision(type, entityReferenceRevisions)
const idVersion = isReferenceRevision
? `${langcodeNormalized}.${id}.${revisionId || 0}`
: `${langcodeNormalized}.${id}`
}

exports.createNodeIdWithVersion = createNodeIdWithVersion
return idVersion
}

const isFileNode = node => {
export const isFileNode = node => {
const type = node?.internal?.type
return type === `files` || type === `file__file`
}

exports.isFileNode = isFileNode

const getFileUrl = (node, baseUrl) => {
let fileUrl = node.url

Expand All @@ -249,8 +267,8 @@ const getFileUrl = (node, baseUrl) => {
return url
}

exports.downloadFile = async (
{ node, store, cache, createNode, createNodeId, getCache, reporter },
export const downloadFile = async (
{ node, cache, createNode, createNodeId, getCache },
{ basicAuth, baseUrl }
) => {
// handle file downloads
Expand Down
10 changes: 0 additions & 10 deletions packages/gatsby-source-drupal/src/plugin-options.js

This file was deleted.

Loading