Merge branch 'master' into feature/tracking

This commit is contained in:
Linus Flood
2024-11-11 15:47:30 +01:00
253 changed files with 3837 additions and 2268 deletions

View File

@@ -1,6 +1,5 @@
import "server-only"
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
import { ClientError, GraphQLClient } from "graphql-request"
import { Lang } from "@/constants/languages"
@@ -20,51 +19,38 @@ export async function request<T>(
client.setHeaders({
access_token: env.CMS_ACCESS_TOKEN,
"Content-Type": "application/json",
...params?.headers,
})
const previewHash = ContentstackLivePreview.hash
if (previewHash) {
client.setEndpoint(env.CMS_PREVIEW_URL)
client.setHeader("preview_token", env.CMS_PREVIEW_TOKEN)
client.setHeader("live_preview", previewHash)
} else {
if (params?.cache) {
client.requestConfig.cache = params.cache
}
if (params?.headers) {
client.requestConfig.headers = params.headers
}
if (params?.next) {
client.requestConfig.next = params.next
}
client.requestConfig.cache = params?.cache
client.requestConfig.next = params?.next
if (env.PRINT_QUERY) {
const print = (await import("graphql/language/printer")).print
const rawResponse = await client.rawRequest<T>(
print(query as DocumentNode),
variables,
{
access_token: env.CMS_ACCESS_TOKEN,
"Content-Type": "application/json",
}
)
/**
* TODO: Send to Monitoring (Logging and Metrics)
*/
console.log({
complexityLimit: rawResponse.headers.get("x-query-complexity"),
})
console.log({
referenceDepth: rawResponse.headers.get("x-reference-depth"),
})
console.log({
resolverCost: rawResponse.headers.get("x-resolver-cost"),
})
return {
data: rawResponse.data,
if (env.PRINT_QUERY) {
const print = (await import("graphql/language/printer")).print
const rawResponse = await client.rawRequest<T>(
print(query as DocumentNode),
variables,
{
access_token: env.CMS_ACCESS_TOKEN,
"Content-Type": "application/json",
}
)
/**
* TODO: Send to Monitoring (Logging and Metrics)
*/
console.log({
complexityLimit: rawResponse.headers.get("x-query-complexity"),
})
console.log({
referenceDepth: rawResponse.headers.get("x-reference-depth"),
})
console.log({
resolverCost: rawResponse.headers.get("x-resolver-cost"),
})
return {
data: rawResponse.data,
}
}

View File

@@ -7,14 +7,15 @@ import { request as _request } from "./_request"
import { Data } from "@/types/request"
const client = new GraphQLClient(env.CMS_URL, {
fetch: fetch,
})
export async function edgeRequest<T>(
query: string | DocumentNode,
variables?: {},
params?: RequestInit
): Promise<Data<T>> {
// Creating a new client for each request to avoid conflicting parameters
const client = new GraphQLClient(env.CMS_URL, {
fetch: fetch,
})
return _request(client, query, variables, params)
}

View File

@@ -1,42 +0,0 @@
import "server-only"
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
import { request as graphqlRequest } from "graphql-request"
import { env } from "@/env/server"
import type { DocumentNode } from "graphql"
import type { Data } from "@/types/request"
export async function previewRequest<T>(
query: string | DocumentNode,
variables?: {}
): Promise<Data<T>> {
try {
const hash = ContentstackLivePreview.hash
if (!hash) {
throw new Error("No hash received")
}
const headers = new Headers({
access_token: env.CMS_ACCESS_TOKEN,
preview_token: env.CMS_PREVIEW_TOKEN,
live_preview: hash,
})
const response = await graphqlRequest<T>({
document: query,
requestHeaders: headers,
url: env.CMS_PREVIEW_URL,
variables,
})
return { data: response }
} catch (error) {
console.error("Error in preview graphql request")
console.error(error)
throw new Error("Something went wrong")
}
}

View File

@@ -4,30 +4,49 @@ import { GraphQLClient } from "graphql-request"
import { cache } from "react"
import { env } from "@/env/server"
import { getPreviewHash, isPreviewByUid } from "@/lib/previewContext"
import { request as _request } from "./_request"
import { Data } from "@/types/request"
const client = new GraphQLClient(env.CMS_URL, {
fetch: cache(async function (
url: URL | RequestInfo,
params: RequestInit | undefined
) {
const wrappedFetch = fetchRetry(fetch, {
retries: 3,
retryDelay: function (attempt, error, response) {
return Math.pow(2, attempt) * 150 // 150, 300, 600
},
})
return wrappedFetch(url, params)
}),
})
export async function request<T>(
query: string | DocumentNode,
variables?: {},
variables?: Record<string, any>,
params?: RequestInit
): Promise<Data<T>> {
return _request(client, query, variables, params)
const shouldUsePreview = variables?.uid
? isPreviewByUid(variables.uid)
: false
const previewHash = getPreviewHash()
const cmsUrl = shouldUsePreview ? env.CMS_PREVIEW_URL : env.CMS_URL
// Creating a new client for each request to avoid conflicting parameters
const client = new GraphQLClient(cmsUrl, {
fetch: cache(async function (url: URL | RequestInfo, params?: RequestInit) {
const wrappedFetch = fetchRetry(fetch, {
retries: 3,
retryDelay: function (attempt, error, response) {
return Math.pow(2, attempt) * 150 // 150, 300, 600
},
})
return wrappedFetch(url, params)
}),
})
const mergedParams =
shouldUsePreview && previewHash
? {
...params,
headers: {
...params?.headers,
live_preview: previewHash,
preview_token: env.CMS_PREVIEW_TOKEN,
},
cache: undefined,
next: undefined,
}
: params
return _request(client, query, variables, mergedParams)
}

42
lib/previewContext.ts Normal file
View File

@@ -0,0 +1,42 @@
import { cache } from "react"
interface PreviewData {
hash: string
uid: string
}
const getRef = cache((): { current?: PreviewData } => ({
current: undefined,
}))
/**
* Set the preview hash for the current request
*
* It works kind of like React's context,
* but on the server side, per request.
*
* @param hash
*/
export function setPreviewData(data?: PreviewData) {
getRef().current = data
}
/**
* Get the preview hash set for the current request
*/
export function getPreviewHash() {
return getRef().current?.hash
}
/**
* Check if the current request is a preview by comparing the uid
*/
export function isPreviewByUid(uid: string) {
const data = getRef().current
if (data?.hash) {
return data.uid === uid
}
return false
}

View File

@@ -143,3 +143,9 @@ export const getBreakfastPackages = cache(async function getMemoizedPackages(
) {
return serverClient().hotel.packages.breakfast(input)
})
export const getBookingConfirmation = cache(
function getMemoizedBookingConfirmation(confirmationNumber: string) {
return serverClient().booking.confirmation({ confirmationNumber })
}
)