Files
web/packages/trpc/lib/graphql/_request.ts
Anton Gunnarsson 002d093af4 Merged in feat/sw-2863-move-contentstack-router-to-trpc-package (pull request #2389)
feat(SW-2863): Move contentstack router to trpc package

* Add exports to packages and lint rule to prevent relative imports

* Add env to trpc package

* Add eslint to trpc package

* Apply lint rules

* Use direct imports from trpc package

* Add lint-staged config to trpc

* Move lang enum to common

* Restructure trpc package folder structure

* WIP first step

* update internal imports in trpc

* Fix most errors in scandic-web

Just 100 left...

* Move Props type out of trpc

* Fix CategorizedFilters types

* Move more schemas in hotel router

* Fix deps

* fix getNonContentstackUrls

* Fix import error

* Fix entry error handling

* Fix generateMetadata metrics

* Fix alertType enum

* Fix duplicated types

* lint:fix

* Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package

* Fix broken imports

* Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package


Approved-by: Linus Flood
2025-06-26 07:53:01 +00:00

148 lines
4.1 KiB
TypeScript

import "server-only"
import { ClientError, type GraphQLClient } from "graphql-request"
import { Lang } from "@scandic-hotels/common/constants/language"
import { env } from "../../env/server"
import type { DocumentNode } from "graphql"
import type { Data } from "../types/requestData"
export async function request<T>(
client: GraphQLClient,
query: string | DocumentNode,
variables?: {},
params?: RequestInit
): Promise<Data<T>> {
try {
client.setHeaders({
access_token: env.CMS_ACCESS_TOKEN,
branch: env.CMS_BRANCH,
"Content-Type": "application/json",
...params?.headers,
})
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,
}
}
try {
// @ts-expect-error: query can be undefined (?)
const operationName = (query as DocumentNode).definitions.find(
(d) => d.kind === "OperationDefinition" && d.operation === "query"
// @ts-expect-error: name does not exist (?)
).name.value
console.log(`[gql] Sending graphql request to ${env.CMS_URL}`, {
operationName,
variables,
})
} catch (e) {
console.error(`[gql] Unable to extract operation name from query`, {
query,
error: e,
})
console.log(`[gql] Sending graphql request to ${env.CMS_URL}`, {
operationName: "<Unable to extract>",
variables,
})
}
const response = await client.request<T>({
document: query,
variables,
requestHeaders: {
"User-Agent": `scandic-web-${env.SENTRY_ENVIRONMENT}`,
},
})
try {
// @ts-expect-error: query can be undefined (?)
const operationName = (query as DocumentNode).definitions.find(
(d) => d.kind === "OperationDefinition" && d.operation === "query"
// @ts-expect-error: name does not exist (?)
).name.value
console.log(`[gql] Response for ${env.CMS_URL}`, {
response,
operationName,
variables,
})
} catch (e) {
console.error(`[gql] Unable to extract operation name from query`, {
query,
error: e,
})
console.log(`[gql] Response for ${env.CMS_URL}`, {
response,
operationName: "<Unable to extract>",
variables,
})
}
return { data: response }
} catch (error) {
if (error instanceof ClientError) {
if (error.response.errors?.length) {
const failedToFetchItem = error.response.errors.find(
(err) => err.message === "Failed to fetch item"
)
if (
failedToFetchItem &&
failedToFetchItem.extensions?.errors === "Object not found!" &&
failedToFetchItem.path?.find((p) => Lang[p as Lang])
) {
/**
* Because of Contentstacks totally obscure way of implementing
* GraphQL where they throw an error when you are querying for
* a single item that is nullable and doesn't exist. This leads
* to the issue where when we have a page that is missing a published
* version for one language, it throws an error which we have to recover
* from here since it isn't an error.
*/
return { data: error.response.data as T }
}
}
}
console.error(
`[gql] Error sending graphql request to ${env.CMS_URL}`,
error
)
throw new Error("Something went wrong")
}
}