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-wordpress): MediaItem.excludeFieldNames / auto exclude interface types that have no fields (#37062) #37085

Merged
merged 1 commit into from
Nov 23, 2022
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -1381,7 +1381,6 @@ Array [
Object {
"fields": Array [
"avatar",
"databaseId",
"id",
"name",
"url",
Expand Down Expand Up @@ -1424,7 +1423,6 @@ Array [
"modifiedGmt",
"slug",
"status",
"template",
"uri",
"nodeType",
"parent",
Expand Down Expand Up @@ -5575,7 +5573,6 @@ Array [
"sourceUrl",
"srcSet",
"status",
"template",
"title",
"uri",
"nodeType",
Expand Down Expand Up @@ -6005,12 +6002,6 @@ Array [
],
"name": "WpNodeWithRevisionsToContentNodeConnectionEdge",
},
Object {
"fields": Array [
"template",
],
"name": "WpNodeWithTemplate",
},
Object {
"fields": Array [
"title",
Expand Down
1 change: 1 addition & 0 deletions integration-tests/gatsby-source-wordpress/gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ require(`dotenv`).config({
console.log(`Sourcing data from ` + process.env.WPGRAPHQL_URL)

const mediaItemTypeSettings = {
excludeFieldNames: [`template`],
localFile: {
excludeByMimeTypes: ["video/mp4"],
/**
Expand Down
21 changes: 21 additions & 0 deletions packages/gatsby-source-wordpress/docs/plugin-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
fieldOfTypeWasFetched,
getTypeSettingsByType,
filterTypeDefinition,
getTypesThatImplementInterfaceType,
} from "./helpers"

const unionType = typeBuilderApi => {
Expand Down Expand Up @@ -47,38 +48,24 @@ const unionType = typeBuilderApi => {
}

const interfaceType = typeBuilderApi => {
const { type, schema, gatsbyNodeTypes, fieldAliases, fieldBlacklist } =
typeBuilderApi
const { type, schema } = typeBuilderApi

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,
})

if (!transformedFields) {
return null
}

let typeDef = {
name: buildTypeName(type.name),
fields: transformedFields,
Expand Down Expand Up @@ -144,7 +131,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))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
Expand All @@ -84,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 => {
Expand All @@ -94,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
Expand All @@ -116,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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { fieldTransformers } from "./field-transformers"
import { getGatsbyNodeTypeNames } from "../../source-nodes/fetch-nodes/fetch-nodes"
import store from "~/store"

import {
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -197,5 +198,9 @@ export const transformFields = ({
return fieldsObject
}, {})

if (!Object.keys(transformedFields).length) {
return null
}

return transformedFields
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import {
findTypeName,
findTypeKind,
} from "~/steps/create-schema-customization/helpers"
import { fieldIsExcludedOnParentType } from "~/steps/ingest-remote-schema/is-excluded"
import {
fieldIsExcludedOnParentType,
fieldIsExcludedOnAll,
} from "~/steps/ingest-remote-schema/is-excluded"
import { returnAliasedFieldName } from "~/steps/create-schema-customization/transform-fields"

export const transformInlineFragments = ({
Expand Down Expand Up @@ -539,11 +542,12 @@ const transformFields = ({
?.filter(
field =>
!fieldIsExcludedOnParentType({
pluginOptions,
field,
parentType,
mainType,
parentField,
}) &&
!fieldIsExcludedOnAll({
pluginOptions,
field,
})
)
.map(field => {
Expand Down
Original file line number Diff line number Diff line change
@@ -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 () => {
Expand Down Expand Up @@ -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) {
Expand Down
Loading