import agility from '@agility/content-fetch' import { CMS_LANG, CMS_CHANNEL } from './constants' import { asyncForEach } from './utils' export { validatePreview } from './preview' import { normalizePosts } from './normalize' import { requireComponentDependancyByName } from './dependancies' // Our LIVE API client const liveClient = agility.getApi({ guid: process.env.AGILITY_CMS_GUID, apiKey: process.env.AGILITY_CMS_API_FETCH_KEY, }) // Our PREVIEW API client const previewClient = agility.getApi({ guid: process.env.AGILITY_CMS_GUID, apiKey: process.env.AGILITY_CMS_API_PREVIEW_KEY, isPreview: true, }) export const getClient = (preview = false) => preview ? previewClient : liveClient // This client is used by nested components to fetch additional data within `getStaticProps` export class APIClient { constructor({ preview = false }) { this.preview = preview this.client = getClient(preview) } async getAllPosts(take) { const data = await this.client.getContentList({ referenceName: `posts`, languageCode: CMS_LANG, contentLinkDepth: 1, take: take, // TODO: Implement pagination }) return data.items } async getLatestPost() { const data = await this.getAllPosts(1) const normalizedPosts = normalizePosts(data) return normalizedPosts[0] || null } async getPostDetails({ contentID, preview }) { const post = await this.client.getContentItem({ contentID, languageCode: CMS_LANG, contentLinkDepth: 1, }) const normalizedPost = normalizePosts([post])[0] return normalizedPost } async getPostsForMoreStories({ postToExcludeContentID }) { let allPosts = await this.getAllPosts(5) //if we don't have a post to exclude, assume we should exclude the latest one if (postToExcludeContentID < 0) { allPosts.shift() } const postsLessThisPost = allPosts.filter((p) => { return p.contentID !== postToExcludeContentID }) const normalizedMorePosts = normalizePosts(postsLessThisPost) return normalizedMorePosts } } export async function getAgilityPaths() { console.log(`Agility CMS => Fetching sitemap for getAgilityPaths...`) const sitemapFlat = await getClient().getSitemapFlat({ channelName: CMS_CHANNEL, languageCode: CMS_LANG, }) //returns an array of paths as a string (i.e. ['/home', '/posts'] //skips folders... const paths = Object.keys(sitemapFlat) .filter((s) => sitemapFlat[s].isFolder !== true) .map((s) => { return s }) return paths } export async function getAgilityPageProps({ params, preview }) { //determine if we are in preview mode const client = getClient(preview) let path = '/' if (params) { //build path by iterating through slugs path = '' params.slug.forEach((slug) => { path += '/' + slug }) } console.log(`Agility CMS => Getting page props for '${path}'...`) //get sitemap const sitemap = await client.getSitemapFlat({ channelName: CMS_CHANNEL, languageCode: CMS_LANG, }) let pageInSitemap = sitemap[path] let page = null if (path === '/') { let firstPagePathInSitemap = Object.keys(sitemap)[0] pageInSitemap = sitemap[firstPagePathInSitemap] } if (pageInSitemap) { //get the page page = await client.getPage({ pageID: pageInSitemap.pageID, languageCode: CMS_LANG, contentLinkDepth: 1, }) } else { //Could not find page console.error('page [' + path + '] not found in sitemap.') return } if (!page) { console.error('page [' + path + '] not found in getpage method.') return } //resolve the page template let pageTemplateName = page.templateName.replace(/[^0-9a-zA-Z]/g, '') //resolve the modules per content zone await asyncForEach(Object.keys(page.zones), async (zoneName) => { let modules = [] //grab the modules for this content zone const modulesForThisContentZone = page.zones[zoneName] //loop through the zone's modules await asyncForEach(modulesForThisContentZone, async (moduleItem) => { let ModuleComponentToRender = requireComponentDependancyByName( moduleItem.module ) if (ModuleComponentToRender) { //resolve any additional data for the modules let moduleData = null if (ModuleComponentToRender.getCustomInitialProps) { //we have some additional data in the module we'll need, execute that method now, so it can be included in SSG console.log( `Agility CMS => Fetching additional data via getCustomInitialProps for ${moduleItem.module}...` ) moduleData = await ModuleComponentToRender.getCustomInitialProps({ client: new APIClient({ preview }), item: moduleItem.item, languageCode: CMS_LANG, channelName: CMS_CHANNEL, pageInSitemap: pageInSitemap, }) } //if we have additional module data, then overwrite our props that will be sent to the module if (moduleData != null) { moduleItem.item = moduleData } modules.push({ moduleName: moduleItem.module, item: moduleItem.item, }) } else { console.error( `No react component found for the module "${moduleItem.module}". Cannot render module.` ) } }) //store as dictionary page.zones[zoneName] = modules }) return { sitemapNode: pageInSitemap, page: page, pageTemplateName: pageTemplateName, languageCode: CMS_LANG, channelName: CMS_CHANNEL, } }