{"version":3,"file":"index.mjs","names":["queryOptions: RequestInit","errorBody: { error?: { message?: string; details?: unknown } }","queryOptions: RequestInit"],"sources":["../src/validator.ts","../src/config.ts","../src/invoke.ts","../src/summon-json.ts","../src/utils.ts","../src/summon.ts","../src/whisper.ts"],"sourcesContent":["/**\n * Check whether a fetch Response appears to be JSON via content-type header.\n */\nexport function isResponseJson(response: Response): boolean {\n  const contentType = response.headers.get(\"content-type\")\n  if (contentType && contentType.includes(\"application/json\")) return true\n  else return false\n}\n","/**\n * Global configuration for the fetcher utilities.\n *\n * Configure this once at app startup via {@link configureCrane} or {@link setBaseURL}.\n * Consumers can also rely on environment variables or a global hint\n * `window.__CRANE_BE_BASE_URL` as a fallback.\n */\nexport type ConjuraConfig = {\n  /** Base URL for backend API requests, e.g. https://api.example.com */\n  baseURL?: string\n  /** Default headers to apply to every request (merged, user overrides last) */\n  defaultHeaders?: Record<string, string>\n  /** Optional custom fetch implementation (SSR, tests) */\n  fetchImpl?: typeof fetch\n}\n\ntype GlobalWithConjura = typeof globalThis & {\n  __SIGIL_CONFIG__?: ConjuraConfig\n}\n\nfunction getGlobal(): GlobalWithConjura {\n  return globalThis as GlobalWithConjura\n}\n\nfunction storage(): ConjuraConfig {\n  const g = getGlobal()\n  if (!g.__SIGIL_CONFIG__) g.__SIGIL_CONFIG__ = {}\n  return g.__SIGIL_CONFIG__!\n}\n\n/**\n * Merge and set global configuration.\n * Repeated calls will shallow-merge with the previous configuration.\n */\nexport function configureConjura(cfg: Partial<ConjuraConfig>) {\n  Object.assign(storage(), cfg)\n}\n\nexport function setBaseURL(baseURL: string) {\n  storage().baseURL = baseURL\n}\n\nexport function getConjuraConfig(): Readonly<ConjuraConfig> {\n  return storage()\n}\n\n/**\n * Resolve a base URL from (in order):\n * 1) explicitly configured config.baseURL\n * 2) runtime globals like window.__CRANE_BE_BASE_URL\n * 3) env-style values (import.meta.env.*, process.env.*)\n */\n/**\n * Resolve the base URL to be used for requests.\n *\n * Priority order:\n * 1) Explicitly configured via {@link configureCrane} or {@link setBaseURL}\n * 2) Runtime global hint `window.__CRANE_BE_BASE_URL`\n * 3) Node.js environment variables (CRANE_BASE_URL, API_BASE_URL, etc.)\n * 4) Vite `import.meta.env` variables (VITE_BE_CORE_URL, etc.)\n */\nexport function getBaseURL(): string | undefined {\n  const cfg = storage()\n  if (cfg.baseURL) return cfg.baseURL\n\n  // 2) window/global hints\n  const hinted = (globalThis as any).__SIGIL_BE_BASE_URL as string | undefined\n  if (typeof hinted === \"string\" && hinted.length > 0) return hinted\n\n  // 3) Prefer Node envs first (avoids CJS import.meta warnings in practice)\n  const penv = (globalThis as any).process?.env as\n    | Record<string, string | undefined>\n    | undefined\n  if (penv) {\n    const v =\n      penv.VITE_BE_CORE_URL ||\n      penv.SIGIL_BASE_URL ||\n      penv.BE_CORE_URL ||\n      penv.API_BASE_URL\n    if (v) return v\n  }\n\n  // 4) Vite envs (guarded)\n  try {\n    if (typeof import.meta !== \"undefined\" && (import.meta as any).env) {\n      const env = (import.meta as any).env as Record<string, string | undefined>\n      const v =\n        env.VITE_BE_CORE_URL ||\n        env.VITE_BE_URL ||\n        env.VITE_API_BASE_URL ||\n        env.VITE_BASE_URL\n      if (v) return v\n    }\n  } catch {\n    // ignore\n  }\n\n  return undefined\n}\n\n/**\n * Get the fetch implementation (configured or global).\n */\nexport function getFetchImpl(): typeof fetch {\n  return storage().fetchImpl || globalThis.fetch.bind(globalThis)\n}\n\n/**\n * Testing helper: reset all configuration.\n * Not intended for production use.\n */\nexport function resetConjuraConfig() {\n  const g = getGlobal()\n  g.__SIGIL_CONFIG__ = {}\n}\n","import { FEError } from \"derbis\"\nimport { isResponseJson } from \"./validator\"\nimport { getBaseURL, getFetchImpl, getConjuraConfig } from \"./config\"\nimport type { Method, InvokeOptions, BEGenericResponse } from \"./types\"\n\n/**\n * Low-level HTTP invocation for backend requests.\n * - Returns either `{ data: T }` or a backend `{ error }` envelope.\n * - Does not throw on backend error; callers decide how to handle it.\n */\nexport async function invoke<T>(\n  pathAPI: string,\n  method: Method,\n  errCode: string,\n  options?: InvokeOptions\n): Promise<BEGenericResponse<T> | undefined> {\n  const headers = new Headers()\n  // Merge default headers from global config first\n  const defaults = getConjuraConfig().defaultHeaders\n  if (defaults) {\n    for (const [k, v] of Object.entries(defaults)) headers.set(k, v)\n  }\n  headers.append(\"Accept\", \"application/json\")\n  headers.append(\"Content-Type\", \"application/json\")\n  if (options?.authKey)\n    headers.append(\"Authorization\", `Bearer ${options?.authKey}`)\n  // SSR-only headers and cookie forwarding\n  if (typeof window === \"undefined\") {\n    headers.append(\"x-ssr\", \"true\")\n    if (\n      options?.cookie &&\n      typeof options.cookie === \"object\" &&\n      Object.keys(options.cookie).length > 0\n    ) {\n      // Always format cookies as: foo=bar; baz=qux\n      const cookieStr = Object.entries(options.cookie)\n        .map(([k, v]) => `${k}=${v}`)\n        .join(\"; \")\n      headers.append(\"Cookie\", cookieStr)\n    }\n  }\n\n  const queryOptions: RequestInit = {\n    method,\n    headers,\n    credentials: \"include\"\n  }\n\n  if (options?.payload) queryOptions.body = JSON.stringify(options?.payload)\n\n  const resolvedBase = options?.baseURL || getBaseURL()\n  if (!resolvedBase) {\n    throw new FEError(\n      \"BASE_URL_NOT_SET\",\n      \"Base URL is not configured. Call configureCrane({ baseURL }) once, or set VITE_BE_CORE_URL/CRANE_BASE_URL env.\",\n      errCode\n    )\n  }\n  const base = String(resolvedBase).replace(/\\/+$/, \"\")\n  const p = pathAPI.startsWith(\"/\") ? pathAPI : `/${pathAPI}`\n  const url = new URL(base + p)\n\n  if (options && options.query) {\n    const query = options.query\n    const params = new URLSearchParams()\n    Object.keys(query).forEach((key) => {\n      const value = query[key]\n      if (Array.isArray(value)) {\n        value.forEach((item) => params.append(key, item.toString()))\n      } else {\n        params.append(key, value.toString())\n      }\n    })\n    url.search = params.toString()\n  }\n\n  const response = await getFetchImpl()(url.toString(), queryOptions)\n\n  if (!isResponseJson(response)) {\n    if (!response.ok) {\n      // Check for important HTTP status codes before processing JSON\n      // Try to parse error details from response body if possible\n      let errorBody: { error?: { message?: string; details?: unknown } } = {}\n      try {\n        if (isResponseJson(response)) {\n          errorBody = await response.json()\n        }\n      } catch {\n        // ignore JSON parse errors here\n      }\n\n      throw new FEError(\n        `HTTP_${response.status}`,\n        errorBody?.error?.message || response.statusText || \"HTTP error\",\n        errCode,\n        errorBody?.error?.details as Record<string, string | number> | undefined\n      )\n    } else {\n      throw new FEError(\"INVALID_JSON\", \"Invalid JSON response\", errCode)\n    }\n  }\n\n  const data = await response.json()\n\n  if (data && typeof data === \"object\") {\n    if (\"data\" in data) {\n      return data\n    } else if (\"error\" in data) {\n      return data\n    }\n  } else {\n    throw new FEError(\n      \"INVALID_STRUCTURE\",\n      \"Invalid response structure\",\n      errCode\n    )\n  }\n}\n","import { FEError } from \"derbis\"\n\n/**\n * Utility function to fetch static JSON .\n *\n * Path must begin with complete URL including domain.\n * `.json` extension is not required.\n * - Correct: `https://example.com/data/file`.\n * - Wrong: `https://example.com/data/file.json`\n * - Wrong: `/data/file`\n */\nexport async function summonJSON<T = unknown>(\n  path: string,\n  errCode = \"summonJSON\"\n): Promise<T> {\n  const url = new URL(`${path}.json`)\n\n  const response = await fetch(url, {\n    method: \"GET\",\n    headers: {\n      Accept: \"application/json\"\n    }\n  })\n\n  if (!response.ok) {\n    throw new FEError(\n      \"FETCH_JSON_FAILED\",\n      `Failed to fetch JSON: ${url} (${response.status} ${response.statusText})`,\n      errCode\n    )\n  }\n\n  try {\n    return await response.json()\n  } catch {\n    throw new FEError(\"JSON_INVALID\", `Invalid JSON in ${url}`, errCode)\n  }\n}\n","import { BEError, BEErrorRespone, BEMultiError } from \"derbis\"\n\n/**\n * Convert a backend error envelope into a typed exception.\n * - If the backend returned multiple errors, throws a {@link BEMultiError}.\n * - Otherwise throws a single {@link BEError}.\n */\nexport function handleSummonError(response: BEErrorRespone) {\n  if (Array.isArray(response.error)) {\n    throw new BEMultiError(response.error)\n  } else {\n    throw new BEError(\n      response.error.code,\n      response.error.message,\n      response.error.status,\n      response.error.source,\n      response.error.details\n    )\n  }\n}\n","import { FEError } from \"derbis\"\nimport { invoke } from \"./invoke\"\nimport { handleSummonError } from \"./utils\"\nimport type { Method, SummonOptions } from \"./types\"\n\n/**\n * High-level helper for backend requests that returns the `data` field\n * or throws a rich error when the backend responds with an error envelope.\n */\nexport async function summon<T>(\n  pathAPI: string,\n  method: Method,\n  errCode: string,\n  options?: SummonOptions\n): Promise<T | undefined> {\n  const response = await invoke<T>(pathAPI, method, errCode, { ...options })\n\n  if (!response)\n    throw new FEError(\"RES_NONE\", \"No response from backend\", errCode)\n\n  if (\"data\" in response) {\n    return response.data\n  } else if (\"error\" in response) {\n    handleSummonError(response)\n  } else {\n    throw new FEError(\n      \"INVALID_STRUCTURE\",\n      \"Invalid response structure\",\n      errCode\n    )\n  }\n}\n","/**\n * Lightweight, non-critical HTTP call (e.g., tracker, telemetry).\n * Does not throw and does not return a response body; only `{ ok, status }`.\n */\nimport { getBaseURL, getFetchImpl } from \"./config\"\nimport type { Method, WhisperOptions } from \"./types\"\n\nexport async function whisper(\n  pathAPI: string,\n  method: Method,\n  options?: WhisperOptions\n): Promise<{ ok: boolean; status: number }> {\n  try {\n    const headers = new Headers()\n    headers.append(\"Accept\", \"application/json\")\n    headers.append(\"Content-Type\", \"application/json\")\n    if (options?.authKey)\n      headers.append(\"Authorization\", `Bearer ${options?.authKey}`)\n    // SSR-only cookie + x-ssr header\n    if (typeof window === \"undefined\") {\n      headers.append(\"x-ssr\", \"true\")\n      if (\n        options?.cookie &&\n        typeof options.cookie === \"object\" &&\n        Object.keys(options.cookie).length > 0\n      ) {\n        const cookieStr = Object.entries(options.cookie)\n          .map(([k, v]) => `${k}=${v ?? \"\"}`)\n          .join(\"; \")\n        headers.append(\"Cookie\", cookieStr)\n      }\n    }\n\n    const queryOptions: RequestInit = {\n      method,\n      headers,\n      // Only set credentials on the client\n      credentials: options?.client ? \"include\" : undefined\n    }\n    if (options?.payload) queryOptions.body = JSON.stringify(options?.payload)\n\n    const resolvedBase = options?.baseURL || getBaseURL()\n    if (!resolvedBase) {\n      // For whisper, don't throw; return a synthetic failure\n      return { ok: false, status: 0 }\n    }\n    const base = String(resolvedBase).replace(/\\/+$/, \"\")\n    const p = pathAPI.startsWith(\"/\") ? pathAPI : `/${pathAPI}`\n    const url = new URL(base + p)\n    if (options && options.query) {\n      const query = options.query\n      const params = new URLSearchParams()\n      Object.keys(query).forEach((key) => {\n        const value = query[key]\n        if (Array.isArray(value)) {\n          value.forEach((item) => params.append(key, item.toString()))\n        } else {\n          params.append(key, value.toString())\n        }\n      })\n      url.search = params.toString()\n    }\n\n    const response = await getFetchImpl()(url.toString(), queryOptions)\n    return { ok: response.ok, status: response.status }\n  } catch {\n    return { ok: false, status: 0 }\n  }\n}\n"],"mappings":"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"}