{"version":3,"sources":["../src/useRequest.ts","../src/MatsuriError.ts","../src/fetcher.ts"],"sourcesContent":["import useSWR, { SWRConfiguration, SWRHook } from \"swr\";\nimport { AuthTokenHeader, fetcherThrows } from \"./fetcher\";\nimport { MatsuriError } from \"./MatsuriError\";\n\ntype SWRKey = Parameters<SWRHook>[0];\n\ninterface FetchCreatorOptions {\n  url: string;\n  method?: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\" | \"OPTIONS\" | \"HEAD\";\n  token?: string;\n  body?: RequestInit[\"body\"];\n  fetch?: (info: RequestInfo, init?: RequestInit) => Promise<Response>;\n  authTokenHeader?: AuthTokenHeader;\n}\n\nexport const createFetcher = <T>(options: FetchCreatorOptions) => {\n  return (_: SWRKey) => {\n    return fetcherThrows<T>(options.url, options);\n  };\n};\n\nexport const useRequest = <T, U = Record<string, string>>(\n  key: SWRKey,\n  fetchOptions: FetchCreatorOptions,\n  config: Partial<SWRConfiguration> = {},\n) => {\n  const { data, error, mutate, isLoading, isValidating } = useSWR<\n    T,\n    MatsuriError<U>\n  >(key, createFetcher<T>(fetchOptions), config);\n\n  return {\n    data,\n    error,\n    refetch: mutate,\n    isLoading,\n    isValidating,\n  };\n};\n\ninterface FetchCreatorOptionsForAuthRequest extends FetchCreatorOptions {\n  token: string;\n}\n\nexport const useAuthRequest = <T, U = Record<string, string>>(\n  key: SWRKey,\n  fetchOptions: FetchCreatorOptionsForAuthRequest,\n  config: Partial<SWRConfiguration> = {},\n) => {\n  const { token } = fetchOptions;\n  return useRequest<T, U>(\n    token ? key : null,\n    {\n      authTokenHeader: \"X-Access-Token\",\n      ...fetchOptions,\n    },\n    config,\n  );\n};\n\nexport const useAuthBearerRequest = <T, U = Record<string, string>>(\n  key: SWRKey,\n  fetchOptions: FetchCreatorOptionsForAuthRequest,\n  config: Partial<SWRConfiguration> = {},\n) => {\n  return useAuthRequest<T, U>(\n    key,\n    {\n      authTokenHeader: \"Authorization\",\n      ...fetchOptions,\n    },\n    config,\n  );\n};\n","export class MatsuriError<T = Record<string, unknown>> extends Error {\n  status?: number;\n\n  private text: string;\n\n  constructor(\n    text: string,\n    options: {\n      status: number;\n    },\n  ) {\n    const { status, ...rest } = options;\n    /**\n     * messageは後方互換性のためにこのような形式にしている\n     */\n    const message = `${status}: ${text}`;\n    super(message, rest);\n    this.name = \"MatsuriError\";\n    this.status = status;\n    this.text = text;\n  }\n  /**\n   * NOTE: メソッドであってもErrorに存在しないプロパティは基本的にundefinedを許容させる。\n   * これは実際はMatsuriErrorでないErrorが投げられたとしてもランタイムエラーを防げるような記述を強制させるために行う。\n   * またMatsuriError|Errorが型としてはより正しいが、一方にしかないプロパティはインスタンスを確認しなければ利用できなくなってしまい冗長な記述を強いられてしまう。\n   */\n  parse: (<S = T>() => S | null) | undefined = <S = T>() => {\n    try {\n      return JSON.parse(this.text) as S;\n    } catch {\n      return null;\n    }\n  };\n}\n","import { MatsuriError } from \"./MatsuriError\";\n\nexport interface FetcherResult<T, U = Record<string, unknown>> {\n  data: T | undefined;\n  error: MatsuriError<U> | undefined;\n}\n\nexport type AuthTokenHeader =\n  | \"Authorization\"\n  | \"X-Access-Token\"\n  | \"x-authorization\"\n  // @see https://github.com/matsuri-tech/m2m-systems\n  | \"X-M2m-Access-Token\";\n\nexport interface FetcherOptions {\n  method?: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\" | \"OPTIONS\" | \"HEAD\";\n  token?: string;\n  body?: RequestInit[\"body\"];\n  fetch?: (info: RequestInfo, init?: RequestInit) => Promise<Response>;\n  authTokenHeader?: AuthTokenHeader;\n}\n\nexport const fetcher = async <T, U = Record<string, unknown>>(\n  url: string,\n  options: FetcherOptions = {},\n): Promise<FetcherResult<T, U>> => {\n  try {\n    return { data: await fetcherThrows(url, options), error: undefined };\n  } catch (e) {\n    return { data: undefined, error: e as MatsuriError<U> };\n  }\n};\n\nexport const bearerFetcher = <T, U = Record<string, unknown>>(\n  token: string,\n  url: string,\n  options?: FetcherOptions,\n): Promise<FetcherResult<T, U>> => {\n  return fetcher(url, { ...options, token, authTokenHeader: \"Authorization\" });\n};\nexport const fetcherThrows = async <T>(\n  url: string,\n  options: FetcherOptions = {},\n): Promise<T> => {\n  const obj: RequestInit = {};\n  if (options.token !== null && options.token !== undefined) {\n    const header = options.authTokenHeader ?? \"X-Access-Token\";\n\n    obj.headers = {\n      [header]:\n        header === \"Authorization\" ? `Bearer ${options.token}` : options.token,\n    };\n  }\n  if (options.method) {\n    obj.method = options.method || \"GET\";\n  }\n\n  const hasBody = !(options?.body === null || options?.body === undefined);\n\n  if (hasBody) {\n    obj.body = options.body;\n  }\n\n  if (hasBody && obj.method === \"GET\") {\n    throw new TypeError(\"The `GET` method cannot be used with a body\");\n  }\n\n  if (typeof obj.body === \"string\") {\n    obj.headers = {\n      \"Content-Type\": \"application/json\",\n      ...(obj.headers ?? {}),\n    };\n  }\n\n  // eslint-disable-next-line no-restricted-globals -- This is the fetcher implementation itself, so direct use of fetch is necessary\n  const resp = await (options.fetch ?? fetch)(url, obj);\n\n  if (!resp.ok) {\n    throw new MatsuriError(await resp.text(), { status: resp.status });\n  }\n\n  const bodyText = await resp.text();\n  // responseが空の場合があるのでケアする\n  return bodyText ? (JSON.parse(bodyText) as T) : (undefined as T);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAkD;;;ACA3C,IAAM,eAAN,cAAwD,MAAM;AAAA,EAKnE,YACE,MACA,SAGA;AACA,UAAM,EAAE,QAAQ,GAAG,KAAK,IAAI;AAI5B,UAAM,UAAU,GAAG,MAAM,KAAK,IAAI;AAClC,UAAM,SAAS,IAAI;AAUrB;AAAA;AAAA;AAAA;AAAA;AAAA,iBAA6C,MAAa;AACxD,UAAI;AACF,eAAO,KAAK,MAAM,KAAK,IAAI;AAAA,MAC7B,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAfE,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EACd;AAaF;;;ACOO,IAAM,gBAAgB,OAC3B,KACA,UAA0B,CAAC,MACZ;AACf,QAAM,MAAmB,CAAC;AAC1B,MAAI,QAAQ,UAAU,QAAQ,QAAQ,UAAU,QAAW;AACzD,UAAM,SAAS,QAAQ,mBAAmB;AAE1C,QAAI,UAAU;AAAA,MACZ,CAAC,MAAM,GACL,WAAW,kBAAkB,UAAU,QAAQ,KAAK,KAAK,QAAQ;AAAA,IACrE;AAAA,EACF;AACA,MAAI,QAAQ,QAAQ;AAClB,QAAI,SAAS,QAAQ,UAAU;AAAA,EACjC;AAEA,QAAM,UAAU,EAAE,SAAS,SAAS,QAAQ,SAAS,SAAS;AAE9D,MAAI,SAAS;AACX,QAAI,OAAO,QAAQ;AAAA,EACrB;AAEA,MAAI,WAAW,IAAI,WAAW,OAAO;AACnC,UAAM,IAAI,UAAU,6CAA6C;AAAA,EACnE;AAEA,MAAI,OAAO,IAAI,SAAS,UAAU;AAChC,QAAI,UAAU;AAAA,MACZ,gBAAgB;AAAA,MAChB,GAAI,IAAI,WAAW,CAAC;AAAA,IACtB;AAAA,EACF;AAGA,QAAM,OAAO,OAAO,QAAQ,SAAS,OAAO,KAAK,GAAG;AAEpD,MAAI,CAAC,KAAK,IAAI;AACZ,UAAM,IAAI,aAAa,MAAM,KAAK,KAAK,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC;AAAA,EACnE;AAEA,QAAM,WAAW,MAAM,KAAK,KAAK;AAEjC,SAAO,WAAY,KAAK,MAAM,QAAQ,IAAW;AACnD;;;AFrEO,IAAM,gBAAgB,CAAI,YAAiC;AAChE,SAAO,CAAC,MAAc;AACpB,WAAO,cAAiB,QAAQ,KAAK,OAAO;AAAA,EAC9C;AACF;AAEO,IAAM,aAAa,CACxB,KACA,cACA,SAAoC,CAAC,MAClC;AACH,QAAM,EAAE,MAAM,OAAO,QAAQ,WAAW,aAAa,QAAI,WAAAA,SAGvD,KAAK,cAAiB,YAAY,GAAG,MAAM;AAE7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;AAMO,IAAM,iBAAiB,CAC5B,KACA,cACA,SAAoC,CAAC,MAClC;AACH,QAAM,EAAE,MAAM,IAAI;AAClB,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,IACd;AAAA,MACE,iBAAiB;AAAA,MACjB,GAAG;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,uBAAuB,CAClC,KACA,cACA,SAAoC,CAAC,MAClC;AACH,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,iBAAiB;AAAA,MACjB,GAAG;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;","names":["useSWR"]}