{"version":3,"sources":["../src/index.ts","../src/shared/index.ts","../src/errors.ts","../src/utils/umami/cache.ts","../src/utils/fetch.ts","../src/modules/umami/api.ts","../src/utils/umami/url-parser.ts","../src/modules/umami/client.ts","../src/astro/integration.ts","../src/runtime/client.ts"],"sourcesContent":["// 核心导出\r\nexport { VERSION } from './shared';\r\n\r\n// 错误类\r\nexport { UmamiError, UmamiUrlError, UmamiAuthError, UmamiNetworkError, UmamiTimeoutError } from './errors';\r\n\r\n// Umami 模块\r\nexport { UmamiClient, createUmamiClient } from './modules/umami/client';\r\nexport type {\r\n  UmamiConfig,\r\n  StatsResult,\r\n  StatsQueryParams,\r\n  StatsComparison,\r\n  MetricType,\r\n  MetricEntry,\r\n  PageviewPoint,\r\n  PageviewsSeries,\r\n  WebsiteInfo,\r\n  DateRange\r\n} from './modules/umami/types';\r\n\r\n// 工具函数\r\nexport { CacheManager } from './utils/umami/cache';\r\nexport { parseShareUrl } from './utils/umami/url-parser';\r\n\r\n// Astro 集成\r\nexport { umami, oddmisc } from './astro';\r\nexport type { UmamiIntegrationOptions, OddmiscIntegrationOptions } from './astro';\r\n\r\n// 运行时客户端（用于手动初始化）\r\nexport { initUmamiRuntime } from './runtime/client';\r\nexport type { UmamiRuntimeConfig as RuntimeConfig, StatsResult as RuntimeStatsResult, OddmiscReadyEvent } from './runtime/client';\r\n","declare const PKG_VERSION: string;\r\nexport const VERSION = typeof PKG_VERSION !== 'undefined' ? PKG_VERSION : 'dev';\r\n","export class UmamiError extends Error {\r\n  readonly code: string;\r\n  readonly status?: number;\r\n\r\n  constructor(message: string, code: string, status?: number) {\r\n    super(message);\r\n    this.name = 'UmamiError';\r\n    this.code = code;\r\n    this.status = status;\r\n  }\r\n}\r\n\r\nexport class UmamiUrlError extends UmamiError {\r\n  constructor(message: string) {\r\n    super(message, 'INVALID_URL');\r\n    this.name = 'UmamiUrlError';\r\n  }\r\n}\r\n\r\nexport class UmamiAuthError extends UmamiError {\r\n  constructor(message: string, status?: number) {\r\n    super(message, 'AUTH_FAILED', status);\r\n    this.name = 'UmamiAuthError';\r\n  }\r\n}\r\n\r\nexport class UmamiNetworkError extends UmamiError {\r\n  constructor(message: string, status?: number) {\r\n    super(message, 'NETWORK_ERROR', status);\r\n    this.name = 'UmamiNetworkError';\r\n  }\r\n}\r\n\r\nexport class UmamiTimeoutError extends UmamiError {\r\n  constructor(message = '请求超时') {\r\n    super(message, 'TIMEOUT');\r\n    this.name = 'UmamiTimeoutError';\r\n  }\r\n}\r\n","const isBrowser = typeof window !== 'undefined' && typeof localStorage !== 'undefined';\r\n\r\nconst DEFAULT_MAX_ENTRIES = 200;\r\n\r\nexport class CacheManager<T = unknown> {\r\n  private memoryCache = new Map<string, { value: T; timestamp: number }>();\r\n  private readonly cacheKey: string;\r\n  private readonly ttl: number;\r\n  private readonly maxEntries: number;\r\n  private storageCache: Record<string, { value: T; timestamp: number }> | null = null;\r\n\r\n  constructor(namespace = 'default', ttl = 3600000, maxEntries = DEFAULT_MAX_ENTRIES) {\r\n    this.cacheKey = `cache-${namespace}`;\r\n    this.ttl = ttl;\r\n    this.maxEntries = maxEntries;\r\n  }\r\n\r\n  private loadStorage(): Record<string, { value: T; timestamp: number }> {\r\n    if (this.storageCache !== null) return this.storageCache;\r\n    if (!isBrowser) {\r\n      this.storageCache = {};\r\n    } else {\r\n      try {\r\n        const cached = localStorage.getItem(this.cacheKey);\r\n        this.storageCache = cached ? JSON.parse(cached) : {};\r\n      } catch {\r\n        this.storageCache = {};\r\n      }\r\n    }\r\n    return this.storageCache!;\r\n  }\r\n\r\n  private saveStorage(): void {\r\n    if (!isBrowser || this.storageCache === null) return;\r\n    try {\r\n      localStorage.setItem(this.cacheKey, JSON.stringify(this.storageCache));\r\n    } catch (e) {\r\n      console.warn('[oddmisc] localStorage write failed:', e instanceof Error ? e.message : e);\r\n    }\r\n  }\r\n\r\n  private isExpired(timestamp: number): boolean {\r\n    return Date.now() - timestamp >= this.ttl;\r\n  }\r\n\r\n  private evictIfNeeded(): void {\r\n    if (this.memoryCache.size <= this.maxEntries) return;\r\n    const entries = [...this.memoryCache.entries()].sort((a, b) => a[1].timestamp - b[1].timestamp);\r\n    const toRemove = entries.length - this.maxEntries;\r\n    const storage = this.loadStorage();\r\n    for (let i = 0; i < toRemove; i++) {\r\n      this.memoryCache.delete(entries[i][0]);\r\n      delete storage[entries[i][0]];\r\n    }\r\n    this.saveStorage();\r\n  }\r\n\r\n  get(key: string): T | null {\r\n    const memCached = this.memoryCache.get(key);\r\n    if (memCached && !this.isExpired(memCached.timestamp)) return memCached.value;\r\n    if (memCached) this.memoryCache.delete(key);\r\n\r\n    const storage = this.loadStorage();\r\n    const stored = storage[key];\r\n    if (stored && !this.isExpired(stored.timestamp)) {\r\n      this.memoryCache.set(key, stored);\r\n      return stored.value;\r\n    }\r\n    if (stored) {\r\n      delete storage[key];\r\n      this.saveStorage();\r\n    }\r\n    return null;\r\n  }\r\n\r\n  set(key: string, value: T): void {\r\n    const entry = { value, timestamp: Date.now() };\r\n    this.memoryCache.set(key, entry);\r\n    const storage = this.loadStorage();\r\n    storage[key] = entry;\r\n    this.saveStorage();\r\n    this.evictIfNeeded();\r\n  }\r\n\r\n  clear(): void {\r\n    this.memoryCache.clear();\r\n    this.storageCache = null;\r\n    if (isBrowser) {\r\n      try { localStorage.removeItem(this.cacheKey); } catch { /* ignore */ }\r\n    }\r\n  }\r\n\r\n  delete(key: string): void {\r\n    this.memoryCache.delete(key);\r\n    const storage = this.loadStorage();\r\n    if (key in storage) {\r\n      delete storage[key];\r\n      this.saveStorage();\r\n    }\r\n  }\r\n}\r\n","import { UmamiTimeoutError } from '../errors';\r\n\r\nconst DEFAULT_TIMEOUT = 10000;\r\n\r\nexport async function fetchWithTimeout(url: string, options?: RequestInit, timeout = DEFAULT_TIMEOUT): Promise<Response> {\r\n  const controller = new AbortController();\r\n  const timeoutId = setTimeout(() => controller.abort(), timeout);\r\n  try {\r\n    return await fetch(url, { ...options, signal: controller.signal });\r\n  } catch (err) {\r\n    if (err instanceof DOMException && err.name === 'AbortError') {\r\n      throw new UmamiTimeoutError(`请求超时 (${timeout}ms): ${url}`);\r\n    }\r\n    throw err;\r\n  } finally {\r\n    clearTimeout(timeoutId);\r\n  }\r\n}\r\n","import type {\r\n  ShareData,\r\n  StatsQueryParams,\r\n  PageviewsSeries,\r\n  MetricEntry,\r\n  MetricType,\r\n  WebsiteInfo,\r\n  DateRange\r\n} from './types';\r\nimport { CacheManager } from '../../utils/umami/cache';\r\nimport { fetchWithTimeout } from '../../utils/fetch';\r\nimport { UmamiNetworkError, UmamiAuthError } from '../../errors';\r\n\r\n// cloud.umami.is 需要此 header，否则 401\r\nconst SHARE_CONTEXT_HEADER = 'x-umami-share-context';\r\nconst SHARE_CONTEXT_VALUE = '1';\r\n\r\n// endAt 默认值按 5 分钟对齐，减少缓存未命中\r\nconst RANGE_ALIGN_MS = 5 * 60_000;\r\n\r\ninterface StatsAPIParams extends Partial<StatsQueryParams> {\r\n  path?: string;\r\n  hostname?: string;\r\n  url?: string;\r\n}\r\n\r\nexport interface StatsAPIResponse {\r\n  pageviews?: number | { value: number };\r\n  visitors?: number | { value: number };\r\n  visits?: number | { value: number };\r\n  bounces?: number | { value: number };\r\n  totaltime?: number | { value: number };\r\n  comparison?: {\r\n    pageviews?: number;\r\n    visitors?: number;\r\n    visits?: number;\r\n    bounces?: number;\r\n    totaltime?: number;\r\n  };\r\n  _fromCache?: boolean;\r\n  [key: string]: unknown;\r\n}\r\n\r\nexport interface TimeRange {\r\n  startAt?: number;\r\n  endAt?: number;\r\n}\r\n\r\nexport interface PageviewsParams extends TimeRange {\r\n  unit?: 'year' | 'month' | 'day' | 'hour' | 'minute';\r\n  timezone?: string;\r\n}\r\n\r\nexport interface MetricsParams extends TimeRange {\r\n  limit?: number;\r\n}\r\n\r\ntype Cached<T> = T & { _fromCache?: boolean };\r\n\r\nexport class UmamiAPI {\r\n  private sharePromises = new Map<string, Promise<ShareData>>();\r\n\r\n  constructor(private readonly cacheManager: CacheManager) {}\r\n\r\n  private shareKey(baseUrl: string, shareId: string): string {\r\n    return `${baseUrl}|${shareId}`;\r\n  }\r\n\r\n  async getShareData(baseUrl: string, shareId: string): Promise<ShareData> {\r\n    const key = this.shareKey(baseUrl, shareId);\r\n    let promise = this.sharePromises.get(key);\r\n    if (!promise) {\r\n      promise = this.fetchShareData(baseUrl, shareId).catch((err) => {\r\n        this.sharePromises.delete(key);\r\n        throw err;\r\n      });\r\n      this.sharePromises.set(key, promise);\r\n    }\r\n    return promise;\r\n  }\r\n\r\n  clearShareCache(baseUrl?: string, shareId?: string): void {\r\n    if (baseUrl && shareId) {\r\n      this.sharePromises.delete(this.shareKey(baseUrl, shareId));\r\n    } else {\r\n      this.sharePromises.clear();\r\n    }\r\n  }\r\n\r\n  private async fetchShareData(baseUrl: string, shareId: string): Promise<ShareData> {\r\n    const res = await fetchWithTimeout(`${baseUrl}/share/${shareId}`);\r\n    if (!res.ok) {\r\n      throw new UmamiNetworkError(`获取分享信息失败: ${res.status}`, res.status);\r\n    }\r\n    return (await res.json()) as ShareData;\r\n  }\r\n\r\n  private async authedFetch<T>(baseUrl: string, shareId: string, path: string): Promise<T> {\r\n    const { token } = await this.getShareData(baseUrl, shareId);\r\n    const res = await fetchWithTimeout(`${baseUrl}${path}`, {\r\n      headers: {\r\n        'x-umami-share-token': token,\r\n        [SHARE_CONTEXT_HEADER]: SHARE_CONTEXT_VALUE\r\n      }\r\n    });\r\n\r\n    if (!res.ok) {\r\n      if (res.status === 401) {\r\n        this.sharePromises.delete(this.shareKey(baseUrl, shareId));\r\n        throw new UmamiAuthError('认证失败，请检查 shareId', res.status);\r\n      }\r\n      throw new UmamiNetworkError(`请求 ${path} 失败: ${res.status}`, res.status);\r\n    }\r\n    return (await res.json()) as T;\r\n  }\r\n\r\n  private async cachedGet<T extends object>(\r\n    baseUrl: string,\r\n    shareId: string,\r\n    path: string,\r\n    cacheKey: string\r\n  ): Promise<Cached<T>> {\r\n    const cached = this.cacheManager.get(cacheKey) as T | null;\r\n    if (cached) return { ...cached, _fromCache: true };\r\n    const data = await this.authedFetch<T>(baseUrl, shareId, path);\r\n    this.cacheManager.set(cacheKey, data);\r\n    return data;\r\n  }\r\n\r\n  private resolveRange(range: TimeRange = {}): { startAt: number; endAt: number } {\r\n    return {\r\n      startAt: range.startAt ?? 0,\r\n      endAt: range.endAt ?? Math.floor(Date.now() / RANGE_ALIGN_MS) * RANGE_ALIGN_MS\r\n    };\r\n  }\r\n\r\n  async getStats(baseUrl: string, shareId: string, params: StatsAPIParams): Promise<StatsAPIResponse> {\r\n    const { websiteId } = await this.getShareData(baseUrl, shareId);\r\n    const { startAt, endAt } = this.resolveRange(params);\r\n    const qp = new URLSearchParams({ startAt: startAt.toString(), endAt: endAt.toString() });\r\n    const cacheQp = new URLSearchParams({ startAt: startAt.toString(), endAt: endAt.toString() });\r\n    if (params.path) { qp.set('path', params.path); cacheQp.set('path', params.path); }\r\n    if (params.url) { qp.set('url', params.url); cacheQp.set('url', params.url); }\r\n    if (params.hostname) { qp.set('hostname', params.hostname); cacheQp.set('hostname', params.hostname); }\r\n    return this.cachedGet<StatsAPIResponse>(\r\n      baseUrl, shareId,\r\n      `/websites/${websiteId}/stats?${qp.toString()}`,\r\n      `${baseUrl}|${shareId}|stats|${cacheQp.toString()}`\r\n    );\r\n  }\r\n\r\n  async getActiveVisitors(baseUrl: string, shareId: string): Promise<{ visitors: number }> {\r\n    const { websiteId } = await this.getShareData(baseUrl, shareId);\r\n    return this.authedFetch(baseUrl, shareId, `/websites/${websiteId}/active`);\r\n  }\r\n\r\n  async getWebsite(baseUrl: string, shareId: string): Promise<Cached<WebsiteInfo>> {\r\n    const { websiteId } = await this.getShareData(baseUrl, shareId);\r\n    return this.cachedGet<WebsiteInfo>(\r\n      baseUrl, shareId,\r\n      `/websites/${websiteId}`,\r\n      `${baseUrl}|${shareId}|website`\r\n    );\r\n  }\r\n\r\n  async getDateRange(baseUrl: string, shareId: string): Promise<Cached<DateRange>> {\r\n    const { websiteId } = await this.getShareData(baseUrl, shareId);\r\n    return this.cachedGet<DateRange>(\r\n      baseUrl, shareId,\r\n      `/websites/${websiteId}/daterange`,\r\n      `${baseUrl}|${shareId}|daterange`\r\n    );\r\n  }\r\n\r\n  async getPageviews(\r\n    baseUrl: string,\r\n    shareId: string,\r\n    params: PageviewsParams = {}\r\n  ): Promise<Cached<PageviewsSeries>> {\r\n    const { websiteId } = await this.getShareData(baseUrl, shareId);\r\n    const { startAt, endAt } = this.resolveRange(params);\r\n    const qp = new URLSearchParams({ startAt: startAt.toString(), endAt: endAt.toString() });\r\n    const cacheQp = new URLSearchParams({ startAt: startAt.toString(), endAt: endAt.toString() });\r\n    qp.set('unit', params.unit ?? 'day');\r\n    qp.set('timezone', params.timezone ?? 'UTC');\r\n    cacheQp.set('unit', params.unit ?? 'day');\r\n    cacheQp.set('timezone', params.timezone ?? 'UTC');\r\n    return this.cachedGet<PageviewsSeries>(\r\n      baseUrl, shareId,\r\n      `/websites/${websiteId}/pageviews?${qp.toString()}`,\r\n      `${baseUrl}|${shareId}|pageviews|${cacheQp.toString()}`\r\n    );\r\n  }\r\n\r\n  async getMetrics(\r\n    baseUrl: string,\r\n    shareId: string,\r\n    type: MetricType,\r\n    params: MetricsParams = {}\r\n  ): Promise<Cached<MetricEntry[]>> {\r\n    const { websiteId } = await this.getShareData(baseUrl, shareId);\r\n    const { startAt, endAt } = this.resolveRange(params);\r\n    const qp = new URLSearchParams({ startAt: startAt.toString(), endAt: endAt.toString() });\r\n    const cacheQp = new URLSearchParams({ startAt: startAt.toString(), endAt: endAt.toString() });\r\n    qp.set('type', type);\r\n    if (typeof params.limit === 'number') qp.set('limit', params.limit.toString());\r\n    cacheQp.set('type', type);\r\n    if (typeof params.limit === 'number') cacheQp.set('limit', params.limit.toString());\r\n    const cacheKey = `${baseUrl}|${shareId}|metrics|${cacheQp.toString()}`;\r\n\r\n    const cached = this.cacheManager.get(cacheKey) as { data: MetricEntry[] } | null;\r\n    if (cached) {\r\n      Object.defineProperty(cached.data, '_fromCache', { value: true, enumerable: false, writable: true });\r\n      return cached.data;\r\n    }\r\n\r\n    const data = await this.authedFetch<MetricEntry[]>(\r\n      baseUrl, shareId,\r\n      `/websites/${websiteId}/metrics?${qp.toString()}`\r\n    );\r\n    this.cacheManager.set(cacheKey, { data });\r\n    return data;\r\n  }\r\n}\r\n","import { UmamiUrlError } from '../../errors';\r\n\r\nexport function parseShareUrl(shareUrl: string): { apiBase: string; shareId: string } {\r\n  try {\r\n    const url = new URL(shareUrl);\r\n    const pathParts = url.pathname.split('/');\r\n    const shareIndex = pathParts.indexOf('share');\r\n\r\n    if (shareIndex === -1 || shareIndex === pathParts.length - 1) {\r\n      throw new UmamiUrlError('未找到 share 路径');\r\n    }\r\n\r\n    const shareId = pathParts[shareIndex + 1];\r\n    if (!shareId) throw new UmamiUrlError('缺少分享 ID');\r\n\r\n    const pathBeforeShare = pathParts.slice(0, shareIndex).join('/');\r\n    const apiBase = `${url.protocol}//${url.host}${pathBeforeShare}/api`;\r\n    return { apiBase, shareId };\r\n  } catch (error) {\r\n    if (error instanceof UmamiUrlError) throw error;\r\n    throw new UmamiUrlError(`无效的 URL 格式: ${error instanceof Error ? error.message : '未知错误'}`);\r\n  }\r\n}\r\n","import { CacheManager } from '../../utils/umami/cache';\r\nimport { UmamiAPI, type PageviewsParams, type MetricsParams, type StatsAPIResponse } from './api';\r\nimport { parseShareUrl } from '../../utils/umami/url-parser';\r\nimport { UmamiUrlError } from '../../errors';\r\nimport type {\r\n  UmamiConfig,\r\n  StatsResult,\r\n  StatsQueryParams,\r\n  MetricType,\r\n  MetricEntry,\r\n  PageviewsSeries,\r\n  WebsiteInfo,\r\n  DateRange\r\n} from './types';\r\n\r\nfunction extractValue(field: number | { value: number } | undefined): number {\r\n  if (typeof field === 'number') return field;\r\n  return field?.value ?? 0;\r\n}\r\n\r\nfunction toStatsResult(data: StatsAPIResponse): StatsResult {\r\n  const result: StatsResult = {\r\n    pageviews: extractValue(data.pageviews),\r\n    visitors: extractValue(data.visitors),\r\n    visits: extractValue(data.visits),\r\n    _fromCache: data._fromCache\r\n  };\r\n  if (data.bounces !== undefined) result.bounces = extractValue(data.bounces);\r\n  if (data.totaltime !== undefined) result.totaltime = extractValue(data.totaltime);\r\n  if (data.comparison) result.comparison = data.comparison;\r\n  return result;\r\n}\r\n\r\nexport class UmamiClient {\r\n  private baseUrl: string;\r\n  private shareId: string;\r\n  private cacheManager: CacheManager;\r\n  private api: UmamiAPI;\r\n\r\n  constructor(config: UmamiConfig) {\r\n    if (!config.shareUrl) {\r\n      throw new UmamiUrlError('shareUrl 是必需参数');\r\n    }\r\n\r\n    const { apiBase, shareId } = parseShareUrl(config.shareUrl);\r\n    this.baseUrl = apiBase;\r\n    this.shareId = shareId;\r\n\r\n    this.cacheManager = new CacheManager('umami', 3600000);\r\n    this.api = new UmamiAPI(this.cacheManager);\r\n  }\r\n\r\n  async getPageStats(path: string, options: Partial<StatsQueryParams> = {}): Promise<StatsResult> {\r\n    const data = await this.api.getStats(this.baseUrl, this.shareId, {\r\n      path: `eq.${path}`,\r\n      ...options\r\n    });\r\n    return toStatsResult(data);\r\n  }\r\n\r\n  async getPageStatsByUrl(url: string, options: Partial<StatsQueryParams> = {}): Promise<StatsResult> {\r\n    const data = await this.api.getStats(this.baseUrl, this.shareId, { url, ...options });\r\n    return toStatsResult(data);\r\n  }\r\n\r\n  async getSiteStats(options: Partial<StatsQueryParams> = {}): Promise<StatsResult> {\r\n    const data = await this.api.getStats(this.baseUrl, this.shareId, options);\r\n    return toStatsResult(data);\r\n  }\r\n\r\n  async getActiveVisitors(): Promise<number> {\r\n    const data = await this.api.getActiveVisitors(this.baseUrl, this.shareId);\r\n    return data.visitors ?? 0;\r\n  }\r\n\r\n  async getPageviews(options: PageviewsParams = {}): Promise<PageviewsSeries> {\r\n    const data = await this.api.getPageviews(this.baseUrl, this.shareId, options);\r\n    return { pageviews: data.pageviews ?? [], sessions: data.sessions ?? [] };\r\n  }\r\n\r\n  getMetrics(type: MetricType, options: MetricsParams = {}): Promise<MetricEntry[]> {\r\n    return this.api.getMetrics(this.baseUrl, this.shareId, type, options);\r\n  }\r\n\r\n  getWebsite(): Promise<WebsiteInfo> {\r\n    return this.api.getWebsite(this.baseUrl, this.shareId);\r\n  }\r\n\r\n  getDateRange(): Promise<DateRange> {\r\n    return this.api.getDateRange(this.baseUrl, this.shareId);\r\n  }\r\n\r\n  clearCache(): void {\r\n    this.cacheManager.clear();\r\n    this.api.clearShareCache(this.baseUrl, this.shareId);\r\n  }\r\n}\r\n\r\nexport function createUmamiClient(config: UmamiConfig): UmamiClient {\r\n  return new UmamiClient(config);\r\n}\r\n","import { readFileSync } from 'fs';\r\nimport { fileURLToPath } from 'url';\r\nimport { dirname, join } from 'path';\r\nimport type { AstroIntegration, HookParameters } from 'astro';\r\n\r\nexport interface UmamiIntegrationOptions {\r\n  shareUrl: string | false;\r\n}\r\n\r\nexport interface OddmiscIntegrationOptions {\r\n  umami?: UmamiIntegrationOptions;\r\n}\r\n\r\ntype AstroConfigSetupParams = HookParameters<'astro:config:setup'>;\r\n\r\nfunction injectUmamiRuntime(shareUrl: string | false): string | undefined {\r\n  if (!shareUrl) return;\r\n\r\n  let runtimeCode = '';\r\n  try {\r\n    const __dirname = dirname(fileURLToPath(import.meta.url));\r\n    // dist/astro/ → dist/runtime/client.global.js\r\n    const runtimePath = join(__dirname, '../runtime/client.global.js');\r\n    runtimeCode = readFileSync(runtimePath, 'utf-8');\r\n  } catch {\r\n    console.warn('[oddmisc] 无法读取运行时文件，已跳过客户端注入');\r\n    return;\r\n  }\r\n\r\n  return `\r\n// oddmisc Umami Runtime\r\n${runtimeCode}\r\n\r\nif (typeof window !== 'undefined' && typeof __oddmiscRuntime !== 'undefined') {\r\n  __oddmiscRuntime.initUmamiRuntime(${JSON.stringify({ shareUrl })});\r\n}\r\n`;\r\n}\r\n\r\nexport function umami(options: UmamiIntegrationOptions): AstroIntegration {\r\n  return {\r\n    name: 'oddmisc-umami-integration',\r\n    hooks: {\r\n      'astro:config:setup': ({ injectScript }: AstroConfigSetupParams) => {\r\n        const code = injectUmamiRuntime(options.shareUrl);\r\n        if (code) injectScript('page', code);\r\n      }\r\n    }\r\n  };\r\n}\r\n\r\nexport function oddmisc(options: OddmiscIntegrationOptions = {}): AstroIntegration {\r\n  return {\r\n    name: 'oddmisc-integration',\r\n    hooks: {\r\n      'astro:config:setup': ({ injectScript }: AstroConfigSetupParams) => {\r\n        if (options.umami) {\r\n          const code = injectUmamiRuntime(options.umami.shareUrl);\r\n          if (code) injectScript('page', code);\r\n        }\r\n      }\r\n    }\r\n  };\r\n}\r\n","/**\r\n * 浏览器运行时客户端（IIFE 内联注入，不能有外部 import）。\r\n */\r\n\r\nconst DEFAULT_TIMEOUT = 10000;\r\nconst SHARE_CONTEXT_HEADER = 'x-umami-share-context';\r\nconst SHARE_CONTEXT_VALUE = '1';\r\nconst CACHE_TTL = 3600000;\r\nconst CACHE_MAX = 100;\r\nconst RANGE_ALIGN_MS = 5 * 60_000;\r\n\r\n// --- utils ---\r\n\r\nasync function fetchWithTimeout(url: string, options?: RequestInit, timeout = DEFAULT_TIMEOUT): Promise<Response> {\r\n  const controller = new AbortController();\r\n  const timeoutId = setTimeout(() => controller.abort(), timeout);\r\n  try {\r\n    return await fetch(url, { ...options, signal: controller.signal });\r\n  } catch (err) {\r\n    if (err instanceof DOMException && err.name === 'AbortError') {\r\n      throw new Error(`[oddmisc] 请求超时 (${timeout}ms): ${url}`);\r\n    }\r\n    throw err;\r\n  } finally {\r\n    clearTimeout(timeoutId);\r\n  }\r\n}\r\n\r\nfunction extract(field: unknown): number {\r\n  if (typeof field === 'number') return field;\r\n  if (field && typeof (field as { value?: unknown }).value === 'number') {\r\n    return (field as { value: number }).value;\r\n  }\r\n  return 0;\r\n}\r\n\r\nfunction parseShareUrl(shareUrl: string): { apiBase: string; shareId: string } {\r\n  const url = new URL(shareUrl);\r\n  const pathParts = url.pathname.split('/');\r\n  const shareIndex = pathParts.indexOf('share');\r\n  if (shareIndex === -1 || shareIndex === pathParts.length - 1) {\r\n    throw new Error('无效的分享 URL：未找到 share 路径');\r\n  }\r\n  const shareId = pathParts[shareIndex + 1];\r\n  if (!shareId) throw new Error('无效的分享 URL：缺少分享 ID');\r\n  const pathBeforeShare = pathParts.slice(0, shareIndex).join('/');\r\n  return { apiBase: `${url.protocol}//${url.host}${pathBeforeShare}/api`, shareId };\r\n}\r\n\r\nfunction alignedNow(): number {\r\n  return Math.floor(Date.now() / RANGE_ALIGN_MS) * RANGE_ALIGN_MS;\r\n}\r\n\r\n// --- cache ---\r\n\r\nclass SimpleCache {\r\n  private cache = new Map<string, { value: unknown; timestamp: number }>();\r\n\r\n  constructor(private readonly storageKey: string, private readonly ttl: number, private readonly maxEntries = CACHE_MAX) {\r\n    this.loadFromStorage();\r\n  }\r\n\r\n  private loadFromStorage(): void {\r\n    try {\r\n      const stored = localStorage.getItem(this.storageKey);\r\n      if (!stored) return;\r\n      const parsed = JSON.parse(stored) as Record<string, { value: unknown; timestamp: number }>;\r\n      for (const [key, entry] of Object.entries(parsed)) {\r\n        if (entry && typeof entry.timestamp === 'number' && !this.isExpired(entry.timestamp)) {\r\n          this.cache.set(key, entry);\r\n        }\r\n      }\r\n    } catch { /* ignore */ }\r\n  }\r\n\r\n  private saveToStorage(): void {\r\n    try {\r\n      const obj: Record<string, { value: unknown; timestamp: number }> = {};\r\n      this.cache.forEach((v, k) => { obj[k] = v; });\r\n      localStorage.setItem(this.storageKey, JSON.stringify(obj));\r\n    } catch { /* ignore */ }\r\n  }\r\n\r\n  private isExpired(timestamp: number): boolean {\r\n    return Date.now() - timestamp >= this.ttl;\r\n  }\r\n\r\n  private evictIfNeeded(): void {\r\n    if (this.cache.size <= this.maxEntries) return;\r\n    const entries = [...this.cache.entries()].sort((a, b) => a[1].timestamp - b[1].timestamp);\r\n    const toRemove = entries.length - this.maxEntries;\r\n    for (let i = 0; i < toRemove; i++) this.cache.delete(entries[i][0]);\r\n    this.saveToStorage();\r\n  }\r\n\r\n  get(key: string): unknown | null {\r\n    const cached = this.cache.get(key);\r\n    if (cached && !this.isExpired(cached.timestamp)) return cached.value;\r\n    if (cached) { this.cache.delete(key); this.saveToStorage(); }\r\n    return null;\r\n  }\r\n\r\n  set(key: string, value: unknown): void {\r\n    this.cache.set(key, { value, timestamp: Date.now() });\r\n    this.saveToStorage();\r\n    this.evictIfNeeded();\r\n  }\r\n\r\n  clear(): void {\r\n    this.cache.clear();\r\n    try { localStorage.removeItem(this.storageKey); } catch { /* ignore */ }\r\n  }\r\n}\r\n\r\n// --- types ---\r\n\r\ninterface UmamiRuntimeConfig { shareUrl: string | false; }\r\ninterface StatsResult {\r\n  pageviews: number; visitors: number; visits: number;\r\n  bounces?: number; totaltime?: number; _fromCache?: boolean;\r\n}\r\ninterface ShareData { websiteId: string; token: string; }\r\n\r\n// --- client ---\r\n\r\nclass UmamiRuntimeClient {\r\n  private apiBase: string;\r\n  private shareId: string;\r\n  private cache: SimpleCache;\r\n  private shareData: ShareData | null = null;\r\n  private sharePromise: Promise<ShareData> | null = null;\r\n\r\n  constructor(config: UmamiRuntimeConfig) {\r\n    if (!config.shareUrl) throw new Error('shareUrl 是必需参数');\r\n    const { apiBase, shareId } = parseShareUrl(config.shareUrl);\r\n    this.apiBase = apiBase;\r\n    this.shareId = shareId;\r\n    this.cache = new SimpleCache(`umami-runtime-${shareId}`, CACHE_TTL);\r\n  }\r\n\r\n  private async getShareData(): Promise<ShareData> {\r\n    if (this.shareData) return this.shareData;\r\n    if (this.sharePromise) return this.sharePromise;\r\n    this.sharePromise = (async (): Promise<ShareData> => {\r\n      const res = await fetchWithTimeout(`${this.apiBase}/share/${this.shareId}`);\r\n      if (!res.ok) {\r\n        this.shareData = null;\r\n        this.sharePromise = null;\r\n        throw new Error(`获取分享信息失败: ${res.status}`);\r\n      }\r\n      const data = (await res.json()) as ShareData;\r\n      this.shareData = data;\r\n      return data;\r\n    })();\r\n    return this.sharePromise;\r\n  }\r\n\r\n  private async authedFetch<T>(path: string): Promise<T> {\r\n    const { websiteId, token } = await this.getShareData();\r\n    const res = await fetchWithTimeout(`${this.apiBase}/websites/${websiteId}${path}`, {\r\n      headers: { 'x-umami-share-token': token, [SHARE_CONTEXT_HEADER]: SHARE_CONTEXT_VALUE }\r\n    });\r\n    if (!res.ok) {\r\n      if (res.status === 401) { this.shareData = null; this.sharePromise = null; }\r\n      throw new Error(`请求 ${path} 失败: ${res.status}`);\r\n    }\r\n    return (await res.json()) as T;\r\n  }\r\n\r\n  async getStats(path?: string): Promise<StatsResult> {\r\n    const endAt = alignedNow();\r\n    const cacheKey = `${path ? `stats-${path}` : 'stats-site'}-${endAt}`;\r\n    const cached = this.cache.get(cacheKey) as StatsResult | null;\r\n    if (cached) return { ...cached, _fromCache: true };\r\n\r\n    const params = new URLSearchParams({ startAt: '0', endAt: endAt.toString() });\r\n    if (path) params.set('path', `eq.${path}`);\r\n\r\n    const data = await this.authedFetch<Record<string, unknown>>(`/stats?${params.toString()}`);\r\n    const result: StatsResult = {\r\n      pageviews: extract(data.pageviews),\r\n      visitors: extract(data.visitors),\r\n      visits: extract(data.visits)\r\n    };\r\n    if (data.bounces !== undefined) result.bounces = extract(data.bounces);\r\n    if (data.totaltime !== undefined) result.totaltime = extract(data.totaltime);\r\n    this.cache.set(cacheKey, result);\r\n    return result;\r\n  }\r\n\r\n  getSiteStats(): Promise<StatsResult> { return this.getStats(); }\r\n  getPageStats(path: string): Promise<StatsResult> { return this.getStats(path); }\r\n\r\n  async getActiveVisitors(): Promise<number> {\r\n    const data = await this.authedFetch<{ visitors?: number }>('/active');\r\n    return typeof data?.visitors === 'number' ? data.visitors : 0;\r\n  }\r\n\r\n  clearCache(): void {\r\n    this.cache.clear();\r\n    this.shareData = null;\r\n    this.sharePromise = null;\r\n  }\r\n}\r\n\r\n// --- mount ---\r\n\r\nfunction mountEmptyClient(): void {\r\n  const zeroStats = () => Promise.resolve({ pageviews: 0, visitors: 0, visits: 0 });\r\n  (window as typeof window & { oddmisc?: Record<string, unknown> }).oddmisc = {\r\n    getStats: zeroStats, getSiteStats: zeroStats, getPageStats: zeroStats,\r\n    getActiveVisitors: () => Promise.resolve(0), clearCache: () => {}\r\n  };\r\n}\r\n\r\nexport function initUmamiRuntime(config: UmamiRuntimeConfig): void {\r\n  if (!config.shareUrl) {\r\n    console.log('[oddmisc] shareUrl 未配置，跳过初始化');\r\n    mountEmptyClient();\r\n  } else {\r\n    try {\r\n      const client = new UmamiRuntimeClient(config);\r\n      (window as typeof window & { oddmisc?: Record<string, unknown> }).oddmisc = {\r\n        umami: client,\r\n        getStats: (path?: string) => client.getStats(path),\r\n        getSiteStats: () => client.getSiteStats(),\r\n        getPageStats: (path: string) => client.getPageStats(path),\r\n        getActiveVisitors: () => client.getActiveVisitors(),\r\n        clearCache: () => client.clearCache()\r\n      };\r\n      console.log('[oddmisc] Umami runtime client initialized');\r\n    } catch (error) {\r\n      console.warn('[oddmisc] 初始化失败:', error instanceof Error ? error.message : error);\r\n      mountEmptyClient();\r\n    }\r\n  }\r\n\r\n  window.dispatchEvent(\r\n    new CustomEvent('oddmisc-ready', {\r\n      detail: { client: (window as typeof window & { oddmisc?: Record<string, unknown> }).oddmisc }\r\n    })\r\n  );\r\n}\r\n\r\nexport type { UmamiRuntimeConfig, StatsResult };\r\n\r\ninterface OddmiscReadyEvent extends CustomEvent {\r\n  detail: {\r\n    client: {\r\n      getStats: (path?: string) => Promise<StatsResult>;\r\n      getSiteStats: () => Promise<StatsResult>;\r\n      getPageStats: (path: string) => Promise<StatsResult>;\r\n      getActiveVisitors: () => Promise<number>;\r\n      clearCache: () => void;\r\n    };\r\n  };\r\n}\r\n\r\nexport type { OddmiscReadyEvent };\r\n"],"mappings":"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","names":["index_exports","__export","CacheManager","UmamiAuthError","UmamiClient","UmamiError","UmamiNetworkError","UmamiTimeoutError","UmamiUrlError","VERSION","createUmamiClient","initUmamiRuntime","oddmisc","parseShareUrl","umami","__toCommonJS","VERSION","UmamiError","message","code","status","UmamiUrlError","UmamiAuthError","UmamiNetworkError","UmamiTimeoutError","isBrowser","DEFAULT_MAX_ENTRIES","CacheManager","namespace","ttl","maxEntries","cached","e","timestamp","entries","b","toRemove","storage","i","key","memCached","stored","value","entry","DEFAULT_TIMEOUT","fetchWithTimeout","url","options","timeout","controller","timeoutId","err","UmamiTimeoutError","SHARE_CONTEXT_HEADER","SHARE_CONTEXT_VALUE","RANGE_ALIGN_MS","UmamiAPI","cacheManager","baseUrl","shareId","key","promise","err","res","fetchWithTimeout","UmamiNetworkError","path","token","UmamiAuthError","cacheKey","cached","data","range","params","websiteId","startAt","endAt","qp","cacheQp","type","parseShareUrl","shareUrl","url","pathParts","shareIndex","UmamiUrlError","shareId","pathBeforeShare","error","extractValue","field","toStatsResult","data","result","UmamiClient","config","UmamiUrlError","apiBase","shareId","parseShareUrl","CacheManager","UmamiAPI","path","options","url","type","createUmamiClient","import_fs","import_url","import_path","import_meta","injectUmamiRuntime","shareUrl","runtimeCode","__dirname","runtimePath","umami","options","injectScript","code","oddmisc","SHARE_CONTEXT_HEADER","fetchWithTimeout","url","options","timeout","controller","timeoutId","err","extract","field","parseShareUrl","shareUrl","pathParts","shareIndex","shareId","pathBeforeShare","alignedNow","SimpleCache","storageKey","ttl","maxEntries","stored","parsed","key","entry","obj","v","k","timestamp","entries","a","b","toRemove","i","cached","value","UmamiRuntimeClient","config","apiBase","res","data","path","websiteId","token","SHARE_CONTEXT_HEADER","endAt","cacheKey","params","result","mountEmptyClient","zeroStats","initUmamiRuntime","client","error"]}