{"version":3,"file":"utils.mjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import type { EnvironmentContext, LogLevel } from './types'\n\nexport function formatDuration(ms: number): string {\n  if (ms < 1000) {\n    return `${Math.round(ms)}ms`\n  }\n  return `${(ms / 1000).toFixed(2)}s`\n}\n\nexport function isServer(): boolean {\n  return typeof window === 'undefined'\n}\n\nexport function isClient(): boolean {\n  return typeof window !== 'undefined'\n}\n\nexport function isDev(): boolean {\n  if (typeof process !== 'undefined') {\n    return process.env.NODE_ENV !== 'production'\n  }\n  if (typeof window !== 'undefined') {\n    return true\n  }\n  return false\n}\n\nexport function detectEnvironment(): Partial<EnvironmentContext> {\n  const env = typeof process !== 'undefined' ? process.env : {}\n  const defaultEnvironment = isDev() ? 'development' : 'production'\n\n  return {\n    environment: env.NODE_ENV || defaultEnvironment,\n    service: env.SERVICE_NAME || 'app',\n    version: env.APP_VERSION,\n    commitHash: env.COMMIT_SHA\n      || env.GITHUB_SHA\n      || env.VERCEL_GIT_COMMIT_SHA\n      || env.CF_PAGES_COMMIT_SHA,\n    region: env.VERCEL_REGION\n      || env.AWS_REGION\n      || env.FLY_REGION\n      || env.CF_REGION,\n  }\n}\n\nexport function getConsoleMethod(level: LogLevel): LogLevel {\n  return level\n}\n\nexport const colors = {\n  reset: '\\x1B[0m',\n  bold: '\\x1B[1m',\n  dim: '\\x1B[2m',\n  red: '\\x1B[31m',\n  green: '\\x1B[32m',\n  yellow: '\\x1B[33m',\n  blue: '\\x1B[34m',\n  magenta: '\\x1B[35m',\n  cyan: '\\x1B[36m',\n  white: '\\x1B[37m',\n  gray: '\\x1B[90m',\n} as const\n\nexport function getLevelColor(level: string): string {\n  switch (level) {\n    case 'error':\n      return colors.red\n    case 'warn':\n      return colors.yellow\n    case 'info':\n      return colors.cyan\n    case 'debug':\n      return colors.gray\n    default:\n      return colors.white\n  }\n}\n\nexport const cssColors = {\n  dim: 'color: #6b7280',\n  red: 'color: #ef4444; font-weight: bold',\n  green: 'color: #22c55e',\n  yellow: 'color: #f59e0b; font-weight: bold',\n  cyan: 'color: #06b6d4; font-weight: bold',\n  gray: 'color: #6b7280; font-weight: bold',\n  reset: 'color: inherit; font-weight: normal',\n} as const\n\nexport function getCssLevelColor(level: string): string {\n  switch (level) {\n    case 'error':\n      return cssColors.red\n    case 'warn':\n      return cssColors.yellow\n    case 'info':\n      return cssColors.cyan\n    case 'debug':\n      return cssColors.gray\n    default:\n      return cssColors.reset\n  }\n}\n\n/**\n * Escape `%` in strings interpolated into `console.log` format strings\n * to prevent `%c`, `%s`, `%d` etc. in user data from being interpreted\n * as formatting directives.\n */\nexport function escapeFormatString(str: string): string {\n  return str.replace(/%/g, '%%')\n}\n\n/** Headers that should never be passed to hooks for security */\nexport const SENSITIVE_HEADERS = [\n  'authorization',\n  'cookie',\n  'set-cookie',\n  'x-api-key',\n  'x-auth-token',\n  'proxy-authorization',\n]\n\nexport function filterSafeHeaders(headers: Record<string, string>): Record<string, string> {\n  const safeHeaders: Record<string, string> = {}\n\n  for (const [key, value] of Object.entries(headers)) {\n    if (!SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n      safeHeaders[key] = value\n    }\n  }\n\n  return safeHeaders\n}\n\n/**\n * Match a path against a glob pattern.\n * Supports * (any chars except /) and ** (any chars including /).\n */\nexport function matchesPattern(path: string, pattern: string): boolean {\n  const regexPattern = pattern\n    .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // Escape special regex chars except * and ?\n    .replace(/\\*\\*/g, '{{GLOBSTAR}}') // Temp placeholder for **\n    .replace(/\\*/g, '[^/]*') // * matches anything except /\n    .replace(/{{GLOBSTAR}}/g, '.*') // ** matches anything including /\n    .replace(/\\?/g, '[^/]') // ? matches single char except /\n\n  const regex = new RegExp(`^${regexPattern}$`)\n  return regex.test(path)\n}\n"],"mappings":";AAEA,SAAgB,eAAe,IAAoB;AACjD,KAAI,KAAK,IACP,QAAO,GAAG,KAAK,MAAM,GAAG,CAAC;AAE3B,QAAO,IAAI,KAAK,KAAM,QAAQ,EAAE,CAAC;;AAGnC,SAAgB,WAAoB;AAClC,QAAO,OAAO,WAAW;;AAG3B,SAAgB,WAAoB;AAClC,QAAO,OAAO,WAAW;;AAG3B,SAAgB,QAAiB;AAC/B,KAAI,OAAO,YAAY,YACrB,QAAO,QAAQ,IAAI,aAAa;AAElC,KAAI,OAAO,WAAW,YACpB,QAAO;AAET,QAAO;;AAGT,SAAgB,oBAAiD;CAC/D,MAAM,MAAM,OAAO,YAAY,cAAc,QAAQ,MAAM,EAAE;CAC7D,MAAM,qBAAqB,OAAO,GAAG,gBAAgB;AAErD,QAAO;EACL,aAAa,IAAI,YAAY;EAC7B,SAAS,IAAI,gBAAgB;EAC7B,SAAS,IAAI;EACb,YAAY,IAAI,cACX,IAAI,cACJ,IAAI,yBACJ,IAAI;EACT,QAAQ,IAAI,iBACP,IAAI,cACJ,IAAI,cACJ,IAAI;EACV;;AAGH,SAAgB,iBAAiB,OAA2B;AAC1D,QAAO;;AAGT,MAAa,SAAS;CACpB,OAAO;CACP,MAAM;CACN,KAAK;CACL,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,SAAS;CACT,MAAM;CACN,OAAO;CACP,MAAM;CACP;AAED,SAAgB,cAAc,OAAuB;AACnD,SAAQ,OAAR;EACE,KAAK,QACH,QAAO,OAAO;EAChB,KAAK,OACH,QAAO,OAAO;EAChB,KAAK,OACH,QAAO,OAAO;EAChB,KAAK,QACH,QAAO,OAAO;EAChB,QACE,QAAO,OAAO;;;AAIpB,MAAa,YAAY;CACvB,KAAK;CACL,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAED,SAAgB,iBAAiB,OAAuB;AACtD,SAAQ,OAAR;EACE,KAAK,QACH,QAAO,UAAU;EACnB,KAAK,OACH,QAAO,UAAU;EACnB,KAAK,OACH,QAAO,UAAU;EACnB,KAAK,QACH,QAAO,UAAU;EACnB,QACE,QAAO,UAAU;;;;;;;;AASvB,SAAgB,mBAAmB,KAAqB;AACtD,QAAO,IAAI,QAAQ,MAAM,KAAK;;;AAIhC,MAAa,oBAAoB;CAC/B;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,kBAAkB,SAAyD;CACzF,MAAM,cAAsC,EAAE;AAE9C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,CAChD,KAAI,CAAC,kBAAkB,SAAS,IAAI,aAAa,CAAC,CAChD,aAAY,OAAO;AAIvB,QAAO;;;;;;AAOT,SAAgB,eAAe,MAAc,SAA0B;CACrE,MAAM,eAAe,QAClB,QAAQ,qBAAqB,OAAO,CACpC,QAAQ,SAAS,eAAe,CAChC,QAAQ,OAAO,QAAQ,CACvB,QAAQ,iBAAiB,KAAK,CAC9B,QAAQ,OAAO,OAAO;AAGzB,QADc,IAAI,OAAO,IAAI,aAAa,GAAG,CAChC,KAAK,KAAK"}