{"version":3,"sources":["../src/client/interceptor.ts"],"sourcesContent":["import type {\n  AxiosInstance,\n  AxiosResponse,\n  InternalAxiosRequestConfig,\n} from \"axios\";\n\ndeclare const __AUTOMOCK_ENABLED__: boolean;\n\nexport type MockBundleData = {\n  enable: boolean;\n  data: unknown;\n  delay?: number;\n  status?: number;\n  isBinary?: boolean;\n};\n\nexport type MockInterceptorOptions = {\n  mockData: Record<string, MockBundleData>;\n  enabled?: boolean | (() => boolean);\n  onMockHit?: (url: string, method: string, mock: MockBundleData) => void;\n  onBypass?: (url: string, method: string, reason: string) => void;\n};\n\ntype MockEnabledState = boolean | undefined;\n\ndeclare global {\n  interface Window {\n    __MOCK_ENABLED__?: MockEnabledState;\n  }\n}\n\nclass MockInterceptor {\n  private options: MockInterceptorOptions;\n\n  constructor(options: MockInterceptorOptions) {\n    this.options = options;\n  }\n\n  private normalizeUrlPath(url: string, baseURL?: string): string {\n    if (!url) return \"\";\n\n    try {\n      const isAbsoluteUrl = /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url);\n      const browserOrigin =\n        typeof window !== \"undefined\" && window.location?.origin\n          ? window.location.origin\n          : \"http://localhost\";\n\n      if (isAbsoluteUrl) {\n        return new URL(url).pathname;\n      }\n\n      if (baseURL) {\n        const normalizedBase = baseURL.endsWith(\"/\") ? baseURL : `${baseURL}/`;\n        const normalizedUrl = url.replace(/^\\/+/, \"\");\n        return new URL(normalizedUrl, normalizedBase).pathname;\n      }\n\n      return new URL(url, browserOrigin).pathname;\n    } catch {\n      return url.split(/[?#]/)[0] || \"\";\n    }\n  }\n\n  /**\n   * Check if mock is enabled\n   */\n  isEnabled(): boolean {\n    // Check runtime flag first\n    if (window.__MOCK_ENABLED__ !== undefined) {\n      return window.__MOCK_ENABLED__;\n    }\n    // Check environment variable\n    if (typeof this.options.enabled === \"function\") {\n      return this.options.enabled();\n    }\n    return this.options.enabled ?? false;\n  }\n\n  /**\n   * Find matching mock data for the request\n   * Supports both formats:\n   * - \"GET /api/v1/asset/xxx\" (HTTP method + URL)\n   * - \"/api/v1/asset/xxx/get.js\" (File path format from automock plugin)\n   */\n  private findMock(url: string, method: string, baseURL?: string): MockBundleData | null {\n    const methodUpper = method.toUpperCase();\n    const methodLower = method.toLowerCase();\n    const normalizedPath = this.normalizeUrlPath(url, baseURL);\n\n    // Try HTTP method + URL format first (for compatibility)\n    const httpMethodKey = `${methodUpper} ${url}`;\n    if (this.options.mockData[httpMethodKey]) {\n      return this.options.mockData[httpMethodKey];\n    }\n\n    const normalizedHttpMethodKey = `${methodUpper} ${normalizedPath}`;\n    if (this.options.mockData[normalizedHttpMethodKey]) {\n      return this.options.mockData[normalizedHttpMethodKey];\n    }\n\n    // Try file path format from automock plugin: /api/v1/asset/xxx/get.js\n    const filePathKey = `${normalizedPath}/${methodLower}.js`;\n    if (this.options.mockData[filePathKey]) {\n      return this.options.mockData[filePathKey];\n    }\n\n    return null;\n  }\n\n  /**\n   * Determine if request should be mocked\n   */\n  shouldMock(url: string, method: string, baseURL?: string): boolean {\n    if (!this.isEnabled()) {\n      return false;\n    }\n\n    const mock = this.findMock(url, method, baseURL);\n    return mock !== null && mock.enable;\n  }\n\n  /**\n   * Get mock data for request\n   */\n  getMock(url: string, method: string, baseURL?: string): MockBundleData | null {\n    if (!this.shouldMock(url, method, baseURL)) {\n      return null;\n    }\n    return this.findMock(url, method, baseURL);\n  }\n\n  /**\n   * Setup axios interceptor\n   */\n  setupAxios(axiosInstance: AxiosInstance): void {\n    axiosInstance.interceptors.request.use(\n      async (config: InternalAxiosRequestConfig) => {\n        const url = config.url || \"\";\n        const method = config.method?.toUpperCase() || \"GET\";\n        const normalizedUrl = this.normalizeUrlPath(url, config.baseURL);\n\n        const mock = this.getMock(url, method, config.baseURL);\n\n        if (mock) {\n          // Trigger mock hit callback\n          this.options.onMockHit?.(normalizedUrl, method, mock);\n\n          // Set adapter to return mock data\n          (config as InternalAxiosRequestConfig & { adapter: () => Promise<AxiosResponse> }).adapter = async () => {\n            const { data, delay = 0, status = 200 } = mock;\n\n            // Simulate delay\n            if (delay > 0) {\n              await new Promise((resolve) => setTimeout(resolve, delay));\n            }\n\n            return {\n              data,\n              status,\n              statusText: \"OK\",\n              headers: {},\n              config,\n            };\n          };\n        } else {\n          // Trigger bypass callback\n          const reason = !this.isEnabled()\n            ? \"Mock disabled globally\"\n            : \"No matching mock found or mock disabled\";\n          this.options.onBypass?.(normalizedUrl, method, reason);\n        }\n\n        return config;\n      },\n      (error: unknown) => Promise.reject(error),\n    );\n  }\n}\n\n/**\n * Create mock interceptor instance\n */\nexport function createMockInterceptor(\n  options: MockInterceptorOptions,\n): MockInterceptor {\n  return new MockInterceptor(options);\n}\n\n/**\n * Load mock data from bundled JSON file\n */\nexport async function loadMockData(): Promise<Record<string, MockBundleData>> {\n  try {\n    // In production, mock-data.json is generated by automock plugin\n    // Use absolute path to load it from dist directory\n    const response = await fetch(\"/mock-data.json\");\n    if (!response.ok) {\n      console.warn(\n        \"[MockInterceptor] Failed to load mock-data.json:\",\n        response.statusText,\n      );\n      return {};\n    }\n    const data = (await response.json()) as Record<string, MockBundleData>;\n    return data;\n  } catch (error) {\n    console.warn(\"[MockInterceptor] Failed to load mock-data.json:\", error);\n    return {};\n  }\n}\n\nasync function createInterceptorFromBundle(): Promise<MockInterceptor> {\n  const mockData = await loadMockData();\n  const isEnabled = typeof __AUTOMOCK_ENABLED__ !== \"undefined\" && __AUTOMOCK_ENABLED__;\n\n  return new MockInterceptor({\n    mockData,\n    enabled: isEnabled,\n    onMockHit: (url: string, method: string) => {\n      console.log(`[MOCK HIT] ${method} ${url}`);\n    },\n    onBypass: (url: string, method: string, reason: string) => {\n      console.log(`[MOCK BYPASS] ${method} ${url} - ${reason}`);\n    },\n  });\n}\n\nexport async function initMockInterceptor(\n  axiosInstance?: AxiosInstance,\n): Promise<void> {\n  if (!axiosInstance) {\n    throw new Error(\n      \"[MockInterceptor] axiosInstance is required. Please provide an axios instance.\",\n    );\n  }\n\n  const interceptor = await createInterceptorFromBundle();\n  interceptor.setupAxios(axiosInstance);\n}\n\nexport function setMockEnabled(enabled: boolean): void {\n  window.__MOCK_ENABLED__ = enabled;\n}\n\nexport function isMockEnabled(): boolean {\n  return !!window.__MOCK_ENABLED__;\n}\n\ntype HttpInstance = {\n  constructor: { axiosInstance: AxiosInstance };\n};\n\nlet httpInstanceRef: HttpInstance | undefined;\n\nexport function registerHttpInstance(http: HttpInstance): void {\n  httpInstanceRef = http;\n}\n\nexport async function initMockInterceptorForPureHttp(): Promise<void> {\n  if (!httpInstanceRef) {\n    throw new Error(\n      \"[MockInterceptor] http instance not registered. Call registerHttpInstance(http) first.\",\n    );\n  }\n\n  const interceptor = await createInterceptorFromBundle();\n  interceptor.setupAxios(httpInstanceRef.constructor.axiosInstance);\n}\n"],"mappings":"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","names":[]}