{"version":3,"file":"index.mjs","sources":[""],"sourcesContent":["\r\nimport { getDocument, getWindow } from \"ssr-window\";\nimport { bubble } from \"../../evt/bubble/index.ts\";\nimport { getObjFromFormData } from \"../../obj/getObjFromFormData/index.ts\";\nimport { getFormDataFromObj } from \"../getFormDataFromObj/index.ts\";\nimport { getUrlWithQueryParams } from \"../getUrlWithQueryParams/index.ts\";\n\nexport type TGetFromServerMethod = \"GET\" | \"PUT\" | \"POST\" | \"DELETE\" | \"HEAD\" | \"CONNECT\" | \"OPTIONS\" | \"TRACE\" | \"PATCH\";\n\nexport type TGetFromServerErrorKind = \"abort\" | \"http\" | \"network\" | \"parse\" | \"request\" | \"timeout\" | \"transform\";\n\nexport type TGetFromServerError = Error & {\n  cause: unknown;\n  kind: TGetFromServerErrorKind;\n  method: TGetFromServerMethod;\n  name: \"GetFromServerError\";\n  response: Response | null;\n  status: number | null;\n  url: string;\n};\n\nexport type TGetFromServerArgs<TResp = unknown, TSuccess = TResp> = {\n  contentType?: \"auto\" | \"application/json\" | \"application/x-www-form-urlencoded\" | \"multipart/form-data\";\n  isBubble?: boolean;\n  timeout?: number;\n  method?: TGetFromServerMethod;\n  mode?: RequestMode;\n  signal?: AbortSignal | null;\n  data?: Record<string, unknown> | FormData | null;\n  getSuccessResp?: (data: TResp) => TSuccess;\n  getResp?: (resp: Response) => Promise<TResp>;\n  type?: \"text\" | \"json\" | \"blob\" | \"arrayBuffer\";\n  url?: string;\n  headers?: Record<string, string>;\n  allowedCodes?: number[];\n  credentials?: RequestCredentials;\n  redirect?: RequestRedirect;\r\n  cache?: RequestCache;\r\n  referrerPolicy?: ReferrerPolicy;\r\n  fetchProps?: Omit<RequestInit, \"method\" | \"headers\" | \"body\" | \"signal\" | \"mode\" | \"credentials\" | \"redirect\" | \"cache\" | \"referrerPolicy\">;\r\n};\r\n\r\nexport type TGetFromServerReturn = ReturnType<typeof getFromServer>;\n\ntype TGetFromServerErrorProps = {\n  cause: unknown;\n  kind: TGetFromServerErrorKind;\n  method: TGetFromServerMethod;\n  response?: Response | null;\n  status?: number | null;\n  url: string;\n};\n\ntype TRequestStage = \"fetch\" | \"parse\" | \"request\" | \"transform\";\n\nconst getFromServerErrorMarker = Symbol(\"getFromServerError\");\n\nconst getErrorMessage = (kind: TGetFromServerErrorKind, status: number | null): string => {\n  switch (kind) {\n    case \"abort\": return \"getFromServer: request was aborted\";\n    case \"http\": return `getFromServer: request failed with status ${status ?? \"unknown\"}`;\n    case \"network\": return \"getFromServer: network request failed\";\n    case \"parse\": return \"getFromServer: failed to parse response\";\n    case \"request\": return \"getFromServer: failed to create request\";\n    case \"timeout\": return \"getFromServer: request timed out\";\n    case \"transform\": return \"getFromServer: failed to transform response\";\n  }\n};\n\nconst getRequestError = (props: TGetFromServerErrorProps): TGetFromServerError => {\n  const {\n    cause,\n    kind,\n    method,\n    response = null,\n    status = response?.status ?? (kind === \"timeout\" ? 408 : null),\n    url,\n  } = props;\n  const error = new Error(getErrorMessage(kind, status)) as TGetFromServerError & {\n    [getFromServerErrorMarker]: true;\n  };\n  error.name = \"GetFromServerError\";\n  error.cause = cause;\n  error.kind = kind;\n  error.method = method;\n  error.response = response;\n  error.status = status;\n  error.url = url;\n  Object.defineProperty(error, getFromServerErrorMarker, { value: true });\n  return error;\n};\n\nconst isRequestError = (error: unknown): error is TGetFromServerError => {\n  return typeof error === \"object\" && error !== null && getFromServerErrorMarker in error;\n};\n\r\n/**\r\n * Performs an HTTP request (`fetch`) with handy defaults, content-type handling,\r\n * query param building, and optional bubbling of a \"getFromServer\" event.\r\n *\r\n * @template T The expected response data type.\r\n * @param {Object} [props] Request parameters (all optional).\r\n * @param {string} [props.url] The URL to request. Defaults to current window location or './'.\r\n * @param {(\"auto\"|\"application/json\"|\"application/x-www-form-urlencoded\"|\"multipart/form-data\")} [props.contentType=\"auto\"] Content type header. If \"auto\", sets based on data/method.\r\n * @param {boolean} [props.isBubble=true] Whether to bubble a \"getFromServer\" event after success.\r\n * @param {number} [props.timeout=15000] Timeout in milliseconds (use Infinity to disable).\r\n * @param {(\"GET\"|\"PUT\"|\"POST\"|\"DELETE\"|\"HEAD\"|\"CONNECT\"|\"OPTIONS\"|\"TRACE\")} [props.method=\"GET\"] HTTP method.\r\n * @param {RequestMode} [props.mode=\"cors\"] Fetch mode.\r\n * @param {AbortSignal|null} [props.signal=null] AbortSignal for cancellation.\r\n * @param {Record<string,unknown>|FormData|null} [props.data=null] Request data. For GET-like methods, appended as query params.\r\n * @param {function(T): T} [props.getSuccessResp] Transform function for successful response. Defaults to identity function.\r\n * @param {function(Response): Promise<T>} [props.getResp] Custom response parser. If provided, overrides `type` after HTTP status validation.\n * @param {(\"text\"|\"json\"|\"blob\"|\"arrayBuffer\")} [props.type=\"json\"] Response body parsing type (used when `getResp` not provided).\r\n * @param {Record<string,string>} [props.headers={}] Additional headers.\r\n * @param {number[]} [props.allowedCodes=[]] Array of HTTP status codes to treat as success even if not 2xx.\r\n * @param {RequestCredentials} [props.credentials=\"same-origin\"] Credentials mode.\r\n * @param {RequestRedirect} [props.redirect=\"follow\"] Redirect mode.\r\n * @param {RequestCache} [props.cache=\"default\"] Cache mode.\r\n * @param {ReferrerPolicy} [props.referrerPolicy=\"no-referrer-when-downgrade\"] Referrer policy.\r\n * @param {Omit<RequestInit, \"method\"|\"headers\"|\"body\"|\"signal\"|\"mode\"|\"credentials\"|\"redirect\"|\"cache\"|\"referrerPolicy\">} [props.fetchProps={}] Additional fetch options.\r\n * @returns {Promise<T>} Promise with parsed response (type depends on `type` option).\r\n * @throws {TypeError} getFromServer: url must be a string\n * @throws {TypeError} getFromServer: allowedCodes must be an array of integers\n * @throws {TypeError} getFromServer: data must be a plain object, FormData, or null\n * @throws {TypeError} getFromServer: timeout must be a non-negative number or Infinity\n * @throws {TGetFromServerError} Request lifecycle error with a discriminating `kind`\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\n * @example\n * const user = await getFromServer<{ userId: number }>({ url: \"/api/user?id=1\", method: \"GET\" });\n * @example\n * import type { TGetFromServerError } from \"@web3r/flowerkit/net\";\n *\n * try {\n *   await getFromServer({ url: \"/api/user\" });\n * } catch (error) {\n *   if (error instanceof Error && error.name === \"GetFromServerError\") {\n *     const requestError = error as TGetFromServerError;\n *     if (requestError.kind === \"http\") {\n *       console.error(requestError.status, requestError.response);\n *     }\n *   }\n * }\n * @example\n * // Send typed JSON data and transform the successful API response\n * const productId = await getFromServer<{ product: { id: string } }, string>({\n *   url: \"/api/products\",\n *   method: \"POST\",\n *   contentType: \"application/json\",\n *   data: { name: \"Flower pot\", price: 24 },\n *   getSuccessResp: ({ product }) => product.id,\n * });\n */\nexport const getFromServer = async <TResp = unknown, TSuccess = TResp>(\n  props: TGetFromServerArgs<TResp, TSuccess> = {}\n): Promise<TSuccess> => {\n  const {\n    contentType = \"auto\",\n    isBubble = true,\n    timeout = 15000,\n    method = \"GET\",\n    mode = \"cors\",\n    signal = null,\n    data = null,\n    getResp,\n    type = \"json\",\n    url = getWindow().location.href || \"./\",\n    headers = {},\n    allowedCodes = [],\n    credentials = \"same-origin\",\r\n    redirect = \"follow\",\r\n    referrerPolicy = \"no-referrer-when-downgrade\",\r\n    cache = \"default\",\n    fetchProps = {},\n  } = props;\n\n  const getSuccessResp = props.getSuccessResp ?? ((resp: TResp) => resp as unknown as TSuccess);\n  const methodNormalized = String(method).toUpperCase() as TGetFromServerMethod;\n  const methodsWithBody = new Set([\n    \"POST\",\n    \"PUT\",\n    \"DELETE\",\n    \"PATCH\",\n  ]);\n  const methodsNoBody = new Set([\n    \"GET\",\n    \"HEAD\",\n    \"CONNECT\",\n    \"OPTIONS\",\n    \"TRACE\",\n  ]);\n  const isFormData = (v: unknown): v is FormData => typeof FormData !== \"undefined\" && v instanceof FormData;\n  const isPlainObject = (v: unknown): v is Record<string, unknown> => {\n    return Object.prototype.toString.call(v) === \"[object Object]\";\n  };\n\n  if (typeof url !== \"string\") {\n    throw new TypeError(\"getFromServer: url must be a string\");\n  }\n\n  if (!Array.isArray(allowedCodes) || !allowedCodes.every((c) => Number.isInteger(c))) {\n    throw new TypeError(\"getFromServer: allowedCodes must be an array of integers\");\n  }\n\n  if (typeof timeout !== \"number\" || (Number.isFinite(timeout) && timeout < 0) || Number.isNaN(timeout)) {\n    throw new TypeError(\"getFromServer: timeout must be a non-negative number or Infinity\");\n  }\n\n  if (data !== null && !isFormData(data) && !isPlainObject(data)) {\n    throw new TypeError(\"getFromServer: data must be a plain object, FormData, or null\");\n  }\n\n  let timer: ReturnType<typeof setTimeout> | null = null;\n  let isTimedOut = false;\n  const requestController = new AbortController();\n  const externalAbortListener = (): void => {\n    requestController.abort();\n  };\n  if (signal) {\n    if (signal.aborted) {\n      externalAbortListener();\n    } else {\n      signal.addEventListener(\"abort\", externalAbortListener, { once: true });\n    }\n  }\n\n  const getDataAsObject = (): Record<string, unknown> => {\n    return isFormData(data) ? getObjFromFormData(data) : (data ?? {});\n  };\n\n  /**\n   * Produces request body based on contentType and data\n   * @private\n   * @returns {BodyInit | null}\n   */\n  const getBody = (): BodyInit | null => {\n    if (!methodsWithBody.has(methodNormalized)) {\n      return null;\n    }\n\n    switch (true) {\n      case contentType === \"application/json\":\n        return JSON.stringify(getDataAsObject());\n      case contentType === \"application/x-www-form-urlencoded\": {\n        const params = new URLSearchParams();\n        Object.entries(getDataAsObject())\n          .forEach(([ key, value ]) => {\n            params.set(key, String(value ?? \"\"));\n          });\n        return params.toString();\n      }\n      case contentType === \"multipart/form-data\":\n        return isFormData(data)\n          ? data\n          : getFormDataFromObj(getDataAsObject());\n      case contentType === \"auto\":\n        return isFormData(data)\n          ? data\n          : getFormDataFromObj(getDataAsObject());\n      default:\n        return null;\n    }\n  };\n\n  /**\r\n   * URL builder (adds query params for GET-like methods)\n   * @private\n   */\n  const getUrl = (): string => {\n    return (methodsNoBody.has(methodNormalized) && data !== null)\n      ? getUrlWithQueryParams(\n        url, isFormData(data)\n          ? data\n          : (data as Record<string, string | number | boolean | null>)\n      )\n      : url;\r\n  };\r\n\r\n  /**\r\n   * Response parser\n   * @private\n   */\n  const getResponse = async (resp: Response): Promise<TResp> => {\n    const { ok, status } = resp;\n    if (!ok && !(allowedCodes.length > 0 && allowedCodes.includes(status))) {\n      throw getRequestError({\n        cause: resp,\n        kind: \"http\",\n        method: methodNormalized,\n        response: resp,\n        url: requestUrl,\n      });\n    }\n    if (typeof getResp === \"function\") {\n      return await getResp(resp);\n    }\n    switch (type) {\n      case \"arrayBuffer\": return await resp.arrayBuffer() as unknown as TResp;\n      case \"json\": return await resp.json() as TResp;\n      case \"blob\": return await resp.blob() as unknown as TResp;\n      default: return await resp.text() as unknown as TResp;\n    }\n  };\n\n  /**\n   * Headers builder\n   * @private\n   */\r\n  const getHeaders = (): Record<string, string> => {\n    const result: Record<string, string> = { ...(headers || {}) };\n    if (contentType === \"multipart/form-data\") {\n      Object.keys(result).forEach((key) => {\n        if (key.toLowerCase() === \"content-type\") {\n          delete result[key];\n        }\n      });\n      return result;\n    }\n    if ([ \"application/json\", \"application/x-www-form-urlencoded\" ].includes(contentType)) {\n      result[\"Content-Type\"] = contentType;\n    }\n    return result;\n  };\n\n  if (timeout && timeout !== Infinity) {\n    timer = setTimeout(() => {\n      isTimedOut = true;\n      requestController.abort();\n    }, timeout);\n  }\n\n  let requestUrl = url;\n  let response: Response | null = null;\n  let stage: TRequestStage = \"request\";\n\n  try {\n    const fetchParams: RequestInit = {\n      ...fetchProps,\n      method: methodNormalized,\n      body: getBody(),\n      mode,\n      signal: requestController.signal,\n      credentials,\n      redirect,\n      cache,\n      referrerPolicy,\n      headers: getHeaders(),\n    };\n    requestUrl = getUrl();\n    stage = \"fetch\";\n    response = await fetch(requestUrl, fetchParams);\n    stage = \"parse\";\n    const parsed = await getResponse(response);\n\n    stage = \"transform\";\n    if (isBubble && typeof window !== \"undefined\") {\n      bubble(getDocument(), getFromServer.name, parsed);\n    }\n\n    return getSuccessResp(parsed);\n  } catch (error) {\n    if (isRequestError(error)) {\n      throw error;\n    }\n    if (isTimedOut) {\n      throw getRequestError({\n        cause: error,\n        kind: \"timeout\",\n        method: methodNormalized,\n        response,\n        url: requestUrl,\n      });\n    }\n    if (signal?.aborted) {\n      throw getRequestError({\n        cause: signal.reason ?? error,\n        kind: \"abort\",\n        method: methodNormalized,\n        response,\n        url: requestUrl,\n      });\n    }\n    const kindByStage: Record<TRequestStage, TGetFromServerErrorKind> = {\n      fetch: \"network\",\n      parse: \"parse\",\n      request: \"request\",\n      transform: \"transform\",\n    };\n    throw getRequestError({\n      cause: error,\n      kind: kindByStage[stage],\n      method: methodNormalized,\n      response,\n      url: requestUrl,\n    });\n  } finally {\n    if (timer) {\n      clearTimeout(timer);\n    }\n    if (signal) {\n      signal.removeEventListener(\"abort\", externalAbortListener);\n    }\n  }\n};\n"],"names":["getFromServerErrorMarker","Symbol","getErrorMessage","kind","status","getRequestError","props","cause","method","response","url","error","Error","name","Object","defineProperty","value","isRequestError","getFromServer","async","contentType","isBubble","timeout","mode","signal","data","getResp","type","getWindow","location","href","headers","allowedCodes","credentials","redirect","referrerPolicy","cache","fetchProps","getSuccessResp","resp","methodNormalized","String","toUpperCase","methodsWithBody","Set","methodsNoBody","isFormData","v","FormData","isPlainObject","prototype","toString","call","TypeError","Array","isArray","every","c","Number","isInteger","isFinite","isNaN","timer","isTimedOut","requestController","AbortController","externalAbortListener","abort","aborted","addEventListener","once","getDataAsObject","getObjFromFormData","getBody","has","JSON","stringify","params","URLSearchParams","entries","forEach","key","set","getFormDataFromObj","getUrl","getUrlWithQueryParams","getResponse","ok","length","includes","requestUrl","arrayBuffer","json","blob","text","getHeaders","result","keys","toLowerCase","Infinity","setTimeout","stage","fetchParams","body","fetch","parsed","window","bubble","getDocument","reason","kindByStage","parse","request","transform","clearTimeout","removeEventListener"],"mappings":"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"}