Skip to content

Instantly share code, notes, and snippets.

@TimoWestland
Created February 22, 2021 13:20
Show Gist options
  • Save TimoWestland/14bba939ae4b133ebe939466386dbb46 to your computer and use it in GitHub Desktop.
Save TimoWestland/14bba939ae4b133ebe939466386dbb46 to your computer and use it in GitHub Desktop.
import { Configuration, initialize } from '@bloomreach/spa-sdk'
import { BrPage, BrVisitor } from '../types'
import { brHttpClient as httpClient } from '../utils'
type Request = Configuration['request']
type HttpConnection = Request['connection']
export type Options = {
/**
* We need to pass some headers for the initialize function to work.
* Pass trough all headers from the Request object.
*/
headers?: Record<string, string | string[] | undefined>
/**
* HttpConnection string, required from Bloomreach Relevance module to retrieve IP address of user
*/
connection?: HttpConnection
/**
* Visitor object required for Bloomreach Relevance to personalize the page model response
*/
visitor?: BrVisitor
/**
* Whether the URL rewriter is disabled within the CMS.
* This is the case for old < 14.2 version of Bloomreach.
* When deploying newer versions of Bloomreach (14.3+) this will be set to true trough ENV settings
*/
disableUrlRewriter?: boolean
/**
* When "disableUrlRewriter" is set to false, we need the sessionId added to the cookies
* by Bloomreach when the site is is requested from the CMS in preview mode.
*/
legacySessionId?: string
}
// Key for session ID cookie for legacy implementation (using url rewriter)
export const SESSION_COOKIE = 'JSESSIONID'
export async function getPageModel(apiUrl: string, path: string, opts: Options): Promise<BrPage> {
const { headers = {}, connection, visitor, disableUrlRewriter = false, legacySessionId } = opts
if (!apiUrl) {
throw new Error(`Need a valid Bloomreach api url to fetch a pageModel! Got: ${String(apiUrl)}`)
}
if (!path) {
throw new Error(`Need a valid path to fetch a pageModel! Got: ${String(path)}`)
}
// When the URL rewriter is enabled, we need to initialize the "legacy" way
if (!disableUrlRewriter) {
return legacyInitialize(apiUrl, path, legacySessionId)
}
const request: Request = {
path,
connection,
headers: {
...(headers['x-forwarded-for'] ? { 'x-forwarded-for': headers['x-forwarded-for'] } : {}),
},
}
const configuration: Configuration = {
cmsBaseUrl: apiUrl,
visitor,
request,
httpClient,
}
if (process.env.NODE_ENV !== 'production') {
console.log(`Fetching: ${apiUrl}/resourceapi${path}`)
}
return initialize(configuration)
}
/**
* The initialize function from the SDK does not support Bloomreach 14.0.0 and older.
* Hence we need to make do a plain fetch to the API when we're still using the old version
* of bloomreach in combination with the URL rewriter.
*
* To avoid having to duplicate more code, we create an object that is similar to the object
* that the "initialize" function from the SDK returns.
*/
async function legacyInitialize(apiUrl: string, path: string, sessionId?: string): Promise<BrPage> {
const url = `${apiUrl}/resourceapi${path}`
if (process.env.NODE_ENV !== 'production') {
console.log(`Legacy] Fetching: ${url}`)
}
try {
const res = await fetch(url, {
method: 'GET',
// To authenticate the api call in preview mode we need to forward the JSESSIONID cookie
// that bloomreach adds to the request made in preview mode
headers: sessionId !== undefined ? { Cookie: `${SESSION_COOKIE}=${sessionId}` } : {},
})
const pageModel = await res.json()
return {
toJSON: () => pageModel,
// eslint-disable-next-line @typescript-eslint/no-empty-function
getVisitor: () => {},
} as BrPage
} catch (err) {
console.error(`[Legacy] Failed to initialize pageModel.`, err)
return {} as BrPage
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment