{"version":3,"sources":["../src/lib/utils/reviewFormatting.ts","../src/lib/client/googleReviewsClient.ts","../src/lib/server/googleReviews.ts","../src/server/googleReviewsHandler.ts"],"names":["kv"],"mappings":"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","file":"index.cjs","sourcesContent":["export type FallbackReviewData = {\n\trating: number;\n\treviewCount: number | null;\n\tsource: 'fallback';\n\tupdatedAt: string;\n};\n\nconst formatNumber = (value?: number | null) =>\n\ttypeof value === 'number' && Number.isFinite(value) ? value : null;\n\nexport const formatRatingDisplay = (value?: number | string | null): string => {\n\tif (typeof value === 'string') return value;\n\tconst numericValue = formatNumber(typeof value === 'number' ? value : null);\n\treturn numericValue !== null ? numericValue.toFixed(1) : '—';\n};\n\nexport const buildReviewsUrl = (placeId?: string | null): string | undefined => {\n\tif (!placeId) return undefined;\n\treturn `https://search.google.com/local/reviews?placeid=${encodeURIComponent(placeId)}`;\n};\n\nexport const resolveReviewsUrl = (placeId?: string | null, explicitUrl?: string | null): string | undefined => {\n\tif (explicitUrl && explicitUrl.trim().length > 0) return explicitUrl;\n\treturn buildReviewsUrl(placeId);\n};\n\ntype GoogleReviewsRequestUrlOptions = {\n\tendpoint: string;\n\torigin: string;\n\tplaceId?: string | null;\n\tlanguageCode?: string | null;\n\tbusinessName?: string | null;\n};\n\nexport const buildGoogleReviewsRequestUrl = ({\n\tendpoint,\n\torigin,\n\tplaceId,\n\tlanguageCode,\n\tbusinessName,\n}: GoogleReviewsRequestUrlOptions): string => {\n\tconst url = new URL(endpoint, origin);\n\n\tif (placeId) {\n\t\turl.searchParams.set('placeId', placeId);\n\t}\n\n\tconst normalizedLanguageCode = languageCode?.trim();\n\tif (normalizedLanguageCode && normalizedLanguageCode.toLowerCase() !== 'en') {\n\t\turl.searchParams.set('languageCode', normalizedLanguageCode);\n\t}\n\n\tif (businessName) {\n\t\turl.searchParams.set('businessName', businessName);\n\t}\n\n\treturn url.toString();\n};\n\ntype FallbackOptions = {\n\tfallbackRating?: number;\n\tfallbackReviewCount?: number;\n};\n\nexport const createFallbackData = ({ fallbackRating, fallbackReviewCount }: FallbackOptions): FallbackReviewData | null => {\n\tconst ratingValue = formatNumber(fallbackRating);\n\tif (ratingValue === null) {\n\t\treturn null;\n\t}\n\n\tconst reviewCountValue = formatNumber(fallbackReviewCount);\n\n\treturn {\n\t\trating: ratingValue,\n\t\treviewCount: reviewCountValue,\n\t\tsource: 'fallback',\n\t\tupdatedAt: new Date().toISOString(),\n\t};\n};\n","import { buildGoogleReviewsRequestUrl } from '../utils/reviewFormatting';\n\ninterface SelectorConfig {\n\trating: string;\n\tstar: string;\n\tstarsContainer: string;\n\treviewLink: string;\n\tctaText: string;\n\treviewCount: string;\n\tupdatedAt: string;\n\tfallback: string;\n}\n\ninterface StringTemplates {\n\tratingAvailable: string;\n\tratingPending: string;\n\tstarsAvailable: string;\n\tstarsPending: string;\n\tnoReviewsText: string;\n\tnoReviewsCtaText: string;\n}\n\nexport interface GoogleReviewsClientOptions {\n\tid: string;\n\tselectors?: Partial<SelectorConfig>;\n\tstrings?: Partial<StringTemplates>;\n\tctaTemplate?: string;\n\tdisableVisibilityRefresh?: boolean;\n}\n\ntype ReviewPayload = {\n\trating?: number;\n\treviewCount?: number;\n\treviewsUrl?: string;\n\tupdatedAt?: string;\n\tplaceId?: string;\n\tbusinessName?: string;\n\tsource?: 'fresh' | 'cache' | 'fallback';\n};\n\nconst defaultSelectors: SelectorConfig = {\n\trating: '[data-rating]',\n\tstar: '[data-star]',\n\tstarsContainer: '.star-rating',\n\treviewLink: '[data-review-link]',\n\tctaText: '[data-cta-text]',\n\treviewCount: '[data-review-count]',\n\tupdatedAt: '[data-updated-at]',\n\tfallback: 'template[data-fallback]',\n};\n\nconst defaultStrings: StringTemplates = {\n\tratingAvailable: 'Our Google Reviews rating is {rating}',\n\tratingPending: 'Awaiting Google Reviews rating',\n\tstarsAvailable: '{rating} out of 5 stars',\n\tstarsPending: 'Rating not available yet',\n\tnoReviewsText: 'No reviews yet',\n\tnoReviewsCtaText: 'Read our reviews',\n};\n\nconst formatCount = (value: number) =>\n\tIntl.NumberFormat(undefined, {\n\t\tnotation: value >= 1000 ? 'compact' : 'standard',\n\t\tmaximumFractionDigits: 1,\n\t}).format(value);\n\nconst formatRating = (value: number) => value.toFixed(1);\n\nconst template = (input: string, values: Record<string, string>) =>\n\tinput.replace(/\\{(\\w+)\\}/g, (_, key) => values[key] ?? '');\n\nexport default function initGoogleReviews(options: GoogleReviewsClientOptions) {\n\tif (typeof window === 'undefined') return;\n\n\tconst selectors = { ...defaultSelectors, ...(options.selectors ?? {}) };\n\tconst strings = { ...defaultStrings, ...(options.strings ?? {}) };\n\tconst root = document.getElementById(options.id);\n\n\tif (!root) {\n\t\tif (import.meta.env.DEV) {\n\t\t\tconsole.warn('[GoogleReviews] Root element not found for id:', options.id);\n\t\t}\n\t\treturn;\n\t}\n\n\tconst fallbackTemplate = selectors.fallback\n\t\t? (root.querySelector(selectors.fallback) as HTMLTemplateElement | null)\n\t\t: null;\n\tlet fallbackData: ReviewPayload | null = null;\n\n\tif (fallbackTemplate?.textContent) {\n\t\ttry {\n\t\t\tfallbackData = JSON.parse(fallbackTemplate.textContent) as ReviewPayload;\n\t\t} catch (error) {\n\t\t\tif (import.meta.env.DEV) {\n\t\t\t\tconsole.warn('[GoogleReviews] Failed to parse fallback data', error);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst ratingEl = selectors.rating\n\t\t? (root.querySelector(selectors.rating) as HTMLElement | null)\n\t\t: null;\n\tconst stars = selectors.star ? Array.from(root.querySelectorAll(selectors.star)) as HTMLElement[] : [];\n\tconst starsContainer = selectors.starsContainer\n\t\t? (root.querySelector(selectors.starsContainer) as HTMLElement | null)\n\t\t: null;\n\tconst reviewLink = selectors.reviewLink\n\t\t? (root.querySelector(selectors.reviewLink) as HTMLAnchorElement | null)\n\t\t: null;\n\tconst ctaTextEl = selectors.ctaText\n\t\t? (root.querySelector(selectors.ctaText) as HTMLElement | null)\n\t\t: null;\n\tconst reviewCountEl = selectors.reviewCount\n\t\t? (root.querySelector(selectors.reviewCount) as HTMLElement | null)\n\t\t: null;\n\tconst updatedAtEl = selectors.updatedAt\n\t\t? (root.querySelector(selectors.updatedAt) as HTMLElement | null)\n\t\t: null;\n\n\tconst dataset = root.dataset;\n\tconst placeId = dataset.placeId || '';\n\tconst endpoint = dataset.endpoint || '/api/google-reviews';\n\tconst language = dataset.language || 'en';\n\tconst initialBusinessName = dataset.businessName?.trim() ?? '';\n\tconst ctaTemplate = dataset.ctaTemplate || options.ctaTemplate || '';\n\tconst initialSource = dataset.source || '';\n\n\tconst applyStars = (rating: number) => {\n\t\tif (!stars.length) return;\n\t\tstars.forEach((starEl, index) => {\n\t\t\tconst fill = Math.max(0, Math.min(1, rating - index));\n\t\t\tstarEl.style.setProperty('--star-fill', fill.toString());\n\t\t});\n\t};\n\n\tconst buildRatingLabel = (rating: number | null) =>\n\t\trating !== null\n\t\t\t? template(strings.ratingAvailable, { rating: formatRating(rating) })\n\t\t\t: strings.ratingPending;\n\n\tconst buildStarsLabel = (rating: number | null) =>\n\t\trating !== null\n\t\t\t? template(strings.starsAvailable, { rating: formatRating(rating) })\n\t\t\t: strings.starsPending;\n\n\tconst updateText = (payload: ReviewPayload) => {\n\t\tif (!payload) return;\n\n\t\tconst rating =\n\t\t\ttypeof payload.rating === 'number' && Number.isFinite(payload.rating) ? payload.rating : null;\n\n\t\tif (ratingEl) {\n\t\t\tif (rating !== null) {\n\t\t\t\tratingEl.textContent = formatRating(rating);\n\t\t\t\tratingEl.setAttribute('aria-label', buildRatingLabel(rating));\n\t\t\t} else {\n\t\t\t\tratingEl.textContent = '—';\n\t\t\t\tratingEl.setAttribute('aria-label', buildRatingLabel(null));\n\t\t\t}\n\t\t}\n\n\t\tif (starsContainer) {\n\t\t\tstarsContainer.setAttribute('aria-label', buildStarsLabel(rating));\n\t\t}\n\n\t\tif (rating !== null) {\n\t\t\tapplyStars(rating);\n\t\t} else {\n\t\t\tapplyStars(0);\n\t\t}\n\n\t\tconst reviewCount =\n\t\t\ttypeof payload.reviewCount === 'number' && Number.isFinite(payload.reviewCount)\n\t\t\t\t? payload.reviewCount\n\t\t\t\t: null;\n\n\t\tif (reviewCountEl) {\n\t\t\treviewCountEl.textContent =\n\t\t\t\treviewCount !== null ? `${formatCount(reviewCount)} ${reviewCount === 1 ? 'review' : 'reviews'}` : strings.noReviewsText;\n\t\t}\n\n\t\tif (ctaTextEl) {\n\t\t\tif (reviewCount !== null) {\n\t\t\t\tconst countText = formatCount(reviewCount);\n\t\t\t\tconst label = reviewCount === 1 ? 'review' : 'reviews';\n\t\t\t\tif (ctaTemplate) {\n\t\t\t\t\tlet output = ctaTemplate;\n\t\t\t\t\tif (output.includes('{label}')) output = output.replace('{label}', label);\n\t\t\t\t\tctaTextEl.textContent = output.replace('{count}', countText);\n\t\t\t\t} else {\n\t\t\t\t\tctaTextEl.textContent = `${countText} ${label}`;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tctaTextEl.textContent = strings.noReviewsCtaText;\n\t\t\t}\n\t\t}\n\n\t\tif (reviewLink && payload.reviewsUrl) {\n\t\t\treviewLink.href = payload.reviewsUrl;\n\t\t}\n\n\t\tif (updatedAtEl) {\n\t\t\tif (payload.updatedAt) {\n\t\t\t\ttry {\n\t\t\t\t\tconst label = new Date(payload.updatedAt).toLocaleString();\n\t\t\t\t\tupdatedAtEl.textContent = `Last updated ${label}`;\n\t\t\t\t\tupdatedAtEl.setAttribute('title', label);\n\t\t\t\t} catch {\n\t\t\t\t\tupdatedAtEl.textContent = 'Last updated recently';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (payload.placeId) {\n\t\t\troot.dataset.placeId = payload.placeId;\n\t\t}\n\t\tif (typeof payload.rating === 'number') {\n\t\t\troot.dataset.rating = String(payload.rating);\n\t\t}\n\t\tif (typeof payload.reviewCount === 'number') {\n\t\t\troot.dataset.reviewCount = String(payload.reviewCount);\n\t\t}\n\t\tif (payload.updatedAt) {\n\t\t\troot.dataset.updatedAt = payload.updatedAt;\n\t\t}\n\t\tif (payload.businessName) {\n\t\t\troot.dataset.businessName = payload.businessName;\n\t\t}\n\t\tif (payload.source) {\n\t\t\troot.dataset.source = payload.source;\n\t\t}\n\n\t\tconst nextBusinessName = payload.businessName ?? root.dataset.businessName ?? initialBusinessName;\n\n\t\twindow.dispatchEvent(\n\t\t\tnew CustomEvent('google-reviews:update', {\n\t\t\t\tdetail: {\n\t\t\t\t\tplaceId: payload.placeId || root.dataset.placeId,\n\t\t\t\t\tbusinessName: nextBusinessName,\n\t\t\t\t\tdata: payload,\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t};\n\n\tif (fallbackData) {\n\t\tif (typeof fallbackData.rating === 'number') {\n\t\t\tapplyStars(fallbackData.rating);\n\t\t}\n\t\tupdateText({ ...fallbackData, source: 'fallback' });\n\t}\n\n\tconst controller = new AbortController();\n\n\tconst fetchData = async () => {\n\t\ttry {\n\t\t\tconst currentBusinessName = root.dataset.businessName?.trim() ?? initialBusinessName;\n\t\t\tconst requestUrl = buildGoogleReviewsRequestUrl({\n\t\t\t\tendpoint,\n\t\t\t\torigin: window.location.origin,\n\t\t\t\tplaceId,\n\t\t\t\tlanguageCode: language,\n\t\t\t\tbusinessName: currentBusinessName,\n\t\t\t});\n\t\t\tconst response = await fetch(requestUrl, { signal: controller.signal });\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Non-200 response ${response.status}`);\n\t\t\t}\n\n\t\t\tconst payload = (await response.json()) as ReviewPayload;\n\t\t\tupdateText(payload);\n\t\t} catch (error) {\n\t\t\tif (import.meta.env.DEV) {\n\t\t\t\tconsole.error('[GoogleReviews]', error);\n\t\t\t}\n\t\t}\n\t};\n\n\tif (document.readyState === 'complete' || document.readyState === 'interactive') {\n\t\tfetchData();\n\t} else {\n\t\tdocument.addEventListener('DOMContentLoaded', fetchData, { once: true });\n\t}\n\n\tlet visibilityHandler: (() => void) | null = null;\n\tif (!options.disableVisibilityRefresh) {\n\t\tvisibilityHandler = () => {\n\t\t\tif (document.visibilityState === 'visible' && root.dataset.source === 'fallback') {\n\t\t\t\tfetchData();\n\t\t\t}\n\t\t};\n\t\twindow.addEventListener('visibilitychange', visibilityHandler);\n\t}\n\n\troot.addEventListener('astro:unmount', () => {\n\t\tcontroller.abort();\n\t\tif (visibilityHandler) {\n\t\t\twindow.removeEventListener('visibilitychange', visibilityHandler);\n\t\t}\n\t});\n}\n","import { kv } from '@vercel/kv';\n\nconst env = import.meta.env;\n\nif (!process.env.GOOGLE_PLACES_API_KEY && env.GOOGLE_PLACES_API_KEY) {\n\tprocess.env.GOOGLE_PLACES_API_KEY = env.GOOGLE_PLACES_API_KEY;\n}\nif (!process.env.GOOGLE_PLACES_DEFAULT_PLACE_ID && env.GOOGLE_PLACES_DEFAULT_PLACE_ID) {\n\tprocess.env.GOOGLE_PLACES_DEFAULT_PLACE_ID = env.GOOGLE_PLACES_DEFAULT_PLACE_ID;\n}\nif (!process.env.KV_REST_API_URL && env.KV_REST_API_URL) {\n\tprocess.env.KV_REST_API_URL = env.KV_REST_API_URL;\n}\nif (!process.env.KV_REST_API_TOKEN && env.KV_REST_API_TOKEN) {\n\tprocess.env.KV_REST_API_TOKEN = env.KV_REST_API_TOKEN;\n}\nif (!process.env.KV_REST_API_READ_ONLY_TOKEN && env.KV_REST_API_READ_ONLY_TOKEN) {\n\tprocess.env.KV_REST_API_READ_ONLY_TOKEN = env.KV_REST_API_READ_ONLY_TOKEN;\n}\nconst CACHE_PREFIX = 'google-reviews:';\nconst DEFAULT_TTL_SECONDS =\n\tNumber.parseInt(env.GOOGLE_REVIEWS_CACHE_TTL ?? process.env.GOOGLE_REVIEWS_CACHE_TTL ?? '', 10) ||\n\t60 * 60 * 24; // 24h\nconst CACHE_EXPIRY_BUFFER = DEFAULT_TTL_SECONDS * 2;\nconst GOOGLE_API_BASE = 'https://places.googleapis.com/v1';\nconst FIELD_MASK = 'rating,userRatingCount,displayName';\nconst isKvConfigured = Boolean(\n\t(env.KV_REST_API_URL || process.env.KV_REST_API_URL) &&\n\t\t(env.KV_REST_API_TOKEN || process.env.KV_REST_API_TOKEN) &&\n\t\t(env.KV_REST_API_READ_ONLY_TOKEN || process.env.KV_REST_API_READ_ONLY_TOKEN),\n);\n\ntype CachePayload = {\n\tplaceId: string;\n\tbusinessName?: string;\n\tlanguageCode: string;\n\trating: number;\n\treviewCount: number;\n\treviewsUrl: string;\n\tupdatedAt: string;\n};\n\nexport type GoogleReviewSnapshot = CachePayload & {\n\tsource: 'fresh' | 'cache' | 'fallback';\n};\n\ntype InMemoryCacheEntry = {\n\tpayload: CachePayload;\n\texpiresAt: number;\n};\n\ndeclare global {\n\t// eslint-disable-next-line no-var\n\tvar __GOOGLE_REVIEWS_CACHE__: Map<string, InMemoryCacheEntry> | undefined;\n}\n\nconst inMemoryCache =\n\tglobalThis.__GOOGLE_REVIEWS_CACHE__ ??\n\t(globalThis.__GOOGLE_REVIEWS_CACHE__ = new Map<string, InMemoryCacheEntry>());\n\nconst normalizeLanguageCode = (languageCode?: string) => {\n\tconst normalized = languageCode?.trim().toLowerCase();\n\treturn normalized?.length ? normalized : 'en';\n};\nconst getCacheKey = (placeId: string, languageCode?: string) =>\n\t`${CACHE_PREFIX}${placeId}:${normalizeLanguageCode(languageCode)}`;\n\nasync function readCache(placeId: string, languageCode?: string): Promise<CachePayload | null> {\n\tconst key = getCacheKey(placeId, languageCode);\n\n\tif (isKvConfigured) {\n\t\tconst value = await kv.get<CachePayload>(key);\n\t\treturn value ?? null;\n\t}\n\n\tconst entry = inMemoryCache.get(key);\n\tif (!entry) {\n\t\treturn null;\n\t}\n\n\tif (entry.expiresAt <= Date.now()) {\n\t\tinMemoryCache.delete(key);\n\t\treturn null;\n\t}\n\n\treturn entry.payload;\n}\n\nasync function writeCache(placeId: string, payload: CachePayload): Promise<void> {\n\tconst key = getCacheKey(placeId, payload.languageCode);\n\n\tif (isKvConfigured) {\n\t\tawait kv.set(key, payload, { ex: CACHE_EXPIRY_BUFFER });\n\t\treturn;\n\t}\n\n\tinMemoryCache.set(key, {\n\t\tpayload,\n\t\texpiresAt: Date.now() + CACHE_EXPIRY_BUFFER * 1000,\n\t});\n}\n\ntype FetchOptions = {\n\tplaceId: string;\n\tlanguageCode: string;\n\tbusinessName?: string;\n};\n\nasync function fetchFromGoogle({ placeId, languageCode, businessName }: FetchOptions): Promise<CachePayload> {\n\tconst apiKey = env.GOOGLE_PLACES_API_KEY ?? process.env.GOOGLE_PLACES_API_KEY;\n\n\tif (!apiKey) {\n\t\tthrow new Error('GOOGLE_PLACES_API_KEY is not set');\n\t}\n\n\tif (!placeId) {\n\t\tthrow new Error('A Google placeId is required');\n\t}\n\n\tconst url = new URL(`${GOOGLE_API_BASE}/places/${placeId}`);\n\turl.searchParams.set('languageCode', languageCode);\n\n\tconst response = await fetch(url, {\n\t\theaders: {\n\t\t\t'X-Goog-Api-Key': apiKey,\n\t\t\t'X-Goog-FieldMask': FIELD_MASK,\n\t\t},\n\t});\n\n\tconst responseText = await response.text();\n\tif (!response.ok) {\n\t\tlet errorDetail = response.statusText;\n\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(responseText);\n\t\t\terrorDetail = parsed.error?.message ?? response.statusText;\n\t\t} catch {\n\t\t\t// Keep default message\n\t\t}\n\n\t\tthrow new Error(`Google Places API error (${response.status}): ${errorDetail}`);\n\t}\n\n\tconst data = JSON.parse(responseText);\n\tconst rating = typeof data.rating === 'number' ? data.rating : 0;\n\tconst reviewCount = typeof data.userRatingCount === 'number' ? data.userRatingCount : 0;\n\tconst displayName = data.displayName?.text as string | undefined;\n\tconst normalizedDisplayName = displayName?.trim().length ? displayName.trim() : undefined;\n\tconst normalizedInputName = businessName?.trim().length ? businessName.trim() : undefined;\n\tconst resolvedBusinessName = normalizedDisplayName ?? normalizedInputName;\n\n\treturn {\n\t\tplaceId,\n\t\tbusinessName: resolvedBusinessName,\n\t\tlanguageCode,\n\t\trating,\n\t\treviewCount,\n\t\treviewsUrl: buildReviewsUrl(placeId),\n\t\tupdatedAt: new Date().toISOString(),\n\t};\n}\n\nconst buildReviewsUrl = (placeId: string) =>\n\t`https://search.google.com/local/reviews?placeid=${encodeURIComponent(placeId)}`;\n\ntype SnapshotOptions = {\n\tlanguageCode?: string;\n\tbusinessName?: string;\n\tforceRefresh?: boolean;\n};\n\nexport async function getGoogleReviewSnapshot(\n\tplaceId: string,\n\toptions: SnapshotOptions = {},\n): Promise<{ data: GoogleReviewSnapshot; error?: string }> {\n\tconst languageCode = normalizeLanguageCode(options.languageCode);\n\tconst cached = await readCache(placeId, languageCode);\n\tconst now = Date.now();\n\tconst staleThreshold = DEFAULT_TTL_SECONDS * 1000;\n\tconst isCachedFresh = cached ? now - new Date(cached.updatedAt).getTime() <= staleThreshold : false;\n\n\tif (!options.forceRefresh && cached && isCachedFresh) {\n\t\treturn {\n\t\t\tdata: {\n\t\t\t\t...cached,\n\t\t\t\tsource: 'cache',\n\t\t\t},\n\t\t};\n\t}\n\n\ttry {\n\t\tconst fresh = await fetchFromGoogle({\n\t\t\tplaceId,\n\t\t\tlanguageCode,\n\t\t\tbusinessName: options.businessName ?? cached?.businessName,\n\t\t});\n\n\t\tawait writeCache(placeId, fresh);\n\n\t\treturn {\n\t\t\tdata: {\n\t\t\t\t...fresh,\n\t\t\t\tsource: 'fresh',\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : 'Unknown error talking to Google Places API';\n\n\t\tif (cached) {\n\t\t\treturn {\n\t\t\t\tdata: {\n\t\t\t\t\t...cached,\n\t\t\t\t\tsource: 'fallback',\n\t\t\t\t},\n\t\t\t\terror: message,\n\t\t\t};\n\t\t}\n\n\t\tthrow error instanceof Error ? error : new Error(message);\n\t}\n}\n","import type { APIRoute } from 'astro';\nimport { getGoogleReviewSnapshot } from '../lib/server/googleReviews';\n\nconst CACHE_HEADERS = {\n\t'Content-Type': 'application/json',\n\t'Cache-Control': 'no-store',\n\t'Access-Control-Allow-Origin': '*',\n};\n\nexport const googleReviewsHandler: APIRoute = async ({ request }) => {\n\tconst url = new URL(request.url);\n\tconst placeIdParam = url.searchParams.get('placeId');\n\tconst placeId = typeof placeIdParam === 'string' && placeIdParam.trim().length > 0 ? placeIdParam.trim() : null;\n\tconst languageCode = url.searchParams.get('languageCode')?.trim() || 'en';\n\tconst businessNameParam = url.searchParams.get('businessName');\n\tconst businessName = businessNameParam && businessNameParam.trim().length > 0 ? businessNameParam.trim() : undefined;\n\tconst forceParam = url.searchParams.get('force');\n\tconst cronSecret = process.env.CRON_SECRET;\n\tconst authHeader = request.headers.get('authorization') ?? '';\n\tconst bearerToken = authHeader.startsWith('Bearer ') ? authHeader.slice(7).trim() : null;\n\n\tif (!placeId) {\n\t\treturn new Response(JSON.stringify({ error: 'Missing placeId query parameter.' }), {\n\t\t\tstatus: 400,\n\t\t\theaders: CACHE_HEADERS,\n\t\t});\n\t}\n\n\tconst wantsForce = forceParam === 'true' || forceParam === '1';\n\tconst hasCronSecret = Boolean(cronSecret);\n\tconst forceRefresh = Boolean(wantsForce && hasCronSecret && bearerToken === cronSecret);\n\n\tif (wantsForce && (!cronSecret || !forceRefresh)) {\n\t\tconst message = cronSecret\n\t\t\t? 'Missing or invalid Authorization header for forced refresh.'\n\t\t\t: 'CRON_SECRET is not configured, forced refresh is disabled.';\n\t\treturn new Response(JSON.stringify({ error: message }), {\n\t\t\tstatus: 401,\n\t\t\theaders: CACHE_HEADERS,\n\t\t});\n\t}\n\n\ttry {\n\t\tconst { data, error } = await getGoogleReviewSnapshot(placeId, {\n\t\t\tlanguageCode,\n\t\t\tbusinessName,\n\t\t\tforceRefresh,\n\t\t});\n\n\t\treturn new Response(\n\t\t\tJSON.stringify({\n\t\t\t\tplaceId: data.placeId,\n\t\t\t\trating: data.rating,\n\t\t\t\treviewCount: data.reviewCount,\n\t\t\t\tbusinessName: data.businessName,\n\t\t\t\treviewsUrl: data.reviewsUrl,\n\t\t\t\tlanguageCode: data.languageCode,\n\t\t\t\tupdatedAt: data.updatedAt,\n\t\t\t\tsource: data.source,\n\t\t\t\tmeta: {\n\t\t\t\t\tcacheTtlSeconds: Number.parseInt(process.env.GOOGLE_REVIEWS_CACHE_TTL ?? '', 10) || 60 * 60 * 24,\n\t\t\t\t\tfetchError: error ?? null,\n\t\t\t\t},\n\t\t\t}),\n\t\t\t{\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: CACHE_HEADERS,\n\t\t\t},\n\t\t);\n\t} catch (error) {\n\t\tconst message =\n\t\t\terror instanceof Error ? error.message : 'Failed to fetch Google Reviews and no cached value is available.';\n\n\t\treturn new Response(JSON.stringify({ error: message }), {\n\t\t\tstatus: 502,\n\t\t\theaders: CACHE_HEADERS,\n\t\t});\n\t}\n};\n\nexport default googleReviewsHandler;\n"]}