Last active
November 18, 2019 23:28
-
-
Save hyrsky/b11c7327fda6f84b327b48ca5593958d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** GraphQL type name for union of all known paragraph types. */ | |
const PARAGRAPH_UNON_NAME = 'paragraph_types_union' | |
/** GraphQL type name for union of all known media types. */ | |
const MEDIA_UNON_NAME = 'media_types_union' | |
/** Construct field schema with type overrides. */ | |
function createCustomFields(fields) { | |
return fields.reduce((schema, { type, name: fieldName }) => { | |
const resolveById = (parent, args, context) => { | |
const ids = parent[`${fieldName}___NODE`] | |
return context.nodeModel.getNodesByIds({ | |
ids: Array.isArray(ids) ? ids : [ids] | |
}) | |
} | |
switch (type) { | |
case 'paragraphs': | |
schema[fieldName] = { | |
type: `[${PARAGRAPH_UNON_NAME}]`, | |
// Resolve correct paragraph nodes. | |
resolve: resolveById | |
} | |
break | |
case 'media': | |
schema[fieldName] = { | |
type: `[${MEDIA_UNON_NAME}]`, | |
// Resolve correct media nodes. | |
resolve: resolveById | |
} | |
break | |
} | |
return schema | |
}, {}) | |
} | |
/** | |
* gatsby-source-drupal does not handle GraphQL type unions well if not relationship data is present. | |
* | |
* For example instead of infering a separate type for each paragraph field it | |
* would be easier to reuse code if we had a global paragrah type that | |
* would include all paragraph types. | |
* | |
* This schema customization overrides media and paragraph field types to do | |
* just that. | |
*/ | |
exports.createSchemaCustomization = ({ actions, schema, getNodesByType }) => { | |
/** Fix union types for these types and their fields. */ | |
const FixTypes = [ | |
{ type: 'node__landing_page', fields: [{ type: 'paragraphs', name: 'field_landing_paragraphs' }] }, | |
{ type: 'paragraph__hero_form', fields: [{ type: 'media', name: 'field_media_any' }] }, | |
{ type: 'paragraph__media', fields: [{ type: 'media', name: 'field_media_any' }] } | |
] | |
const getAllDrupalTypes = drupalType => | |
getNodesByType(drupalType) | |
.flatMap(node => Object.keys(node.relationships)) | |
.map(type => type.replace('___NODE', '')) | |
/** Get GraphQL relationship field type name for given type. */ | |
const relationshipName = type => `${type}__relationship` | |
// Get all media types. | |
const mediaTypes = getAllDrupalTypes('media_type__media_type') | |
// Get all paragrah types (related to any node in any language). | |
const paragraphTypes = getAllDrupalTypes('paragraphs_type__paragraphs_type') | |
if (process.env.NODE_ENV === 'development') { | |
console.log(`Found ${mediaTypes.length} media types:`, mediaTypes) | |
console.log(`Found ${paragraphTypes.length} paragraph types:`, paragraphTypes) | |
} | |
const { createTypes } = actions | |
createTypes([ | |
// Create GraphQL union type that includes all found paragraph types. | |
schema.buildUnionType({ | |
name: PARAGRAPH_UNON_NAME, | |
types: paragraphTypes | |
}), | |
// Create GraphQL union type that includes all media types. | |
schema.buildUnionType({ | |
name: MEDIA_UNON_NAME, | |
types: mediaTypes | |
}), | |
// Override relationship field type for specified content types. | |
...FixTypes.map( | |
({ type }) => ` | |
type ${type} implements Node @infer { | |
relationships: ${relationshipName(type)} | |
} | |
` | |
), | |
// Change relationship field type to include all found paragraphs types. | |
...FixTypes.map(({ type, fields }) => | |
schema.buildObjectType({ | |
name: relationshipName(type), | |
interfaces: ['Node'], | |
fields: createCustomFields(fields) | |
}) | |
) | |
]) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment