GraphQL field resolvers for remote file processing, image transformation, and URL generation with support for both native Gatsby image CDN and polyfill functionality.
GraphQL resolver that generates optimized image data for gatsby-image components with support for responsive images, multiple formats, and lazy loading.
/**
* Resolves gatsby image data for remote images
* @param source - Remote file node source
* @param args - Image processing arguments
* @param actions - Gatsby actions for caching
* @param store - Gatsby store (optional)
* @returns Promise with gatsby image data or null if not an image
*/
function gatsbyImageResolver(
source: IRemoteFileNode,
args: IGatsbyImageDataArgs,
actions: Actions,
store?: Store
): Promise<{
images: IGatsbyImageData;
layout: string;
width: number;
height: number;
backgroundColor?: string;
placeholder?: { fallback: string } | undefined;
} | null>;
interface IGatsbyImageDataArgs {
/** Image layout type (required) */
layout: ImageLayout;
/** Maximum width for responsive images */
width?: number;
/** Maximum height for responsive images */
height?: number;
/** Aspect ratio override */
aspectRatio?: number;
/** Image format preference */
formats?: Array<ImageFormat>;
/** Placeholder style */
placeholder?: PlaceholderType | "none";
/** Quality setting (1-100) */
quality?: number;
/** Crop focus area */
cropFocus?: Array<ImageCropFocus>;
/** Image fit mode */
fit?: ImageFit;
/** Breakpoints for responsive images */
breakpoints?: Array<number>;
/** Output pixel densities */
outputPixelDensities?: Array<number>;
/** Background color for transparent images */
backgroundColor?: string;
/** Sizes attribute for responsive images */
sizes?: string;
}
interface IGatsbyImageData {
sources: Array<{
srcSet: string;
type: string;
sizes: string;
}>;
fallback: {
srcSet: string;
src: string;
sizes: string;
};
}Usage Examples:
// In GraphQL schema
const gatsbyImageField = generateGatsbyImageFieldConfig(enums, actions, store);
// GraphQL query
query {
myImageNode {
gatsbyImage(
layout: CONSTRAINED
width: 800
height: 600
formats: [WEBP, JPG]
placeholder: BLURRED
quality: 80
) {
images {
sources {
srcSet
type
}
fallback {
src
srcSet
}
}
width
height
placeholder {
fallback
}
}
}
}GraphQL resolver for simple image resizing operations with format conversion support.
/**
* Resolves resized image data
* @param source - Remote file node source
* @param args - Resize arguments with width/height requirement
* @param actions - Gatsby actions for caching
* @param store - Gatsby store (optional)
* @returns Promise with resized image data or null if not an image
*/
function resizeResolver(
source: IRemoteFileNode,
args: Partial<IResizeArgs> & WidthOrHeight,
actions: Actions,
store?: Store
): Promise<{
width: number;
height: number;
src: string;
} | null>;
interface IResizeArgs {
/** Image fit mode */
fit: ImageFit;
/** Output format */
format: ImageFormat;
/** Crop focus area */
cropFocus: Array<ImageCropFocus>;
/** Quality setting (1-100) */
quality: number;
/** Aspect ratio override */
aspectRatio: number;
}
interface WidthOrHeight {
/** Target width (required if height not provided) */
width?: number;
/** Target height (required if width not provided) */
height?: number;
}
interface IRemoteFileResize {
/** Processed image URL */
src: string;
/** Final image width */
width: number;
/** Final image height */
height: number;
}Usage Examples:
// GraphQL query
query {
myImageNode {
resize(width: 400, height: 300, format: WEBP, quality: 90) {
src
width
height
}
thumbnail: resize(width: 150, height: 150, fit: COVER) {
src
}
hero: resize(width: 1200, format: WEBP) {
src
width
height
}
}
}GraphQL resolver that provides direct access to remote file URLs with proper caching headers.
/**
* Resolves public URL for remote files
* @param source - Remote file node source
* @param actions - Gatsby actions for caching
* @param store - Gatsby store (optional)
* @returns Public URL string
*/
function publicUrlResolver(
source: IRemoteFileNode,
actions: Actions,
store?: Store
): string;Usage Examples:
// GraphQL query
query {
myFileNode {
publicUrl
}
myImageNode {
publicUrl # Direct image URL
resize(width: 400) {
src # Processed image URL
}
}
}
// Usage in React component
import React from "react";
import { graphql } from "gatsby";
const MyComponent = ({ data }) => {
return (
<div>
<img src={data.myImage.publicUrl} alt="Original image" />
<img src={data.myImage.resize.src} alt="Resized image" />
</div>
);
};
export const query = graphql`
query {
myImage {
publicUrl
resize(width: 400) {
src
}
}
}
`;Creates GraphQL field configuration for gatsby image processing.
/**
* Generates GraphQL field config for gatsby image processing
* @param enums - Remote file enums for GraphQL types
* @param actions - Gatsby actions
* @param store - Gatsby store (optional)
* @returns GraphQL field configuration
*/
function generateGatsbyImageFieldConfig(
enums: RemoteFileEnums,
actions: Actions,
store?: Store
): IGraphQLFieldConfigDefinition<IRemoteFileNode, {
images: IGatsbyImageData;
layout: string;
width: number;
height: number;
backgroundColor?: string;
placeholder?: { fallback: string } | undefined;
} | null, IGatsbyImageDataArgs>;Creates GraphQL field configuration for image resizing.
/**
* Generates GraphQL field config for image resizing
* @param enums - Remote file enums for GraphQL types
* @param actions - Gatsby actions
* @param store - Gatsby store (optional)
* @returns GraphQL field configuration
*/
function generateResizeFieldConfig(
enums: RemoteFileEnums,
actions: Actions,
store?: Store
): IGraphQLFieldConfigDefinition<IRemoteFileNode, {
width: number;
height: number;
src: string;
} | null, Partial<IResizeArgs> & WidthOrHeight>;Creates GraphQL field configuration for public URL access.
/**
* Generates GraphQL field config for public URLs
* @param actions - Gatsby actions
* @param store - Gatsby store (optional)
* @returns GraphQL field configuration
*/
function generatePublicUrlFieldConfig(
actions: Actions,
store?: Store
): IGraphQLFieldConfigDefinition<IRemoteFileNode, string>;Creates GraphQL enum types for image processing options.
/**
* Creates GraphQL enums for remote file processing
* @param createEnumTC - Function to create enum type composers
* @returns Object with enum type composers
*/
function getRemoteFileEnums(
createEnumTC: (name: string) => EnumTypeComposer
): {
ImageFormat: EnumTypeComposer;
ImageLayout: EnumTypeComposer;
ImagePlaceholder: EnumTypeComposer;
ImageCropFocus: EnumTypeComposer;
ImageFit: EnumTypeComposer;
};The generated enums include:
enum ImageFormat {
NO_CHANGE
AUTO
JPG
PNG
WEBP
AVIF
}
enum ImageLayout {
FIXED
FIXED_WIDTH
CONSTRAINED
FULL_WIDTH
}
enum ImagePlaceholder {
DOMINANT_COLOR
BLURRED
NONE
}
enum ImageCropFocus {
CENTER
NORTH
NORTHEAST
EAST
SOUTHEAST
SOUTH
SOUTHWEST
WEST
NORTHWEST
ENTROPY
ATTENTION
}
enum ImageFit {
COVER
CONTAIN
FILL
INSIDE
OUTSIDE
}// gatsby-node.js
const {
getRemoteFileEnums,
generateGatsbyImageFieldConfig,
generateResizeFieldConfig,
generatePublicUrlFieldConfig
} = require("gatsby-plugin-utils/polyfill-remote-file");
const { SchemaComposer } = require("graphql-compose");
exports.createSchemaCustomization = ({ actions, schema, store }) => {
// Create enums
const composer = new SchemaComposer();
const enums = getRemoteFileEnums(composer.createEnumTC.bind(composer));
// Create enum types in Gatsby schema
const enumTypes = [];
for (const enumName in enums) {
enumTypes.push(
schema.buildEnumType({
name: enums[enumName].getTypeName(),
values: enums[enumName].getFields()
})
);
}
// Create RemoteFile interface with resolvers
const remoteFileInterface = schema.buildInterfaceType({
name: 'RemoteFile',
fields: {
id: 'ID!',
mimeType: 'String!',
filename: 'String!',
filesize: 'Int',
width: 'Int',
height: 'Int',
publicUrl: generatePublicUrlFieldConfig(actions, store),
resize: generateResizeFieldConfig(enums, actions, store),
gatsbyImage: generateGatsbyImageFieldConfig(enums, actions, store)
}
});
// Create types
actions.createTypes([
...enumTypes,
remoteFileInterface,
schema.buildObjectType({
name: 'RemoteFileResize',
fields: {
width: 'Int',
height: 'Int',
src: 'String'
}
})
]);
};// Component with conditional image processing
import React from "react";
import { GatsbyImage, getImage } from "gatsby-plugin-image";
const ResponsiveImage = ({ imageNode, isHero = false }) => {
const heroImageArgs = {
layout: "FULL_WIDTH",
formats: ["WEBP", "JPG"],
placeholder: "BLURRED",
quality: 90
};
const thumbnailArgs = {
layout: "FIXED",
width: 300,
height: 200,
formats: ["WEBP", "JPG"],
placeholder: "DOMINANT_COLOR"
};
const args = isHero ? heroImageArgs : thumbnailArgs;
const image = getImage(imageNode.gatsbyImage);
return image ? (
<GatsbyImage image={image} alt={imageNode.alt || ""} />
) : (
<img src={imageNode.publicUrl} alt={imageNode.alt || ""} />
);
};// Optimized GraphQL query with fragments
export const imageFragment = graphql`
fragment OptimizedImage on RemoteFile {
publicUrl
gatsbyImage(
layout: CONSTRAINED
width: 800
formats: [WEBP, JPG]
placeholder: BLURRED
quality: 80
) {
...GatsbyImageData
}
resize(width: 400, format: WEBP) {
src
width
height
}
}
`;
export const query = graphql`
query {
heroImage {
...OptimizedImage
}
thumbnails {
...OptimizedImage
}
}
`;interface IGraphQLFieldConfigDefinition<TSource, TReturn, TArgs = {}> {
type: string;
description?: string;
args?: {
[K in keyof TArgs]: {
type: string;
description?: string;
defaultValue?: TArgs[K];
};
};
resolve(source: TSource, args: TArgs): TReturn;
}