-
Notifications
You must be signed in to change notification settings - Fork 26k
/
api.ts
207 lines (170 loc) · 5.55 KB
/
api.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
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 {
public preview: any
public client: any
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,
}
}