From 960bf210d77147c9e4980e0314a136c8979a93e1 Mon Sep 17 00:00:00 2001 From: Tyler Barnes Date: Fri, 18 Nov 2022 15:21:15 -0800 Subject: [PATCH 1/9] allow MediaItem type to use excludeFieldNames option --- .../docs/plugin-options.md | 21 +++++++++++++++++++ .../steps/declare-plugin-options-schema.js | 14 +++++++++++++ 2 files changed, 35 insertions(+) diff --git a/packages/gatsby-source-wordpress/docs/plugin-options.md b/packages/gatsby-source-wordpress/docs/plugin-options.md index 03cfa6aec7937..cb8fd920f0206 100644 --- a/packages/gatsby-source-wordpress/docs/plugin-options.md +++ b/packages/gatsby-source-wordpress/docs/plugin-options.md @@ -63,6 +63,7 @@ - [type.\_\_all.beforeChangeNode](#type__allbeforechangenode) - [type.RootQuery](#typerootquery) - [type.MediaItem](#typemediaitem) + - [type.MediaItem.excludeFieldNames](#typemediaitemexcludefieldnames) - [type.MediaItem.placeholderSizeName](#typemediaitemplaceholdersizename) - [type.MediaItem.createFileNodes](#typemediaitemcreatefilenodes) - [type.MediaItem.lazyNodes](#typemediaitemlazynodes) @@ -1230,6 +1231,26 @@ A special type which is applied to any non-node root fields that are ingested an **Field type**: `Object` +#### type.MediaItem.excludeFieldNames + +Excludes fields on the MediaItem type by field name. + +**Field type**: `Array` + +```js +{ + resolve: `gatsby-source-wordpress`, + options: { + type: { + MediaItem: { + excludeFieldNames: [`dateGmt`, `parent`], + }, + }, + }, +} + +``` + #### type.MediaItem.placeholderSizeName This option allows you to choose the placeholder size used in the new Gatsby image service (currently in ALPHA/BETA) for the small placeholder image. Please make this image size very small for better performance. 20px or smaller width is recommended. To use, create a new image size in WP and name it "gatsby-image-placeholder" (or the name that you pass to this option) and that new size will be used automatically for placeholder images in the Gatsby build. diff --git a/packages/gatsby-source-wordpress/src/steps/declare-plugin-options-schema.js b/packages/gatsby-source-wordpress/src/steps/declare-plugin-options-schema.js index 08e6dc4ec6990..f55e2e33d4b1b 100644 --- a/packages/gatsby-source-wordpress/src/steps/declare-plugin-options-schema.js +++ b/packages/gatsby-source-wordpress/src/steps/declare-plugin-options-schema.js @@ -765,6 +765,20 @@ When using this option, be sure to gitignore the wordpress-cache directory in th `), }), MediaItem: Joi.object({ + excludeFieldNames: Joi.array() + .items(Joi.string()) + .allow(null) + .allow(false) + .description(`Excludes fields on the MediaItem type by field name.`) + .meta({ + example: wrapOptions(` + type: { + MediaItem: { + excludeFieldNames: [\`dateGmt\`, \`parent\`], + }, + }, + `), + }), placeholderSizeName: Joi.string() .default(`gatsby-image-placeholder`) .description( From d5e3414c1a173f0b9cf7c464fd44b5676217f309 Mon Sep 17 00:00:00 2001 From: Tyler Barnes Date: Fri, 18 Nov 2022 15:22:30 -0800 Subject: [PATCH 2/9] make sure cached media item nodes always return the MediaItem node, not File nodes if those are cached --- .../fetch-nodes/fetch-referenced-media-items.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/gatsby-source-wordpress/src/steps/source-nodes/fetch-nodes/fetch-referenced-media-items.js b/packages/gatsby-source-wordpress/src/steps/source-nodes/fetch-nodes/fetch-referenced-media-items.js index 993a02ce2330f..66edd0b52f64e 100644 --- a/packages/gatsby-source-wordpress/src/steps/source-nodes/fetch-nodes/fetch-referenced-media-items.js +++ b/packages/gatsby-source-wordpress/src/steps/source-nodes/fetch-nodes/fetch-referenced-media-items.js @@ -343,7 +343,16 @@ export const fetchMediaItemsBySourceUrl = async ({ // take our previously cached id's and get nodes for them const previouslyCachedMediaItemNodes = await Promise.all( - cachedMediaItemNodeIds.map(async nodeId => helpers.getNode(nodeId)) + cachedMediaItemNodeIds.map(async nodeId => { + const node = await helpers.getNode(nodeId) + + const parentNode = + node?.internal?.type === `File` && node?.parent + ? helpers.getNode(node.parent) + : null + + return parentNode || node + }) ) const { From 16d8fd427a6edf6b78c6bbeb62fb2831be9b435c Mon Sep 17 00:00:00 2001 From: Tyler Barnes Date: Fri, 18 Nov 2022 15:23:32 -0800 Subject: [PATCH 3/9] use get type settings helper instead of accessing settings on options --- .../steps/ingest-remote-schema/is-excluded.js | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/is-excluded.js b/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/is-excluded.js index 8082b7dc84319..42edad258f958 100644 --- a/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/is-excluded.js +++ b/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/is-excluded.js @@ -1,5 +1,8 @@ import store from "~/store" -import { findTypeName } from "~/steps/create-schema-customization/helpers" +import { + findTypeName, + getTypeSettingsByType, +} from "~/steps/create-schema-customization/helpers" const typeIsExcluded = ({ pluginOptions, typeName }) => pluginOptions && @@ -15,9 +18,7 @@ const fieldIsExcludedOnAll = ({ pluginOptions, field }) => { return !!allFieldSettings?.excludeFieldNames?.includes(field?.name) } -const fieldIsExcludedOnParentType = ({ pluginOptions, field, parentType }) => { - const allTypeSettings = pluginOptions.type - +const fieldIsExcludedOnParentType = ({ field, parentType }) => { const state = store.getState() const { typeMap } = state.remoteSchema @@ -27,15 +28,16 @@ const fieldIsExcludedOnParentType = ({ pluginOptions, field, parentType }) => { field => field.name === `nodes` ) - const parentTypeNodesFieldTypeName = findTypeName(parentTypeNodesField?.type) + const parentTypeNameSettings = getTypeSettingsByType(parentType) + const parentTypeNodesFieldTypeNameSettings = getTypeSettingsByType( + parentTypeNodesField?.type + ) const fieldIsExcludedOnParentType = // if this field is excluded on either the parent type - allTypeSettings[parentType?.name]?.excludeFieldNames?.includes( - field?.name - ) || + parentTypeNameSettings?.excludeFieldNames?.includes(field?.name) || // or the parent type has a "nodes" field and that type has this field excluded - allTypeSettings[parentTypeNodesFieldTypeName]?.excludeFieldNames?.includes( + parentTypeNodesFieldTypeNameSettings?.excludeFieldNames?.includes( field?.name ) From 0db3bc5901b96ae9edd6a9c9a23150ab326ea8c5 Mon Sep 17 00:00:00 2001 From: Tyler Barnes Date: Fri, 18 Nov 2022 15:30:04 -0800 Subject: [PATCH 4/9] auto exclude interface types that have no fields due to an implementing type excluding all of it's fields --- .../build-types.js | 39 ++++++++----------- .../create-schema-customization/helpers.js | 32 +++++++++++++++ .../transform-fields/index.js | 13 +++++-- .../recursively-transform-fields.js | 3 -- .../identify-and-store-ingestable-types.js | 23 ++++++++++- 5 files changed, 79 insertions(+), 31 deletions(-) diff --git a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/build-types.js b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/build-types.js index de91b8b0e32c5..b6930ea45f373 100644 --- a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/build-types.js +++ b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/build-types.js @@ -6,6 +6,7 @@ import { fieldOfTypeWasFetched, getTypeSettingsByType, filterTypeDefinition, + getTypesThatImplementInterfaceType, } from "./helpers" const unionType = typeBuilderApi => { @@ -47,38 +48,26 @@ const unionType = typeBuilderApi => { } const interfaceType = typeBuilderApi => { - const { type, schema, gatsbyNodeTypes, fieldAliases, fieldBlacklist } = - typeBuilderApi + const { type, schema } = typeBuilderApi + const debug = type.name === `WpNode` || type.name === `Node` const state = store.getState() - const { ingestibles, typeMap } = state.remoteSchema + const { ingestibles } = state.remoteSchema const { nodeInterfaceTypes } = ingestibles - const allTypes = typeMap.values() - - const implementingTypes = Array.from(allTypes) - .filter( - ({ interfaces }) => - interfaces && - // find types that implement this interface type - interfaces.find(singleInterface => singleInterface.name === type.name) - ) - .map(type => typeMap.get(type.name)) - .filter( - type => - type.kind !== `UNION` || - // if this is a union type, make sure the union type has one or more member types, otherwise schema customization will throw an error - (!!type.possibleTypes && !!type.possibleTypes.length) - ) + const implementingTypes = getTypesThatImplementInterfaceType(type) const transformedFields = transformFields({ parentInterfacesImplementingTypes: implementingTypes, + parentType: type, fields: type.fields, - gatsbyNodeTypes, - fieldAliases, - fieldBlacklist, + debug, }) + if (!transformedFields) { + return null + } + let typeDef = { name: buildTypeName(type.name), fields: transformedFields, @@ -144,7 +133,11 @@ const objectType = typeBuilderApi => { .filter(interfaceType => { const interfaceTypeSettings = getTypeSettingsByType(interfaceType) - return !interfaceTypeSettings.exclude && fieldOfTypeWasFetched(type) + return ( + !interfaceTypeSettings.exclude && + fieldOfTypeWasFetched(type) && + fieldOfTypeWasFetched(interfaceType) + ) }) .map(({ name }) => buildTypeName(name)) } diff --git a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/helpers.js b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/helpers.js index 0afa669a0dd34..b592d1feb3f7d 100644 --- a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/helpers.js +++ b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/helpers.js @@ -59,6 +59,38 @@ export const fieldOfTypeWasFetched = type => { return typeWasFetched } +const implementingTypeCache = new Map() + +export const getTypesThatImplementInterfaceType = type => { + if (implementingTypeCache.has(type.name)) { + return implementingTypeCache.get(type.name) + } + + const state = store.getState() + const { typeMap } = state.remoteSchema + + const allTypes = typeMap.values() + + const implementingTypes = Array.from(allTypes) + .filter( + ({ interfaces }) => + interfaces && + // find types that implement this interface type + interfaces.find(singleInterface => singleInterface.name === type.name) + ) + .map(type => typeMap.get(type.name)) + .filter( + type => + type.kind !== `UNION` || + // if this is a union type, make sure the union type has one or more member types, otherwise schema customization will throw an error + (!!type.possibleTypes && !!type.possibleTypes.length) + ) + + implementingTypeCache.set(type.name, implementingTypes) + + return implementingTypes +} + const supportedScalars = [ `Int`, `Float`, diff --git a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/transform-fields/index.js b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/transform-fields/index.js index 8809f45c2c1e4..c16c7037196e5 100644 --- a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/transform-fields/index.js +++ b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/transform-fields/index.js @@ -1,4 +1,5 @@ import { fieldTransformers } from "./field-transformers" +import { getGatsbyNodeTypeNames } from "../../source-nodes/fetch-nodes/fetch-nodes" import store from "~/store" import { @@ -88,19 +89,19 @@ const excludeField = ({ * with proper node linking and type namespacing * also filters out unusable fields and types */ - export const transformFields = ({ fields, - fieldAliases, - fieldBlacklist, parentType, parentInterfacesImplementingTypes, - gatsbyNodeTypes, }) => { if (!fields || !fields.length) { return null } + const gatsbyNodeTypes = getGatsbyNodeTypeNames() + + const { fieldAliases, fieldBlacklist } = store.getState().remoteSchema + const parentTypeSettings = getTypeSettingsByType(parentType) const parentInterfacesImplementingTypeSettings = @@ -197,5 +198,9 @@ export const transformFields = ({ return fieldsObject }, {}) + if (!Object.keys(transformedFields).length) { + return null + } + return transformedFields } diff --git a/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/build-queries-from-introspection/recursively-transform-fields.js b/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/build-queries-from-introspection/recursively-transform-fields.js index 7aaf7b3344f70..acf2bcc549228 100644 --- a/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/build-queries-from-introspection/recursively-transform-fields.js +++ b/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/build-queries-from-introspection/recursively-transform-fields.js @@ -542,11 +542,8 @@ const transformFields = ({ ?.filter( field => !fieldIsExcludedOnParentType({ - pluginOptions, field, parentType, - mainType, - parentField, }) && !fieldIsExcludedOnAll({ pluginOptions, diff --git a/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/identify-and-store-ingestable-types.js b/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/identify-and-store-ingestable-types.js index c2a64131f195c..b551dcc58c986 100644 --- a/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/identify-and-store-ingestable-types.js +++ b/packages/gatsby-source-wordpress/src/steps/ingest-remote-schema/identify-and-store-ingestable-types.js @@ -1,7 +1,11 @@ import store from "~/store" import { typeIsExcluded } from "~/steps/ingest-remote-schema/is-excluded" import { typeIsABuiltInScalar } from "../create-schema-customization/helpers" -import { findTypeName } from "~/steps/create-schema-customization/helpers" +import { + findTypeName, + getTypesThatImplementInterfaceType, +} from "~/steps/create-schema-customization/helpers" +import { transformFields } from "~/steps/create-schema-customization/transform-fields" import { getPersistentCache } from "~/utils/cache" const identifyAndStoreIngestableFieldsAndTypes = async () => { @@ -46,6 +50,23 @@ const identifyAndStoreIngestableFieldsAndTypes = async () => { continue } + if (!interfaceType.fields) { + continue + } + + const typesThatImplementInterface = + getTypesThatImplementInterfaceType(interfaceType) + + const shouldSkipInterfaceType = !transformFields({ + fields: interfaceType.fields, + parentType: interfaceType, + parentInterfacesImplementingTypes: typesThatImplementInterface, + }) + + if (shouldSkipInterfaceType && interfaceType.name !== `Node`) { + continue + } + store.dispatch.remoteSchema.addFetchedType(interfaceType) if (interfaceType.fields) { From 0fc3e110299c5ae9199526896f83379236c75d3a Mon Sep 17 00:00:00 2001 From: Tyler Barnes Date: Fri, 18 Nov 2022 15:30:22 -0800 Subject: [PATCH 5/9] this should've been excluded before! Fixed now --- .../__tests__/__snapshots__/index.js.snap | 1 - 1 file changed, 1 deletion(-) diff --git a/integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap b/integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap index 670f199ca6f0f..b42f335439b64 100644 --- a/integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap +++ b/integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap @@ -1493,7 +1493,6 @@ Array [ Object { "fields": Array [ "avatar", - "databaseId", "id", "name", "url", From 0a369644b2428762d6baeadd6c6efabb1b22a932 Mon Sep 17 00:00:00 2001 From: Tyler Barnes Date: Fri, 18 Nov 2022 15:30:29 -0800 Subject: [PATCH 6/9] update comment --- .../src/steps/create-schema-customization/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/index.js b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/index.js index 3e9b4595ab11b..eb181e3db5015 100644 --- a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/index.js +++ b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/index.js @@ -62,8 +62,7 @@ const customizeSchema = async ({ actions, schema, store: gatsbyStore }) => { break case `SCALAR`: /** - * custom scalar types aren't imlemented currently. - * @todo make this hookable so sub-plugins or plugin options can add custom scalar support. + * custom scalar types aren't supported. */ break } From 2c6f33b4b87dcd625cd700dfb038635d569baa74 Mon Sep 17 00:00:00 2001 From: Tyler Barnes Date: Fri, 18 Nov 2022 15:30:47 -0800 Subject: [PATCH 7/9] use Map for caching instead of object properties --- .../src/steps/create-schema-customization/helpers.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/helpers.js b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/helpers.js index b592d1feb3f7d..d16c6dd836be1 100644 --- a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/helpers.js +++ b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/helpers.js @@ -116,7 +116,7 @@ export const typeIsASupportedScalar = type => { return supportedScalars.includes(findTypeName(type)) } -const typeSettingCache = {} +const typeSettingCache = new Map() // retrieves plugin settings for the provided type export const getTypeSettingsByType = type => { @@ -126,7 +126,11 @@ export const getTypeSettingsByType = type => { const typeName = findTypeName(type) - const cachedTypeSettings = typeSettingCache[typeName] + if (!typeName) { + return {} + } + + const cachedTypeSettings = typeSettingCache.get(typeName) if (cachedTypeSettings) { return cachedTypeSettings @@ -148,12 +152,12 @@ export const getTypeSettingsByType = type => { if (typeSettings) { const mergedSettings = merge(__allTypeSetting, typeSettings) - typeSettingCache[typeName] = mergedSettings + typeSettingCache.set(typeName, mergedSettings) return mergedSettings } - typeSettingCache[typeName] = __allTypeSetting + typeSettingCache.set(typeName, __allTypeSetting) return __allTypeSetting } From cb5cb8d4ae7398fd0bb328fbbbc25197edcefe17 Mon Sep 17 00:00:00 2001 From: Tyler Barnes Date: Fri, 18 Nov 2022 15:49:29 -0800 Subject: [PATCH 8/9] exclude MediaItem.template field in tests --- .../__tests__/__snapshots__/index.js.snap | 8 -------- .../gatsby-source-wordpress/gatsby-config.js | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap b/integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap index b42f335439b64..c46abb54c341d 100644 --- a/integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap +++ b/integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap @@ -1543,7 +1543,6 @@ Array [ "modifiedGmt", "slug", "status", - "template", "uri", "nodeType", "parent", @@ -5782,7 +5781,6 @@ Array [ "sourceUrl", "srcSet", "status", - "template", "title", "uri", "nodeType", @@ -6300,12 +6298,6 @@ Array [ ], "name": "WpNodeWithRevisionsToContentNodeConnectionEdge", }, - Object { - "fields": Array [ - "template", - ], - "name": "WpNodeWithTemplate", - }, Object { "fields": Array [ "title", diff --git a/integration-tests/gatsby-source-wordpress/gatsby-config.js b/integration-tests/gatsby-source-wordpress/gatsby-config.js index 31708eb64fb2e..d38b13b4dcd1b 100644 --- a/integration-tests/gatsby-source-wordpress/gatsby-config.js +++ b/integration-tests/gatsby-source-wordpress/gatsby-config.js @@ -5,6 +5,7 @@ require(`dotenv`).config({ console.log(`Sourcing data from ` + process.env.WPGRAPHQL_URL) const mediaItemTypeSettings = { + excludeFieldNames: [`template`], localFile: { excludeByMimeTypes: ["video/mp4"], /** From a06278631171f78a7a0966e06c104fdcd694a367 Mon Sep 17 00:00:00 2001 From: Tyler Barnes Date: Fri, 18 Nov 2022 15:59:29 -0800 Subject: [PATCH 9/9] remove debug code --- .../src/steps/create-schema-customization/build-types.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/build-types.js b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/build-types.js index b6930ea45f373..87966d6171be6 100644 --- a/packages/gatsby-source-wordpress/src/steps/create-schema-customization/build-types.js +++ b/packages/gatsby-source-wordpress/src/steps/create-schema-customization/build-types.js @@ -49,7 +49,6 @@ const unionType = typeBuilderApi => { const interfaceType = typeBuilderApi => { const { type, schema } = typeBuilderApi - const debug = type.name === `WpNode` || type.name === `Node` const state = store.getState() const { ingestibles } = state.remoteSchema @@ -61,7 +60,6 @@ const interfaceType = typeBuilderApi => { parentInterfacesImplementingTypes: implementingTypes, parentType: type, fields: type.fields, - debug, }) if (!transformedFields) {