import { join } from 'path' ; import { outputJSON , pathExists } from 'fs-extra' ; import { sourceStoreCollectionNode } from '@vtex/gatsby-source-vtex' ; import type { JSONSchema6 } from 'json-schema' ; import type { CreatePagesArgs , SourceNodesArgs , PluginOptionsSchemaArgs , CreateNodeArgs , } from 'gatsby' ; import type { StoreCollection } from '@vtex/gatsby-source-vtex' ; import { Barrier } from './utils/barrier' ; import { fetchAllNodes as fetchAllRemoteNodes } from './node-api/cms/fetchNodes' ; import { createSchemaCustomization as createCmsSchemaCustomization , sourceNode as sourceCmsNode , } from './node-api/cms/sourceNode' ; import { fetchAllNodes as fetchAllLocalNodes } from './node-api/cms/sourceLocalNodes' ; import { getCollectionRemoteId , getCollectionsFromPageContent , splitCollections , } from './node-api/catalog' ; import type { WithPLP } from './node-api/catalog/index' ; import type { BuilderConfig } from './index' ; import type { ICategoryCollection , IClusterCollection , IBrandCollection , } from './native-types/blocks/collection' ; interface CMSContentType { id : string ; name : string ; configurationSchemaSets : Array < { name : string ; configurations : Array < { name : string ; schema : JSONSchema6 ; } > ; } > ; } interface CMSBuilderConfig { id : 'faststore' ; productionBaseUrl : string ; } const { name } = require ( './package.json' ) ; const root = process . cwd ( ) ; const BUILDER_CONFIG_PATH = join ( root , 'public/page-data/_cms/builderConfig.json' ) ; const CONTENT_TYPES_PATH = join ( root , 'public/page-data/_cms/content-types.json' ) ; const SECTIONS_PATH = join ( root , 'public/page-data/_cms/sections.json' ) ; const TRANSLATION_KEYS_PATH = join ( root , 'public/page-data/_cms/translation-keys.json' ) ; const SHADOWED_INDEX_PATH = join ( root , 'src' , name , 'index.ts' ) ; export interface Options { tenant : string ; workspace : string ; environment : 'vtexcommercestable' | 'vtexcommercebeta' ; itemsPerPage ? : number ; preview ? : boolean ; } export const pluginOptionsSchema = ( { Joi } ) => Joi . object ( { tenant : Joi . string ( ) . required ( ) , workspace : Joi . string ( ) . required ( ) , environment : Joi . string ( ) . required ( ) . valid ( 'vtexcommercestable' , 'vtexcommercebeta' ) , itemsPerPage : Joi . number ( ) , preview : Joi . boolean ( ) , } ) ; interface CollectionsByType { Category : Record < string , WithPLP < ICategoryCollection > > ; Department : Record < string , WithPLP < ICategoryCollection > > ; Cluster : Record < string , WithPLP < IClusterCollection > > ; Brand : Record < string , WithPLP < IBrandCollection > > ; } const overridesBarrier = new Barrier < CollectionsByType > ( ) ; export const sourceNodes = async ( gatsbyApi , options ) => { const nodes = await Promise . all ( [ fetchAllRemoteNodes ( gatsbyApi , options ) , fetchAllLocalNodes ( gatsbyApi ) , ] ) . then ( ( [ x , y ] ) => [ ... x , ... y ] . filter ( Boolean ) ) ; createCmsSchemaCustomization ( gatsbyApi , nodes ) ; for ( const node of nodes ) { sourceCmsNode ( gatsbyApi , node ) ; } /**
     * Add CMS overrides to StoreCollection Nodes
     */ const collections = getCollectionsFromPageContent ( gatsbyApi , nodes ) ; const splitted = splitCollections ( collections ) ; overridesBarrier . set ( { Category : splitted . categories , Department : splitted . categories , Brand : splitted . brands , Cluster : splitted . clusters , } ) ; /**
     * Source StoreCollection from clusters. This part isn't done in
     * gatsby-source-vtex because collections do not have a defined
     * path on the store
     */ for ( const cluster of Object . values ( splitted . clusters ) ) { const node = { id : `${ cluster . clusterId }:${ cluster . seo . slug }` , remoteId : getCollectionRemoteId ( cluster ) , slug : cluster . seo . slug , seo : { title : cluster . seo . title , description : cluster . seo . description , } , type : 'Cluster' , meta : { selectedFacets : [ { key : 'productClusterIds' , value : cluster . clusterId } , ] , } , } ; sourceStoreCollectionNode ( gatsbyApi , node ) ; } } ; description export const onCreateNode = async ( gatsbyApi , { itemsPerPage = 12 } ) => { const { node } = gatsbyApi ; if ( node . internal . type !== 'StoreCollection' ) { return ; } const collection = ( node as unknown ) as StoreCollection ; const overrides = await overridesBarrier . get ( ) ; const override = overrides [ collection . type ] [ collection . remoteId ] ; gatsbyApi . actions . createNodeField ( { node , name : 'searchParams' , value : { sort : override ?. sort === '""' ? '' : override ?. sort ?? '' , itemsPerPage , selectedFacets : collection . meta . selectedFacets , } , } ) ; gatsbyApi . actions . createNodeField ( { node , name : `plp___NODE` , value : override ?. plp ?? null , } ) ; } ; export const createPages = async ( { graphql , reporter } ) => { const { data , errors } = await graphql ( `
    {
      site {
        siteMetadata {
          siteUrl
        }
      }
    }
  ` ) ; if ( errors && errors . length > 0 ) { reporter . panicOnBuild ( 'Seomething went wrong while querying site metadata' , errors ) ; } const { site : { siteMetadata : { siteUrl } , } , } = data as any ; const exists = await pathExists ( SHADOWED_INDEX_PATH ) ; if ( ! exists ) { return ; } require ( '@babel/register' ) ( { extensions : [ '.ts' ] , presets : [ '@babel/preset-typescript' ] , } ) ; const { builderConfig : { messages = { } , blocks : userBlocks = { } , contentTypes : userContentTypes = { } , } = { } , } = require ( SHADOWED_INDEX_PATH ) as { builderConfig : BuilderConfig ; } ; const blocks = Object . keys ( userBlocks ) . map ( ( blockName ) => ( { name : blockName , schema : userBlocks [ blockName ] , } ) ) ; const contentTypes = Object . keys ( userContentTypes ) . reduce ( ( acc , contentTypeId ) => { const contentType = userContentTypes [ contentTypeId ] ; const configurationSchemaSets = Object . keys ( contentType . extraBlocks ) . map ( ( sectionName ) => ( { name : sectionName , configurations : Object . keys ( contentType . extraBlocks [ sectionName ] ) . map ( ( blockName ) => ( { name : blockName , schema : contentType . extraBlocks [ sectionName ] [ blockName ] , } ) ) , } ) ) ; acc . push ( { id : contentTypeId , name : contentType . name , configurationSchemaSets , } ) ; return acc ; } , [ ] as CMSContentType [ ] ) ; const builderConfig = { id : 'faststore' , productionBaseUrl : siteUrl , } ; Promise . all ( [ outputJSON ( SECTIONS_PATH , blocks ) , outputJSON ( TRANSLATION_KEYS_PATH , messages ) , outputJSON ( CONTENT_TYPES_PATH , contentTypes ) , outputJSON ( BUILDER_CONFIG_PATH , builderConfig ) , ] ) ; } ;