useApi.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { $fetch } from 'ofetch'
  2. import { useLogger } from './useLogger'
  3. import { useUser } from '~/store/useUser'
  4. interface TUserData {
  5. user_id: number
  6. access_token: string
  7. }
  8. interface Detail {
  9. type: string
  10. loc: string[]
  11. msg: string
  12. }
  13. interface TException {
  14. error?: string
  15. code?: number
  16. detail?: Detail[]
  17. }
  18. export function useApi() {
  19. const { public: { API_URL } } = useRuntimeConfig()
  20. const log = useLogger('useApi')
  21. const user = useUser()
  22. function showError(data: TException) {
  23. if (Object.prototype.hasOwnProperty.call(data, 'code') && Object.prototype.hasOwnProperty.call(data, 'error')) {
  24. log.error(`${data.error} (${data.code})`)
  25. }
  26. else if (Object.prototype.hasOwnProperty.call(data, 'detail')) {
  27. const details = data.detail[0]
  28. log.error(`${details.type} ${details.loc.join(', ')} (${details.msg})`)
  29. }
  30. return data
  31. }
  32. const instance = $fetch.create({
  33. baseURL: API_URL,
  34. onRequest(ctx) {
  35. if (!user.data.access_token && ctx.request !== '/login')
  36. navigateTo('/auth')
  37. },
  38. async onResponse(ctx) {
  39. const statusCode = ctx.response.status
  40. if (statusCode > 300)
  41. showError(ctx.response._data)
  42. },
  43. async onResponseError(ctx) {
  44. const statusCode = ctx.response.status
  45. if (statusCode === 401) {
  46. const newToken: TUserData = await api.get('/user/refresh', {
  47. access_token: ctx.request.toString().split('?')[1].split('=')[1],
  48. })
  49. user.setUserData(newToken)
  50. }
  51. else if (statusCode === 400) {
  52. user.logout()
  53. }
  54. },
  55. })
  56. const api = {
  57. get: function<T>(url: string, params?: object): Promise<T> {
  58. return instance(url, {
  59. method: 'GET',
  60. params: {
  61. access_token: user.data.access_token,
  62. ...params,
  63. },
  64. })
  65. },
  66. post: function<T>(url: string, body?: object, params?: object): Promise<T> {
  67. return instance(url, {
  68. method: 'POST',
  69. body,
  70. params: {
  71. access_token: user.data.access_token,
  72. ...params,
  73. },
  74. })
  75. },
  76. put: function<T>(url: string, body?: object, params?: object): Promise<T> {
  77. return instance(url, {
  78. method: 'PUT',
  79. body,
  80. params: {
  81. access_token: user.data.access_token,
  82. ...params,
  83. },
  84. })
  85. },
  86. delete: function<T>(url: string, body?: object, params?: object): Promise<T> {
  87. return instance(url, {
  88. method: 'DELETE',
  89. body,
  90. params: {
  91. access_token: user.data.access_token,
  92. ...params,
  93. },
  94. })
  95. },
  96. }
  97. return api
  98. }