UNPKG

gatsby-source-cloudinary

Version:

Gatsby source plugin to fetch files from Cloudinary into Gatsby.

162 lines (146 loc) 4.27 kB
const { newCloudinary, getResourceOptions, generateCloudinaryUrl, } = require('./utils'); const REPORTER_PREFIX = `gatsby-source-cloudinary`; const NODE_TYPE = `CloudinaryMedia`; exports.pluginOptionsSchema = ({ Joi }) => { return Joi.object({ cloudName: Joi.string().required(), apiKey: Joi.string().required(), apiSecret: Joi.string().required(), resourceType: Joi.string().default('image'), type: Joi.string(), maxResults: Joi.number().integer().positive().default(10), resultsPerPage: Joi.number() .integer() .positive() .default(Joi.ref('maxResults')), tags: Joi.boolean().default(false), prefix: Joi.string(), context: Joi.boolean(), cname: Joi.string(), secureDistribution: Joi.string(), privateCdn: Joi.boolean().default(false), }); }; const getNodeData = ( gatsbyUtils, media, cloudName, cname, secureDistribution, privateCdn, ) => { const { createNodeId, createContentDigest } = gatsbyUtils; // When Cloudinary returns a resource via the API, they return both // a secure_url and a url, with the url including `http://`. We want // to extend this option to what we return so that the developer // can have the option of using the URL they prefer for their // specific use case along with any transformations const url = generateCloudinaryUrl(media, { secure: false, cname: cname, secure_distribution: secureDistribution, private_cdn: privateCdn, }); const secureUrl = generateCloudinaryUrl(media, { secure: true, cname: cname, secure_distribution: secureDistribution, private_cdn: privateCdn, }); return { // Keep all original data around, // keep for backwards compatability. // Remove in favour of `cloudinaryData: media`, // when next breaking change is released ...media, // ID id: createNodeId(`cloudinary-media-${media.public_id}`), // Needed by gatsby-transformer-cloudinary cloudName: cloudName, publicId: media.public_id, originalHeight: media.height, originalWidth: media.width, originalFormat: media.format, // Keep all original data around cloudinaryData: media, // Generated urls url: url, secure_url: secureUrl, // Internal internal: { type: NODE_TYPE, content: JSON.stringify(media), contentDigest: createContentDigest(media), }, }; }; const createCloudinaryNodes = async ( gatsbyUtils, cloudinary, resourceOptions, cloudName, cname, secureDistribution, privateCdn, ) => { const { actions, reporter } = gatsbyUtils; const { max_results, results_per_page } = resourceOptions; let nextCursor = null; let limit = max_results; let resultsPerPage = results_per_page; do { try { const result = await cloudinary.api.resources({ ...resourceOptions, max_results: limit < resultsPerPage ? limit : resultsPerPage, next_cursor: nextCursor, }); result.resources.forEach((resource) => { const nodeData = getNodeData( gatsbyUtils, resource, cloudName, cname, secureDistribution, privateCdn, ); actions.createNode(nodeData); }); if (result.resources.length === 0) { reporter.warn( `${REPORTER_PREFIX}: No Cloudinary resources found. Try a different query?`, ); } else { reporter.info( `${REPORTER_PREFIX}: Added ${result.resources.length} ${NODE_TYPE} nodes(s)`, ); } nextCursor = result.next_cursor; limit = limit - result.resources.length; } catch (error) { reporter.error( `${REPORTER_PREFIX}: Fetching Cloudinary resources failed.`, error.error || error, ); } } while (nextCursor && limit > 0); }; exports.sourceNodes = async (gatsbyUtils, pluginOptions) => { const { cloudName, cname, secureDistribution, privateCdn } = pluginOptions; const cloudinary = newCloudinary(pluginOptions); const resourceOptions = getResourceOptions(pluginOptions); await createCloudinaryNodes( gatsbyUtils, cloudinary, resourceOptions, cloudName, cname, secureDistribution, privateCdn, ); };