{"version":3,"sources":["../src/route-rules.ts"],"sourcesContent":["import type { HeaderConfig, RedirectConfig } from \"./config\";\nimport { isFarmRedirectStatus, type FarmRedirectStatus } from \"./navigation-errors\";\nimport type { FarmRouteRuntimeConfig } from \"./route-runtime\";\nimport { normalizeFarmRouteRuntimeConfig } from \"./route-runtime\";\nimport { validateConfigRouteSource } from \"./plugins/route-pattern\";\n\nexport type FarmRouteRuleRenderMode = \"static\" | \"dynamic\";\n\nexport type FarmRouteRuleRedirect =\n  | string\n  | {\n      to: string;\n      statusCode?: FarmRedirectStatus;\n      permanent?: boolean;\n    };\n\nexport type FarmRouteRuleCors =\n  | boolean\n  | {\n      origin?: string;\n      methods?: string | readonly string[];\n      headers?: string | readonly string[];\n    };\n\nexport interface FarmRouteRule extends FarmRouteRuntimeConfig {\n  prerender?: boolean;\n  render?: FarmRouteRuleRenderMode;\n  ssr?: boolean;\n  swr?: boolean | number;\n  isr?: boolean | number;\n  cors?: FarmRouteRuleCors;\n  headers?: Record<string, string>;\n  redirect?: FarmRouteRuleRedirect;\n}\n\nexport type FarmRouteRules = Record<string, FarmRouteRule>;\n\nexport function normalizeRouteRules(routeRules: FarmRouteRules | undefined): FarmRouteRules {\n  if (!routeRules) return {};\n\n  const normalized: FarmRouteRules = {};\n  const normalizedSources = new Map<string, string>();\n  for (const [source, rule] of Object.entries(routeRules)) {\n    if (!rule) continue;\n    const normalizedSource = normalizeRuleSource(source);\n    validateConfigRouteSource(normalizedSource, `Route rule \"${source}\" source`);\n    const existingSource = normalizedSources.get(normalizedSource);\n    if (existingSource !== undefined) {\n      throw new Error(\n        `Route rules \"${existingSource}\" and \"${source}\" both normalize to \"${normalizedSource}\".`,\n      );\n    }\n    normalizedSources.set(normalizedSource, source);\n    if (\n      typeof rule.redirect === \"object\" &&\n      rule.redirect.statusCode !== undefined &&\n      !isFarmRedirectStatus(rule.redirect.statusCode)\n    ) {\n      throw new RangeError(\n        `Route rule \"${normalizedSource}\" redirect.statusCode must be one of 301, 302, 303, 307, or 308.`,\n      );\n    }\n    normalized[normalizedSource] = {\n      ...rule,\n      ...normalizeFarmRouteRuntimeConfig(rule, `Route rule \"${normalizedSource}\"`),\n    };\n  }\n  return normalized;\n}\n\nexport function routeRulesToRedirects(routeRules: FarmRouteRules): RedirectConfig[] {\n  return Object.entries(routeRules)\n    .filter((entry): entry is [string, FarmRouteRule & { redirect: FarmRouteRuleRedirect }] =>\n      Boolean(entry[1].redirect),\n    )\n    .map(([source, rule]) => {\n      const redirect = typeof rule.redirect === \"string\" ? { to: rule.redirect } : rule.redirect;\n      return {\n        source,\n        destination: redirect.to,\n        permanent: redirect.permanent,\n        statusCode: redirect.statusCode ?? (redirect.permanent === true ? 308 : undefined),\n      };\n    });\n}\n\nexport function routeRulesToHeaders(routeRules: FarmRouteRules): HeaderConfig[] {\n  const configs: HeaderConfig[] = [];\n\n  for (const [source, rule] of Object.entries(routeRules)) {\n    const headers = {\n      ...normalizeCorsHeaders(rule.cors),\n      ...rule.headers,\n    };\n\n    const entries = Object.entries(headers);\n    if (entries.length === 0) continue;\n\n    configs.push({\n      source,\n      headers: entries.map(([key, value]) => ({ key, value })),\n    });\n  }\n\n  return configs;\n}\n\nexport function routeRulesToNitroRouteRules(routeRules: FarmRouteRules): Record<string, any> {\n  const nitroRules: Record<string, any> = {};\n\n  for (const [source, rule] of Object.entries(routeRules)) {\n    const nitroRule: Record<string, any> = { ...rule };\n\n    if (rule.render === \"static\") {\n      nitroRule.prerender = true;\n    } else if (rule.render === \"dynamic\") {\n      nitroRule.prerender = false;\n    }\n\n    if (rule.redirect) {\n      const redirect = typeof rule.redirect === \"string\" ? { to: rule.redirect } : rule.redirect;\n      if (hasExplicitQuery(redirect.to)) {\n        // Nitro merges the incoming query into redirect targets, including when\n        // the target already declares one. Farm's redirect contract replaces\n        // the incoming query in that case, so let the bundled Farm handler own\n        // these redirects instead of changing their meaning in production.\n        delete nitroRule.redirect;\n      } else {\n        nitroRule.redirect = {\n          to: redirect.to,\n          status: redirect.statusCode ?? (redirect.permanent === true ? 308 : 307),\n        };\n      }\n    }\n\n    if (rule.cors) {\n      nitroRule.cors = true;\n      nitroRule.headers = {\n        ...normalizeCorsHeaders(rule.cors),\n        ...rule.headers,\n      };\n    }\n\n    delete nitroRule.render;\n    delete nitroRule.runtime;\n    delete nitroRule.regions;\n    delete nitroRule.maxDuration;\n    nitroRules[source] = nitroRule;\n  }\n\n  return nitroRules;\n}\n\nfunction normalizeCorsHeaders(cors: FarmRouteRuleCors | undefined): Record<string, string> {\n  if (!cors) return {};\n\n  if (cors === true) {\n    return {\n      \"Access-Control-Allow-Origin\": \"*\",\n      \"Access-Control-Allow-Methods\": \"*\",\n      \"Access-Control-Allow-Headers\": \"*\",\n    };\n  }\n\n  return {\n    \"Access-Control-Allow-Origin\": cors.origin ?? \"*\",\n    \"Access-Control-Allow-Methods\": normalizeList(cors.methods) ?? \"*\",\n    \"Access-Control-Allow-Headers\": normalizeList(cors.headers) ?? \"*\",\n  };\n}\n\nfunction normalizeList(value: string | readonly string[] | undefined): string | undefined {\n  if (!value || typeof value === \"string\") return value;\n  return value.join(\", \");\n}\n\nfunction normalizeRuleSource(source: string): string {\n  const trimmed = source.trim();\n  if (!trimmed) {\n    throw new TypeError(\"Route rule source must be a non-empty pathname pattern.\");\n  }\n  return trimmed.startsWith(\"/\") ? trimmed : `/${trimmed}`;\n}\n\nfunction hasExplicitQuery(destination: string): boolean {\n  const queryIndex = destination.indexOf(\"?\");\n  if (queryIndex === -1) return false;\n  const hashIndex = destination.indexOf(\"#\");\n  return hashIndex === -1 || queryIndex < hashIndex;\n}\n"],"mappings":"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","names":[]}