import "server-only" import deepmerge from "deepmerge" import merge from "deepmerge" import type { DocumentNode } from "graphql" import { createLogger } from "@scandic-hotels/common/logger/createLogger" import { request } from "./request" import type { CacheTime } from "@scandic-hotels/common/dataCache" import type { BatchRequestDocument } from "graphql-request" import type { Data } from "../types/requestData" export async function batchRequest( queries: (BatchRequestDocument & { cacheOptions?: { key: string | string[] ttl: CacheTime } })[] ): Promise> { const batchLogger = createLogger("graphql-batch-request") try { const response = await Promise.allSettled( queries.map((query) => request( query.document as string | DocumentNode, query.variables, query.cacheOptions ) ) ) let data = {} as T const reasons: PromiseRejectedResult["reason"][] = [] response.forEach((res) => { if (res.status === "fulfilled") { data = deepmerge(data, res.value.data, { arrayMerge }) } else { reasons.push(res.reason) } }) if (reasons.length) { reasons.forEach((reason) => { batchLogger.error(`Batch request failed`, reason) }) } return { data } } catch (error) { batchLogger.error("Error in batched graphql request", error) throw error } } function arrayMerge( target: any[], source: any[], options: merge.ArrayMergeOptions ) { const destination = target.slice() source.forEach((item, index) => { if (typeof destination[index] === "undefined") { destination[index] = options.cloneUnlessOtherwiseSpecified(item, options) } else if (options?.isMergeableObject(item)) { destination[index] = merge(target[index], item, options) } else if (target.indexOf(item) === -1) { destination.push(item) } }) return destination }