{"version":3,"file":"fetch-client-VuLKnuMk.mjs","names":[],"sources":["../../../platform/api-client-core/src/api-error-shape.ts","../../../platform/api-client-core/src/fetch-client.ts"],"sourcesContent":["/**\n * The shape contract for `ApiError.body` and `ApiError.data`.\n *\n * One decision, in one place: `body` is the response envelope exactly as the\n * server sent it, `data` is the unwrapped field-error bag. Rationale and the\n * alternatives considered live in `docs/api-error-data-contract.md`.\n */\n\n/**\n * The parsed JSON error response body, exactly as the server sent it.\n *\n * This is the envelope: `errors`, `error_message`, `error`, `status`, `meta`\n * and `request_id` all live here. `null` when the response carried no JSON\n * object — HTML, an empty body, a JSON primitive, or unparseable text.\n */\nexport type ApiErrorBody = Record<string, unknown> | null;\n\n/**\n * The field-level error bag: the envelope's `errors` value when the body has\n * one, otherwise the body itself.\n *\n * `errors` is declared `never` because unwrapping already consumed it — read\n * the envelope from `ApiError.body`, not from here. That makes the historical\n * mistake (`error.data.errors.some_field`, which silently resolved to\n * `undefined`) a typecheck failure instead of a degraded error message.\n */\nexport type ApiErrorFieldErrors = Record<string, unknown> & {\n  errors?: never;\n};\n\n/**\n * Every value `ApiError.data` can hold. Fluid endpoints return an object bag,\n * but `errors` is occasionally an array or a string, and non-JSON responses\n * carry no data at all.\n */\nexport type ApiErrorData =\n  | ApiErrorFieldErrors\n  | readonly unknown[]\n  | string\n  | number\n  | boolean\n  | null;\n\n/**\n * Narrows a parsed JSON error payload to the envelope contract. Arrays and\n * primitives are not envelopes, so they resolve to `null` — their content is\n * still reachable through `ApiError.data`.\n */\nexport function toApiErrorBody(value: unknown): ApiErrorBody {\n  if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n    return null;\n  }\n\n  return value as Record<string, unknown>;\n}\n\n/**\n * The single unwrap rule, shared by every producer of `ApiError`.\n *\n * `??` rather than `||` so an explicitly empty `errors` (`\"\"`, `0`, `false`)\n * is preserved instead of silently falling back to the whole envelope.\n */\nexport function toApiErrorData(body: ApiErrorBody): ApiErrorData {\n  if (!body) {\n    return null;\n  }\n\n  return (body.errors ?? body) as ApiErrorData;\n}\n","/**\n * Minimal, framework-agnostic fetch client for Fluid APIs\n * Compatible with fluid-admin patterns but usable standalone\n */\n\nimport type { ApiErrorBody, ApiErrorData } from \"./api-error-shape\";\nimport { toApiErrorBody, toApiErrorData } from \"./api-error-shape\";\n\nexport interface FetchClientConfig {\n  /**\n   * Base URL for all requests (e.g., \"https://api.fluid.app/api\")\n   */\n  baseUrl: string;\n\n  /**\n   * Optional function to get auth token\n   * Return null/undefined if no token available\n   */\n  getAuthToken?: () => string | null | Promise<string | null>;\n\n  /**\n   * Optional callback when 401 auth error occurs\n   */\n  onAuthError?: () => void;\n\n  /**\n   * Default headers to include in all requests\n   * Example: { \"x-fluid-client\": \"admin\" }\n   */\n  defaultHeaders?: Record<string, string>;\n\n  /**\n   * Credentials mode for fetch requests.\n   * Set to `\"include\"` for cookie-based (same-origin BFF) authentication.\n   * @default undefined (browser default: \"same-origin\")\n   */\n  credentials?: RequestCredentials;\n\n  /**\n   * Request cache mode for fetch requests.\n   * @default undefined (browser default)\n   */\n  cache?: RequestCache;\n\n  /**\n   * Retry configuration for thrown network errors from fetch.\n   * Does not retry HTTP error responses or aborted requests.\n   * @default undefined (no retries)\n   */\n  networkRetry?: {\n    maxRetries?: number;\n    baseDelayMs?: number;\n  };\n\n  /**\n   * Throw ApiError when a successful response declares JSON but cannot be parsed.\n   * Defaults to false to preserve the legacy generated-client behavior.\n   * @default false\n   */\n  throwOnInvalidJson?: boolean;\n}\n\nexport interface RequestOptions {\n  method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\n  headers?: Record<string, string>;\n  params?: Record<string, unknown>;\n  body?: unknown;\n  signal?: AbortSignal;\n  priority?: RequestInit[\"priority\"];\n}\n\n/**\n * API Error class compatible with fluid-admin's ApiError\n */\nexport class ApiError extends Error {\n  public readonly status: number;\n\n  /**\n   * The unwrapped field-error bag. See `ApiErrorData`; the contract is\n   * documented in `docs/api-error-data-contract.md`.\n   */\n  public readonly data: ApiErrorData;\n\n  /**\n   * The full error response envelope. Read `error_message`, `error`, `status`\n   * and nested `errors` from here — `data` has already unwrapped one level.\n   */\n  public readonly body: ApiErrorBody;\n\n  public readonly requestId?: string;\n\n  constructor(\n    message: string,\n    status: number,\n    data?: ApiErrorData,\n    requestId?: string,\n    body?: ApiErrorBody,\n  ) {\n    super(message);\n    this.name = \"ApiError\";\n    this.status = status;\n    this.data = data ?? null;\n    this.body = body ?? null;\n    this.requestId = requestId;\n\n    if (\"captureStackTrace\" in Error) {\n      (\n        Error as {\n          captureStackTrace: (\n            target: Error,\n            constructor: NewableFunction,\n          ) => void;\n        }\n      ).captureStackTrace(this, ApiError);\n    }\n  }\n\n  toJSON(): {\n    name: string;\n    message: string;\n    status: number;\n    data: ApiErrorData;\n    body: ApiErrorBody;\n    requestId?: string;\n  } {\n    return {\n      name: this.name,\n      message: this.message,\n      status: this.status,\n      data: this.data,\n      body: this.body,\n      requestId: this.requestId,\n    };\n  }\n}\n\nfunction getStringRequestId(value: unknown): string | undefined {\n  if (typeof value !== \"string\") {\n    return undefined;\n  }\n\n  const trimmed = value.trim();\n  return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction getRequestIdFromHeaders(headers: Headers): string | undefined {\n  return (\n    getStringRequestId(headers.get(\"x-request-id\")) ??\n    getStringRequestId(headers.get(\"request-id\")) ??\n    getStringRequestId(headers.get(\"X-Request-ID\"))\n  );\n}\n\nfunction getRequestIdFromJsonBody(body: unknown): string | undefined {\n  if (!body || typeof body !== \"object\" || Array.isArray(body)) {\n    return undefined;\n  }\n\n  const record = body as Record<string, unknown>;\n  const meta = record.meta;\n\n  return (\n    getStringRequestId(record.request_id) ??\n    getStringRequestId(record.requestId) ??\n    (meta && typeof meta === \"object\" && !Array.isArray(meta)\n      ? (getStringRequestId((meta as Record<string, unknown>).request_id) ??\n        getStringRequestId((meta as Record<string, unknown>).requestId))\n      : undefined)\n  );\n}\n\n/**\n * Type guard for ApiError\n */\nexport function isApiError(error: unknown): error is ApiError {\n  return error instanceof ApiError;\n}\n\nexport interface FetchClientInstance {\n  request: <TResponse = unknown>(\n    endpoint: string,\n    options?: RequestOptions,\n  ) => Promise<TResponse>;\n  requestWithFormData: <TResponse = unknown>(\n    endpoint: string,\n    formData: FormData,\n    options?: Omit<RequestOptions, \"body\" | \"params\"> & {\n      method?: \"POST\" | \"PUT\" | \"PATCH\";\n    },\n  ) => Promise<TResponse>;\n  get: <TResponse = unknown>(\n    endpoint: string,\n    params?: Record<string, unknown>,\n    options?: Omit<RequestOptions, \"method\" | \"params\">,\n  ) => Promise<TResponse>;\n  post: <TResponse = unknown>(\n    endpoint: string,\n    body?: unknown,\n    options?: Omit<RequestOptions, \"method\" | \"body\">,\n  ) => Promise<TResponse>;\n  put: <TResponse = unknown>(\n    endpoint: string,\n    body?: unknown,\n    options?: Omit<RequestOptions, \"method\" | \"body\">,\n  ) => Promise<TResponse>;\n  patch: <TResponse = unknown>(\n    endpoint: string,\n    body?: unknown,\n    options?: Omit<RequestOptions, \"method\" | \"body\">,\n  ) => Promise<TResponse>;\n  delete: <TResponse = unknown>(\n    endpoint: string,\n    options?: Omit<RequestOptions, \"method\">,\n  ) => Promise<TResponse>;\n}\n\n/**\n * Creates a configured fetch client instance\n */\nexport function createFetchClient(\n  config: FetchClientConfig,\n): FetchClientInstance {\n  const {\n    baseUrl,\n    getAuthToken,\n    onAuthError,\n    defaultHeaders = {},\n    credentials,\n    cache,\n    networkRetry,\n    throwOnInvalidJson = false,\n  } = config;\n  const maxNetworkRetries = Math.max(0, networkRetry?.maxRetries ?? 0);\n  const baseNetworkRetryDelayMs = Math.max(0, networkRetry?.baseDelayMs ?? 0);\n\n  /**\n   * Build headers for a request\n   */\n  async function buildHeaders(\n    customHeaders?: Record<string, string>,\n  ): Promise<Record<string, string>> {\n    const headers: Record<string, string> = {\n      Accept: \"application/json\",\n      \"Content-Type\": \"application/json\",\n      ...defaultHeaders,\n      ...customHeaders,\n    };\n\n    // Add auth token if available\n    if (getAuthToken) {\n      const token = await getAuthToken();\n      if (token) {\n        headers.Authorization = `Bearer ${token}`;\n      }\n    }\n\n    return headers;\n  }\n\n  /**\n   * Join baseUrl + endpoint via string concatenation (matches fetchApi).\n   * Using `new URL(endpoint, baseUrl)` would strip any path prefix from\n   * baseUrl (e.g. \"/api\") when the endpoint starts with \"/\".\n   */\n  function joinUrl(endpoint: string): string {\n    return `${baseUrl}${endpoint}`;\n  }\n\n  /**\n   * Build URL with query parameters for GET requests\n   * Compatible with fluid-admin's query param handling\n   */\n  function buildUrl(\n    endpoint: string,\n    params?: Record<string, unknown>,\n  ): string {\n    const fullUrl = joinUrl(endpoint);\n\n    if (!params || Object.keys(params).length === 0) {\n      return fullUrl;\n    }\n\n    const queryString = new URLSearchParams();\n\n    Object.entries(params).forEach(([key, value]) => {\n      if (value === undefined || value === null) {\n        return; // Skip undefined/null values\n      }\n\n      if (Array.isArray(value)) {\n        // Handle arrays like Rails expects: key[]\n        value.forEach((item) => queryString.append(`${key}[]`, String(item)));\n      } else if (typeof value === \"object\") {\n        // Handle nested objects: key[subkey]\n        Object.entries(value).forEach(([subKey, subValue]) => {\n          if (subValue === undefined || subValue === null) {\n            return;\n          }\n\n          if (Array.isArray(subValue)) {\n            subValue.forEach((item) =>\n              queryString.append(`${key}[${subKey}][]`, String(item)),\n            );\n          } else {\n            queryString.append(`${key}[${subKey}]`, String(subValue));\n          }\n        });\n      } else {\n        queryString.append(key, String(value));\n      }\n    });\n\n    const qs = queryString.toString();\n    return qs ? `${fullUrl}?${qs}` : fullUrl;\n  }\n\n  /**\n   * Shared response handler for both JSON and FormData requests.\n   * Handles auth errors, non-OK responses, 204 No Content, and JSON parsing.\n   */\n  async function handleResponse<TResponse>(\n    response: Response,\n    method: string,\n    _url: string,\n  ): Promise<TResponse> {\n    const headerRequestId = getRequestIdFromHeaders(response.headers);\n\n    if (response.status === 401 && onAuthError) {\n      onAuthError();\n    }\n\n    if (!response.ok) {\n      // Read body as text first to avoid SyntaxError from response.json()\n      // when server returns non-JSON bodies with application/json content-type.\n      const errorText = await response.text().catch(() => \"\");\n      const contentType = response.headers.get(\"content-type\");\n\n      if (contentType?.includes(\"application/json\")) {\n        // Parsed as `unknown` and narrowed before any property read: a body of\n        // `null` (or a bare string/number/array) is valid JSON, and reading\n        // `.error` off it directly threw a TypeError instead of an ApiError.\n        let parsed: unknown;\n        try {\n          parsed = JSON.parse(errorText);\n        } catch {\n          throw new ApiError(\n            errorText.slice(0, 200) ||\n              `${method} request failed with status ${response.status}`,\n            response.status,\n            null,\n            headerRequestId,\n          );\n        }\n\n        const body = toApiErrorBody(parsed);\n        // Only an object envelope can carry a message. Some Rails BFF endpoints\n        // return `{ error: { message, details } }` instead of `{ message }` or\n        // `{ error_message }`, so that shape is tried last.\n        const msg = body\n          ? (() => {\n              const nestedError =\n                typeof body.error === \"object\" && body.error !== null\n                  ? (body.error as { message?: unknown }).message\n                  : undefined;\n              const directError =\n                typeof body.error === \"string\" ? body.error : undefined;\n              const message =\n                typeof body.message === \"string\" ? body.message : undefined;\n              const errorMessage =\n                typeof body.error_message === \"string\"\n                  ? body.error_message\n                  : undefined;\n              return (\n                message ||\n                errorMessage ||\n                directError ||\n                (typeof nestedError === \"string\" ? nestedError : undefined)\n              );\n            })()\n          : undefined;\n\n        throw new ApiError(\n          msg || `${method} request failed with status ${response.status}`,\n          response.status,\n          body ? toApiErrorData(body) : (parsed as ApiErrorData),\n          headerRequestId ?? getRequestIdFromJsonBody(parsed),\n          body,\n        );\n      } else {\n        throw new ApiError(\n          `${method} request failed with status ${response.status}`,\n          response.status,\n          null,\n          headerRequestId,\n        );\n      }\n    }\n\n    if (\n      response.status === 204 ||\n      response.headers.get(\"content-length\") === \"0\"\n    ) {\n      return null as TResponse;\n    }\n\n    const contentType = response.headers.get(\"content-type\");\n\n    if (contentType?.includes(\"application/json\")) {\n      const responseText = await response.text();\n\n      try {\n        const data = JSON.parse(responseText);\n        return data as TResponse;\n      } catch {\n        if (throwOnInvalidJson) {\n          throw new ApiError(\n            \"Failed to parse response as JSON\",\n            response.status,\n            null,\n            headerRequestId,\n          );\n        }\n\n        // API declared JSON content-type but body isn't valid JSON.\n        // Return the raw payload to preserve the legacy non-strict path.\n        return responseText ? (responseText as TResponse) : (null as TResponse);\n      }\n    }\n\n    // Non-JSON response (text/plain, text/html, etc.)\n    return null as TResponse;\n  }\n\n  function getNetworkRetryDelayMs(retryAttempt: number): number {\n    return baseNetworkRetryDelayMs * 2 ** (retryAttempt - 1);\n  }\n\n  async function waitForNetworkRetry(retryAttempt: number): Promise<void> {\n    const delayMs = getNetworkRetryDelayMs(retryAttempt);\n    if (delayMs <= 0) {\n      return;\n    }\n\n    await new Promise((resolve) => setTimeout(resolve, delayMs));\n  }\n\n  async function fetchWithNetworkRetry(\n    url: string,\n    fetchOptions: RequestInit,\n    signal?: AbortSignal,\n  ): Promise<Response> {\n    let retryCount = 0;\n\n    while (true) {\n      try {\n        return await fetch(url, fetchOptions);\n      } catch (networkError) {\n        if (signal?.aborted || retryCount >= maxNetworkRetries) {\n          throw networkError;\n        }\n\n        retryCount += 1;\n        await waitForNetworkRetry(retryCount);\n\n        if (signal?.aborted) {\n          throw networkError;\n        }\n      }\n    }\n  }\n\n  /**\n   * Main request function\n   */\n  async function request<TResponse = unknown>(\n    endpoint: string,\n    options: RequestOptions = {},\n  ): Promise<TResponse> {\n    const {\n      method = \"GET\",\n      headers: customHeaders,\n      params,\n      body,\n      signal,\n      priority,\n    } = options;\n\n    const url = params ? buildUrl(endpoint, params) : joinUrl(endpoint);\n\n    const headers = await buildHeaders(customHeaders);\n\n    let response: Response;\n\n    try {\n      const fetchOptions: RequestInit = { method, headers };\n      if (credentials) fetchOptions.credentials = credentials;\n      if (cache) fetchOptions.cache = cache;\n      if (priority) fetchOptions.priority = priority;\n      const serializedBody =\n        body && method !== \"GET\" ? JSON.stringify(body) : null;\n      if (serializedBody) fetchOptions.body = serializedBody;\n      if (signal) fetchOptions.signal = signal;\n      response = await fetchWithNetworkRetry(url, fetchOptions, signal);\n    } catch (networkError) {\n      throw new ApiError(\n        `Network error: ${networkError instanceof Error ? networkError.message : \"Unknown network error\"}`,\n        0,\n        null,\n      );\n    }\n\n    return handleResponse<TResponse>(response, method, url);\n  }\n\n  /**\n   * Request with FormData (for file uploads)\n   */\n  async function requestWithFormData<TResponse = unknown>(\n    endpoint: string,\n    formData: FormData,\n    options: Omit<RequestOptions, \"body\" | \"params\"> & {\n      method?: \"POST\" | \"PUT\" | \"PATCH\";\n    } = {},\n  ): Promise<TResponse> {\n    const {\n      method = \"POST\",\n      headers: customHeaders,\n      signal,\n      priority,\n    } = options;\n\n    const url = joinUrl(endpoint);\n    const headers = await buildHeaders(customHeaders);\n\n    // Remove Content-Type to let browser set it with boundary\n    delete headers[\"Content-Type\"];\n\n    let response: Response;\n\n    try {\n      const fetchOptions: RequestInit = { method, headers, body: formData };\n      if (credentials) fetchOptions.credentials = credentials;\n      if (cache) fetchOptions.cache = cache;\n      if (priority) fetchOptions.priority = priority;\n      if (signal) fetchOptions.signal = signal;\n      response = await fetchWithNetworkRetry(url, fetchOptions, signal);\n    } catch (networkError) {\n      throw new ApiError(\n        `Network error: ${networkError instanceof Error ? networkError.message : \"Unknown network error\"}`,\n        0,\n        null,\n      );\n    }\n\n    return handleResponse<TResponse>(response, method, url);\n  }\n\n  // Return client with convenience methods\n  return {\n    request: request,\n    requestWithFormData: requestWithFormData,\n\n    // Convenience methods for common HTTP verbs\n    get: <TResponse = unknown>(\n      endpoint: string,\n      params?: Record<string, unknown>,\n      options?: Omit<RequestOptions, \"method\" | \"params\">,\n    ): Promise<TResponse> =>\n      request<TResponse>(endpoint, {\n        ...options,\n        method: \"GET\" as const,\n        ...(params && { params }),\n      }),\n\n    post: <TResponse = unknown>(\n      endpoint: string,\n      body?: unknown,\n      options?: Omit<RequestOptions, \"method\" | \"body\">,\n    ): Promise<TResponse> =>\n      request<TResponse>(endpoint, {\n        ...options,\n        method: \"POST\",\n        body,\n      }),\n\n    put: <TResponse = unknown>(\n      endpoint: string,\n      body?: unknown,\n      options?: Omit<RequestOptions, \"method\" | \"body\">,\n    ): Promise<TResponse> =>\n      request<TResponse>(endpoint, {\n        ...options,\n        method: \"PUT\",\n        body,\n      }),\n\n    patch: <TResponse = unknown>(\n      endpoint: string,\n      body?: unknown,\n      options?: Omit<RequestOptions, \"method\" | \"body\">,\n    ): Promise<TResponse> =>\n      request<TResponse>(endpoint, {\n        ...options,\n        method: \"PATCH\",\n        body,\n      }),\n\n    delete: <TResponse = unknown>(\n      endpoint: string,\n      options?: Omit<RequestOptions, \"method\">,\n    ): Promise<TResponse> =>\n      request<TResponse>(endpoint, {\n        ...options,\n        method: \"DELETE\",\n      }),\n  };\n}\n\nexport type FetchClient = FetchClientInstance;\n"],"mappings":"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"}