11import { createContext , useContext } from 'react'
22import pick from 'lodash/pick'
3+ import type { Response } from 'express'
34
45import type { BreadcrumbT } from '@/frame/components/page-header/Breadcrumbs'
56import type { FeatureFlags } from '@/frame/components/hooks/useFeatureFlags'
6- import type { SidebarLink } from '@/types'
7+ import type { ExtendedRequest , Permalink , SidebarLink } from '@/types'
78
89export type ProductT = {
910 external : boolean
@@ -106,7 +107,7 @@ export type MainContextT = {
106107 currentProduct ?: ProductT
107108 currentProductName : string
108109 currentProductTree ?: ProductTreeNode | null
109- currentLayoutName ?: string
110+ currentLayoutName ?: string | null
110111 currentVersion ?: string
111112 data : DataT
112113 enterpriseServerReleases : EnterpriseServerReleases
@@ -127,7 +128,7 @@ export type MainContextT = {
127128 applicableVersions : string [ ]
128129 docsTeamMetrics : string [ ] | null
129130 } | null
130- relativePath ?: string
131+ relativePath ?: string | null
131132 sidebarTree ?: ProductTreeNode | null
132133 status : number
133134 xHost ?: string
@@ -154,8 +155,8 @@ const DEFAULT_UI_NAMESPACES = [
154155 'cookbook_landing' ,
155156]
156157
157- export function addUINamespaces ( req : any , ui : UIStrings , namespaces : string [ ] ) {
158- const pool = req . context . site . data . ui
158+ export function addUINamespaces ( req : ExtendedRequest , ui : UIStrings , namespaces : string [ ] ) {
159+ const pool = req . context ! . site ! . data . ui
159160 for ( const namespace of namespaces ) {
160161 if ( ! ( namespace in pool ) ) {
161162 throw new Error (
@@ -168,22 +169,26 @@ export function addUINamespaces(req: any, ui: UIStrings, namespaces: string[]) {
168169 }
169170}
170171
171- export const getMainContext = async ( req : any , res : any ) : Promise < MainContextT > => {
172+ export const getMainContext = async (
173+ req : ExtendedRequest ,
174+ res : Response ,
175+ ) : Promise < MainContextT > => {
176+ const context = req . context !
172177 // Our current translation process adds 'ms.*' frontmatter properties to files
173178 // it translates including when data/ui.yml is translated. We don't use these
174179 // properties and their syntax (e.g. 'ms.openlocfilehash',
175180 // 'ms.sourcegitcommit', etc.) causes problems so just delete them.
176- if ( req . context . site . data . ui . ms ) {
177- delete req . context . site . data . ui . ms
181+ if ( context . site ! . data . ui . ms ) {
182+ delete context . site ! . data . ui . ms
178183 }
179184
180- const { page } = req . context
185+ const { page } = context
181186
182187 const documentType = page ? ( page . documentType as string ) : undefined
183188
184189 const ui : UIStrings = { }
185190 addUINamespaces ( req , ui , DEFAULT_UI_NAMESPACES )
186- if ( req . context . currentJourneyTrack ?. trackId ) {
191+ if ( context . currentJourneyTrack ?. trackId ) {
187192 addUINamespaces ( req , ui , [ 'journey_track_nav' ] )
188193 }
189194
@@ -197,65 +202,65 @@ export const getMainContext = async (req: any, res: any): Promise<MainContextT>
197202 // To know whether we need this key, we need to match this
198203 // with the business logic in `DeprecationBanner.tsx` which is as follows:
199204 if (
200- req . context . enterpriseServerReleases . releasesWithOldestDeprecationDate . includes (
201- req . context . currentRelease ,
205+ context . enterpriseServerReleases ! . releasesWithOldestDeprecationDate . includes (
206+ context . currentRelease as string ,
202207 )
203208 ) {
204209 reusables . enterprise_deprecation = {
205- version_was_deprecated : req . context . getDottedData (
210+ version_was_deprecated : context . getDottedData ! (
206211 'reusables.enterprise_deprecation.version_was_deprecated' ,
207- ) ,
208- version_will_be_deprecated : req . context . getDottedData (
212+ ) as string ,
213+ version_will_be_deprecated : context . getDottedData ! (
209214 'reusables.enterprise_deprecation.version_will_be_deprecated' ,
210- ) ,
211- deprecation_details : req . context . getDottedData (
215+ ) as string ,
216+ deprecation_details : context . getDottedData ! (
212217 'reusables.enterprise_deprecation.deprecation_details' ,
213- ) ,
218+ ) as string ,
214219 }
215220 }
216221
217222 // This is a number, like 3.13 or it's possibly null if there is no
218223 // supported release candidate at the moment.
219- const { releaseCandidate } = req . context . enterpriseServerReleases
224+ const { releaseCandidate } = context . enterpriseServerReleases !
220225 // Combine the version number with the prefix so it can appear
221226 // as a full version string if the release candidate is set.
222227 const releaseCandidateVersion = releaseCandidate ? `enterprise-server@${ releaseCandidate } ` : null
223228
224229 const pageInfo =
225230 ( page && {
226231 documentType,
227- contentType : req . context . page . contentType || null ,
228- title : req . context . page . title ,
229- fullTitle : req . context . page . fullTitle || null ,
230- introPlainText : req . context . page ? .introPlainText || null ,
231- applicableVersions : req . context . page ? .permalinks . map ( ( obj : any ) => obj . pageVersion ) || [ ] ,
232- hidden : req . context . page . hidden || false ,
233- noEarlyAccessBanner : req . context . page . noEarlyAccessBanner || false ,
234- docsTeamMetrics : req . context . page . docsTeamMetrics || null ,
232+ contentType : page . contentType || null ,
233+ title : page . title ,
234+ fullTitle : page . fullTitle || null ,
235+ introPlainText : page . introPlainText || null ,
236+ applicableVersions : page . permalinks . map ( ( obj : Permalink ) => obj . pageVersion ) ,
237+ hidden : page . hidden || false ,
238+ noEarlyAccessBanner : page . noEarlyAccessBanner || false ,
239+ docsTeamMetrics : page . docsTeamMetrics || null ,
235240 } ) ||
236241 null
237242
238- const currentProduct : ProductT = req . context . productMap [ req . context . currentProduct ] || null
239- const currentProductName : string = req . context . currentProductName || ''
243+ const currentProduct = ( context . productMap ?. [ context . currentProduct || '' ] || null ) as ProductT
244+ const currentProductName : string = context . currentProductName || ''
240245
241246 const props : MainContextT = {
242- allVersions : minimalAllVersions ( req . context . allVersions ) ,
243- breadcrumbs : req . context . breadcrumbs || { } ,
244- communityRedirect : req . context . page ?. communityRedirect || { } ,
245- currentCategory : req . context . currentCategory || '' ,
246- currentLayoutName : req . context . currentLayoutName || null ,
247- currentPathWithoutLanguage : req . context . currentPathWithoutLanguage ,
247+ allVersions : minimalAllVersions ( context . allVersions ! ) ,
248+ breadcrumbs : ( context . breadcrumbs || { } ) as MainContextT [ 'breadcrumbs' ] ,
249+ communityRedirect : ( context . page ?. communityRedirect || { } ) as MainContextT [ 'communityRedirect' ] ,
250+ currentCategory : context . currentCategory || '' ,
251+ currentLayoutName : context . currentLayoutName || null ,
252+ currentPathWithoutLanguage : context . currentPathWithoutLanguage ! ,
248253 currentProduct,
249254 currentProductName,
250- // This is a slimmed down version of `req. context.currentProductTree`
255+ // This is a slimmed down version of `context.currentProductTree`
251256 // that only has the minimal titles stuff needed for sidebars and
252257 // any page that is hidden is omitted.
253258 // However, it's not needed on most pages. For example, on article pages,
254259 // you don't need it. It's similar to the minimal product tree but,
255260 // has the full length titles and not just the short titles.
256261 currentProductTree :
257- ( includeFullProductTree && req . context . currentProductTreeTitlesExcludeHidden ) || null ,
258- currentVersion : req . context . currentVersion ,
262+ ( includeFullProductTree && context . currentProductTreeTitlesExcludeHidden ) || null ,
263+ currentVersion : context . currentVersion ,
259264 data : {
260265 ui,
261266 reusables,
@@ -265,24 +270,24 @@ export const getMainContext = async (req: any, res: any): Promise<MainContextT>
265270 } ,
266271 } ,
267272 } ,
268- enterpriseServerReleases : pick ( req . context . enterpriseServerReleases , [
273+ enterpriseServerReleases : pick ( context . enterpriseServerReleases ! , [
269274 'isOldestReleaseDeprecated' ,
270275 'oldestSupported' ,
271276 'nextDeprecationDate' ,
272277 'supported' ,
273278 'releasesWithOldestDeprecationDate' ,
274- ] ) ,
275- enterpriseServerVersions : req . context . enterpriseServerVersions ,
276- error : req . context . error ? req . context . error . toString ( ) : '' ,
279+ ] ) as EnterpriseServerReleases ,
280+ enterpriseServerVersions : context . enterpriseServerVersions ! ,
281+ error : context . error ? context . error . toString ( ) : '' ,
277282 featureFlags : { } ,
278283 fullUrl : `${ req . protocol } ://${ req . hostname } ${ req . originalUrl } ` , // does not include port for localhost
279- isHomepageVersion : req . context . page ?. documentType === 'homepage' ,
280- nonEnterpriseDefaultVersion : req . context . nonEnterpriseDefaultVersion ,
281- page : pageInfo ,
282- relativePath : req . context . page ?. relativePath || null ,
284+ isHomepageVersion : context . page ?. documentType === 'homepage' ,
285+ nonEnterpriseDefaultVersion : context . nonEnterpriseDefaultVersion ! ,
286+ page : pageInfo as MainContextT [ 'page' ] ,
287+ relativePath : context . page ?. relativePath || null ,
283288 // The minimal product tree is needed on all pages that depend on
284289 // the product sidebar or the rest sidebar.
285- sidebarTree : ( includeSidebarTree && req . context . sidebarTree ) || null ,
290+ sidebarTree : ( includeSidebarTree && context . sidebarTree ) || null ,
286291 status : res . statusCode ,
287292 xHost : req . get ( 'x-host' ) || '' ,
288293 }
0 commit comments