UNPKG

@prg/gatsby-source-something-whatever

Version:

something something whatever who gives a crap.

265 lines (229 loc) 6.5 kB
import pluralize from 'pluralize'; import camelCase from 'lodash.camelcase'; import createNodeHelpers from 'gatsby-node-helpers'; import { formatMsg, convertId } from './util'; import { TYPE_PREFIX, IMAGE, PRODUCT, PRODUCT_VARIANT, PRODUCT_OPTION, PRODUCT_OPTION_VALUE, } from './constants'; import { IMAGES_QUERY, PRODUCTS_QUERY, PRODUCT_VARIANTS_QUERY, PRODUCT_OPTIONS_QUERY, PRODUCT_OPTION_VALUES_QUERY, } from './queries'; const { createNodeFactory } = createNodeHelpers({ typePrefix: TYPE_PREFIX, conflictFieldPrefix: 'platform', }); const byPosition = ({ position: positionA }, { position: positionB }) => positionA - positionB; const byId = TYPE => ({ id }) => convertId(id, TYPE); const getSelectedOptions = variant => variant.selectedOptions.reduce((acc, { title, value }) => ({ ...acc, [title]: value }), {}); const productMiddleware = node => { const { id, available, title, handle, description, type, parent, children, internal, } = node; const foreignIds = node.shopifyProductIds.map(({ id }) => id); const metadata = node.metadata === null ? {} : node.metadata; const images = node.images.map(byId(IMAGE)); const options = node.options .sort(byPosition) .map(byId(PRODUCT_OPTION)); const optionValues = node.options.reduce((acc, { title, values }) => ({ ...acc, [title]: values .sort(byPosition) .map(value => value.title), }), {}); const variants = node.variants .sort((a, b) => { try { const A = getSelectedOptions(a); const B = getSelectedOptions(b); if (A.Color === B.Color && A.Size !== B.Size) { return optionValues.Size.indexOf(A.Size) - optionValues.Size.indexOf(B.Size); } return optionValues.Color.indexOf(A.Color) - optionValues.Color.indexOf(B.Color); } catch (error) { return 0; } }); const featuredImage = (variants[0].images.length) ? convertId(variants[0].images[0].id, IMAGE) : images[0] return { id, available, title, handle, description, type, foreignIds, metadata, featuredImage___NODE: featuredImage, options___NODE: options, images___NODE: images, optionValues, variants___NODE: variants.map(({ id }) => convertId(id, PRODUCT_VARIANT)), parent, children, internal, } }; const productVariantMiddleware = node => { const { id, title, available, inventory, foreignId, productForeignId, foreignProductHandle, foreignProductPublishedAt, price, compareAtPrice, metadata, parent, children, internal, } = node; const productId = convertId(node.productId, PRODUCT); const product = productId; const selectedOptions = getSelectedOptions(node); const firstImage = node.images.find(({ position }) => position === 1); const secondImage = node.images.find(({ position }) => position === 2); const image = firstImage ? convertId(firstImage.id, IMAGE) : null; const hoverImage = secondImage ? convertId(secondImage.id, IMAGE) : null; const images = node.images.map(byId(IMAGE)); return { id, title, available, inventory, foreignId, productForeignId, foreignProductHandle, foreignProductPublishedAt, price, compareAtPrice, product___NODE: product, productId, images___NODE: images, image___NODE: image, hoverImage___NODE: hoverImage, selectedOptions, metadata, parent, children, internal, } }; const imageMiddleware = node => { const { id, src, altText, parent, children, internal } = node; if (node.variants && node.variants.length) { const { variant: firstVariant } = node.variants && node.variants[0]; const match = firstVariant.images.find(({ id }) => id === node.platformId) || {}; const position = match.position || null; const product = convertId(firstVariant.productId, PRODUCT); const variants = node.variants .map(({ id }) => convertId(id, PRODUCT_VARIANT)); return { id, src, altText, position, product___NODE: product, variants___NODE: variants, parent, children, internal, }; } if (node.product) { return { id, src, altText, position: node.product.position || null, product___NODE: convertId(node.product.id, PRODUCT), variants___NODE: [], parent, children, internal, }; } return { id, src, altText, position: null, product___NODE: null, variants___NODE: [], parent, children, internal, }; }; const optionMiddleware = node => { const productId = convertId(node.productId, PRODUCT); const product = productId; const values = node.values .sort(byPosition) .map(byId(PRODUCT_OPTION_VALUE)) return { ...node, productId, product___NODE: product, values, }; }; const types = [ { name: IMAGE, query: IMAGES_QUERY, middleware: imageMiddleware }, { name: PRODUCT, query: PRODUCTS_QUERY, middleware: productMiddleware }, { name: PRODUCT_VARIANT, query: PRODUCT_VARIANTS_QUERY, middleware: productVariantMiddleware }, { name: PRODUCT_OPTION, query: PRODUCT_OPTIONS_QUERY, middleware: optionMiddleware }, { name: PRODUCT_OPTION_VALUE, query: PRODUCT_OPTION_VALUES_QUERY }, ]; const getTypeData = async (types, client, shopId) => { const queries = types.map(({ name, query, middleware = node => node }) => { const factory = createNodeFactory(name, middleware); const normalizedName = camelCase(pluralize(name)); return client.query({ query, variables: { shopId } }) .then(({ data }) => { return ({ name, nodes: data[normalizedName].map(item => factory(item)) }) }); }); const typeData = await Promise.all(queries); return typeData .reduce((acc, {name, nodes}) => ({ ...acc, [name]: nodes }), {}); }; export const createContentNodes = async (client, shopId, { actions: { createNode }}) => { try { const typeData = await getTypeData(types, client, shopId); const createdNodes = Object.entries(typeData).map(([type, nodes]) => { console.log(formatMsg(`Created ${nodes.length} ${TYPE_PREFIX}${type} nodes.`)); return nodes.map(node => createNode(node)); }); await Promise.all(createdNodes); return typeData; } catch (error) { console.log('error', error); } };