diff --git a/components/Footer/index.tsx b/components/Footer/index.tsx
index 83c5aa7d7..ee11328ba 100644
--- a/components/Footer/index.tsx
+++ b/components/Footer/index.tsx
@@ -1,15 +1,11 @@
import { serverClient } from "@/lib/trpc/server"
-import { getLang } from "@/i18n/serverContext"
-
import FooterDetails from "./Details"
import FooterNavigation from "./Navigation"
export default async function Footer() {
- const footerData = await serverClient().contentstack.base.footer({
- lang: getLang(),
- })
const languages = await serverClient().contentstack.languageSwitcher.get()
+ const footerData = await serverClient().contentstack.base.footer()
if (!footerData || !languages) {
return
diff --git a/server/routers/contentstack/base/output.ts b/server/routers/contentstack/base/output.ts
index a9ab60805..37c1a3ea1 100644
--- a/server/routers/contentstack/base/output.ts
+++ b/server/routers/contentstack/base/output.ts
@@ -291,14 +291,12 @@ const validateInternalLink = z
})
.optional()
-const validateLinkItem = z.object({
+export const validateLinkItem = z.object({
open_in_new_tab: z.boolean(),
link: validateExternalLink,
pageConnection: validateInternalLink,
})
-export type FooterLinkItem = z.infer
-
export const validateFooterConfigSchema = z.object({
all_footer: z.object({
items: z.array(
@@ -333,9 +331,6 @@ export const validateFooterConfigSchema = z.object({
}),
})
-export type FooterDataRaw = z.infer
-export type FooterData = FooterDataRaw["all_footer"]["items"][0]
-
const pageConnectionRefs = z.object({
edges: z.array(
z.object({
@@ -350,7 +345,7 @@ const pageConnectionRefs = z.object({
),
})
-const validateFooterRefConfigSchema = z.object({
+export const validateFooterRefConfigSchema = z.object({
all_footer: z.object({
items: z.array(
z.object({
@@ -382,8 +377,6 @@ const validateFooterRefConfigSchema = z.object({
}),
})
-export type FooterRefDataRaw = z.infer
-
const linkConnectionNodeSchema = z
.object({
edges: z
diff --git a/server/routers/contentstack/base/query.ts b/server/routers/contentstack/base/query.ts
index a3affedfc..30a262a42 100644
--- a/server/routers/contentstack/base/query.ts
+++ b/server/routers/contentstack/base/query.ts
@@ -29,17 +29,24 @@ import {
CurrentHeaderData,
CurrentHeaderDataRaw,
CurrentHeaderRefDataRaw,
- FooterDataRaw,
- FooterRefDataRaw,
getHeaderRefSchema,
getHeaderSchema,
validateContactConfigSchema,
validateCurrentFooterConfigSchema,
validateCurrentHeaderConfigSchema,
validateFooterConfigSchema,
+ validateFooterRefConfigSchema,
} from "./output"
-import { getConnections, transformPageConnectionLinks } from "./utils"
+import {
+ getConnections,
+ getFooterConnections,
+ transformPageConnectionLinks,
+} from "./utils"
+import type {
+ FooterDataRaw,
+ FooterRefDataRaw,
+} from "@/types/components/footer/footer"
import type { HeaderRefResponse, HeaderResponse } from "@/types/header"
const meter = metrics.getMeter("trpc.contentstack.base")
@@ -90,6 +97,27 @@ const getHeaderSuccessCounter = meter.createCounter(
const getHeaderFailCounter = meter.createCounter(
"trpc.contentstack.header.get-fail"
)
+
+// OpenTelemetry metrics: CurrentHeader
+const getCurrentFooterRefCounter = meter.createCounter(
+ "trpc.contentstack.currentFooter.ref.get"
+)
+const getCurrentFooterRefSuccessCounter = meter.createCounter(
+ "trpc.contentstack.currentFooter.ref.get-success"
+)
+const getCurrentFooterRefFailCounter = meter.createCounter(
+ "trpc.contentstack.currentFooter.ref.get-fail"
+)
+const getCurrentFooterCounter = meter.createCounter(
+ "trpc.contentstack.currentFooter.get"
+)
+const getCurrentFooterSuccessCounter = meter.createCounter(
+ "trpc.contentstack.currentFooter.get-success"
+)
+const getCurrentFooterFailCounter = meter.createCounter(
+ "trpc.contentstack.currentFooter.get-fail"
+)
+
// OpenTelemetry metrics: Footer
const getFooterRefCounter = meter.createCounter(
"trpc.contentstack.footer.ref.get"
@@ -403,9 +431,9 @@ export const baseQueryRouter = router({
currentFooter: contentstackBaseProcedure
.input(langInput)
.query(async ({ input }) => {
- getFooterRefCounter.add(1, { lang: input.lang })
+ getCurrentFooterRefCounter.add(1, { lang: input.lang })
console.info(
- "contentstack.footer.ref start",
+ "contentstack.currentFooter.ref start",
JSON.stringify({ query: { lang: input.lang } })
)
const responseRef = await request(
@@ -421,9 +449,9 @@ export const baseQueryRouter = router({
}
)
// There's currently no error handling/validation for the responseRef, should it be added?
- getFooterCounter.add(1, { lang: input.lang })
+ getCurrentFooterCounter.add(1, { lang: input.lang })
console.info(
- "contentstack.footer start",
+ "contentstack.currentFooter start",
JSON.stringify({
query: {
lang: input.lang,
@@ -447,13 +475,13 @@ export const baseQueryRouter = router({
if (!response.data) {
const notFoundError = notFound(response)
- getFooterFailCounter.add(1, {
+ getCurrentFooterFailCounter.add(1, {
lang: input.lang,
error_type: "not_found",
error: JSON.stringify({ code: notFoundError.code }),
})
console.error(
- "contentstack.footer not found error",
+ "contentstack.currentFooter not found error",
JSON.stringify({
query: {
lang: input.lang,
@@ -464,142 +492,194 @@ export const baseQueryRouter = router({
throw notFoundError
}
- const validatedFooterConfig = validateCurrentFooterConfigSchema.safeParse(
- response.data
- )
+ const validatedCurrentFooterConfig =
+ validateCurrentFooterConfigSchema.safeParse(response.data)
- if (!validatedFooterConfig.success) {
+ if (!validatedCurrentFooterConfig.success) {
getFooterFailCounter.add(1, {
lang: input.lang,
error_type: "validation_error",
- error: JSON.stringify(validatedFooterConfig.error),
+ error: JSON.stringify(validatedCurrentFooterConfig.error),
})
console.error(
- "contentstack.footer validation error",
+ "contentstack.currentFooter validation error",
JSON.stringify({
query: { lang: input.lang },
- error: validatedFooterConfig.error,
+ error: validatedCurrentFooterConfig.error,
})
)
return null
}
- getFooterSuccessCounter.add(1, { lang: input.lang })
+ getCurrentFooterSuccessCounter.add(1, { lang: input.lang })
console.info(
- "contentstack.footer success",
+ "contentstack.currentFooter success",
JSON.stringify({ query: { lang: input.lang } })
)
- return validatedFooterConfig.data.all_current_footer.items[0]
+ return validatedCurrentFooterConfig.data.all_current_footer.items[0]
}),
- footer: contentstackBaseProcedure
- .input(langInput)
- .query(async ({ input }) => {
- getFooterRefCounter.add(1, { lang: input.lang })
- console.info(
- "contentstack.footer.ref start",
- JSON.stringify({ query: { lang: input.lang } })
- )
- const responseRef = await request(
- GetFooterRef,
- {
- locale: input.lang,
+ footer: contentstackBaseProcedure.query(async ({ ctx }) => {
+ const { lang } = ctx
+ getFooterRefCounter.add(1, { lang })
+ console.info(
+ "contentstack.footer.ref start",
+ JSON.stringify({ query: { lang } })
+ )
+ const responseRef = await request(
+ GetFooterRef,
+ {
+ locale: lang,
+ },
+ {
+ cache: "force-cache",
+ next: {
+ tags: [generateRefsResponseTag(lang, "footer")],
},
- {
- cache: "force-cache",
- next: {
- tags: [generateRefsResponseTag(input.lang, "footer")],
- },
- }
- )
+ }
+ )
- // There's currently no error handling/validation for the responseRef, should it be added?
- getFooterCounter.add(1, { lang: input.lang })
- console.info(
- "contentstack.footer start",
+ if (!responseRef.data) {
+ const notFoundError = notFound(responseRef)
+ getFooterRefFailCounter.add(1, {
+ lang,
+ error_type: "not_found",
+ error: JSON.stringify({ code: notFoundError.code }),
+ })
+ console.error(
+ "contentstack.footer.refs not found error",
JSON.stringify({
query: {
- lang: input.lang,
+ lang,
},
+ error: { code: notFoundError.code },
})
)
- const footerUID = responseRef.data.all_footer.items[0].system.uid
- const response = await request(
- GetFooter,
- {
- locale: input.lang,
+ throw notFoundError
+ }
+
+ const validatedFooterRefs = validateFooterRefConfigSchema.safeParse(
+ responseRef.data
+ )
+
+ if (!validatedFooterRefs.success) {
+ getFooterRefFailCounter.add(1, {
+ lang,
+ error_type: "validation_error",
+ error: JSON.stringify(validatedFooterRefs.error),
+ })
+ console.error(
+ "contentstack.footer.refs validation error",
+ JSON.stringify({
+ query: {
+ lang,
+ },
+ error: validatedFooterRefs.error,
+ })
+ )
+ return null
+ }
+
+ getFooterRefSuccessCounter.add(1, { lang })
+ console.info(
+ "contentstack.footer.refs success",
+ JSON.stringify({ query: { lang } })
+ )
+
+ const connections = getFooterConnections(validatedFooterRefs.data)
+ const footerUID = responseRef.data.all_footer.items[0].system.uid
+
+ // There's currently no error handling/validation for the responseRef, should it be added?
+ getFooterCounter.add(1, { lang: lang })
+ console.info(
+ "contentstack.footer start",
+ JSON.stringify({
+ query: {
+ lang,
},
- {
- cache: "force-cache",
- next: {
- tags: [generateTag(input.lang, footerUID)],
+ })
+ )
+ const tags = [
+ generateTags(lang, connections),
+ generateTag(lang, footerUID),
+ ].flat()
+
+ const response = await request(
+ GetFooter,
+ {
+ locale: lang,
+ },
+ {
+ cache: "force-cache",
+ next: {
+ tags,
+ },
+ }
+ )
+
+ if (!response.data) {
+ const notFoundError = notFound(response)
+ getFooterFailCounter.add(1, {
+ lang,
+ error_type: "not_found",
+ error: JSON.stringify({ code: notFoundError.code }),
+ })
+ console.error(
+ "contentstack.footer not found error",
+ JSON.stringify({
+ query: {
+ lang,
},
- }
- )
-
- if (!response.data) {
- const notFoundError = notFound(response)
- getFooterFailCounter.add(1, {
- lang: input.lang,
- error_type: "not_found",
- error: JSON.stringify({ code: notFoundError.code }),
- })
- console.error(
- "contentstack.footer not found error",
- JSON.stringify({
- query: {
- lang: input.lang,
- },
- error: { code: notFoundError.code },
- })
- )
- throw notFoundError
- }
-
- const validatedFooterConfig = validateFooterConfigSchema.safeParse(
- response.data
- )
-
- if (!validatedFooterConfig.success) {
- getFooterFailCounter.add(1, {
- lang: input.lang,
- error_type: "validation_error",
- error: JSON.stringify(validatedFooterConfig.error),
- })
- console.error(
- "contentstack.footer validation error",
- JSON.stringify({
- query: { lang: input.lang },
- error: validatedFooterConfig.error,
- })
- )
- return null
- }
- getFooterSuccessCounter.add(1, { lang: input.lang })
- console.info(
- "contentstack.footer success",
- JSON.stringify({ query: { lang: input.lang } })
- )
- const validatedFooterData = validatedFooterConfig.data.all_footer.items[0]
- const mainLinks = transformPageConnectionLinks(
- validatedFooterData.main_links
- )
-
- const secondaryLinks = validatedFooterData.secondary_links.map(
- (section) => ({
- title: section.title,
- links: transformPageConnectionLinks(section.links),
+ error: { code: notFoundError.code },
})
)
+ throw notFoundError
+ }
- const tertiaryLinks = transformPageConnectionLinks(
- validatedFooterData.tertiary_links
+ const validatedFooterConfig = validateFooterConfigSchema.safeParse(
+ response.data
+ )
+
+ if (!validatedFooterConfig.success) {
+ getFooterFailCounter.add(1, {
+ lang,
+ error_type: "validation_error",
+ error: JSON.stringify(validatedFooterConfig.error),
+ })
+ console.error(
+ "contentstack.footer validation error",
+ JSON.stringify({
+ query: { lang: lang },
+ error: validatedFooterConfig.error,
+ })
)
+ return null
+ }
+ getFooterSuccessCounter.add(1, { lang })
+ console.info(
+ "contentstack.footer success",
+ JSON.stringify({ query: { lang } })
+ )
+ const validatedFooterData = validatedFooterConfig.data.all_footer.items[0]
+ const mainLinks = transformPageConnectionLinks(
+ validatedFooterData.main_links
+ )
- return {
- mainLinks: mainLinks,
- appDownloads: validatedFooterData.app_downloads,
- secondaryLinks: secondaryLinks,
- socialMedia: validatedFooterData.social_media,
- tertiaryLinks: tertiaryLinks,
- }
- }),
+ const secondaryLinks = validatedFooterData.secondary_links.map(
+ (section) => ({
+ title: section.title,
+ links: transformPageConnectionLinks(section.links),
+ })
+ )
+
+ const tertiaryLinks = transformPageConnectionLinks(
+ validatedFooterData.tertiary_links
+ )
+
+ return {
+ mainLinks: mainLinks,
+ appDownloads: validatedFooterData.app_downloads,
+ secondaryLinks: secondaryLinks,
+ socialMedia: validatedFooterData.social_media,
+ tertiaryLinks: tertiaryLinks,
+ }
+ }),
})
diff --git a/server/routers/contentstack/base/utils.ts b/server/routers/contentstack/base/utils.ts
index 2493da1f4..83347bdb6 100644
--- a/server/routers/contentstack/base/utils.ts
+++ b/server/routers/contentstack/base/utils.ts
@@ -1,7 +1,10 @@
-import { HeaderRefResponse } from "@/types/header"
+import type {
+ FooterLinkItem,
+ FooterRefDataRaw,
+} from "@/types/components/footer/footer"
+import type { HeaderRefResponse } from "@/types/header"
import { Edges } from "@/types/requests/utils/edges"
import { NodeRefs } from "@/types/requests/utils/refs"
-import type { FooterLinkItem } from "./output"
export function getConnections(refs: HeaderRefResponse) {
const connections: Edges[] = []
@@ -40,6 +43,33 @@ export function getConnections(refs: HeaderRefResponse) {
return connections
}
+export function getFooterConnections(refs: FooterRefDataRaw) {
+ const connections: Edges[] = []
+ const footerData = refs.all_footer.items[0]
+ const mainLinks = footerData.main_links
+ const secondaryLinks = footerData.secondary_links
+ const tertiaryLinks = footerData.tertiary_links
+ if (mainLinks) {
+ mainLinks.forEach(({ pageConnection }) => {
+ connections.push(pageConnection)
+ })
+ }
+ secondaryLinks?.forEach(({ links }) => {
+ if (links) {
+ links.forEach(({ pageConnection }) => {
+ connections.push(pageConnection)
+ })
+ }
+ })
+ if (tertiaryLinks) {
+ tertiaryLinks.forEach(({ pageConnection }) => {
+ connections.push(pageConnection)
+ })
+ }
+
+ return connections
+}
+
export function transformPageConnectionLinks(links: FooterLinkItem[]) {
if (!links) return []
return links.flatMap((link) => {
diff --git a/types/components/footer/footer.ts b/types/components/footer/footer.ts
new file mode 100644
index 000000000..8df0eaf8a
--- /dev/null
+++ b/types/components/footer/footer.ts
@@ -0,0 +1,12 @@
+import { z } from "zod"
+
+import {
+ validateFooterConfigSchema,
+ validateFooterRefConfigSchema,
+ validateLinkItem,
+} from "@/server/routers/contentstack/base/output"
+
+export type FooterRefDataRaw = z.infer
+export type FooterDataRaw = z.infer
+export type FooterData = FooterDataRaw["all_footer"]["items"][0]
+export type FooterLinkItem = z.infer