Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 

179 рядки
5.0 KiB

  1. import { SessionWithTokens, authOptions } from "@/config/authConfig";
  2. import { getServerSession } from "next-auth";
  3. import { headers } from "next/headers";
  4. import { redirect } from "next/navigation";
  5. export class ServerFetchError extends Error {
  6. public readonly response: Response | undefined;
  7. constructor(message?: string, response?: Response) {
  8. super(message);
  9. this.response = response;
  10. Object.setPrototypeOf(this, ServerFetchError.prototype);
  11. }
  12. }
  13. export const serverFetch: typeof fetch = async (input, init) => {
  14. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  15. const session = await getServerSession<any, SessionWithTokens>(authOptions);
  16. const accessToken = session?.accessToken;
  17. console.log(accessToken);
  18. return fetch(input, {
  19. ...init,
  20. headers: {
  21. ...init?.headers,
  22. ...(accessToken
  23. ? {
  24. Authorization: `Bearer ${accessToken}`,
  25. Accept:
  26. "application/json, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, multipart/form-data",
  27. }
  28. : {}),
  29. },
  30. });
  31. };
  32. type FetchParams = Parameters<typeof fetch>;
  33. export async function serverFetchJson<T>(...args: FetchParams) {
  34. const response = await serverFetch(...args);
  35. if (response.ok) {
  36. return response.json() as T;
  37. } else {
  38. const errorText = await response.text()
  39. switch (response.status) {
  40. case 401:
  41. signOutUser();
  42. case 422:
  43. throw new ServerFetchError(
  44. JSON.parse(errorText).error,
  45. response
  46. );
  47. default:
  48. console.error(errorText);
  49. throw new ServerFetchError(
  50. "Something went wrong fetching data in server.",
  51. response
  52. );
  53. }
  54. }
  55. }
  56. export async function serverFetchWithNoContent(...args: FetchParams) {
  57. const response = await serverFetch(...args);
  58. if (response.ok) {
  59. return response.status; // 204 No Content, e.g. for delete data
  60. } else {
  61. switch (response.status) {
  62. case 401:
  63. signOutUser();
  64. default:
  65. console.error(await response.text());
  66. throw Error("Something went wrong fetching data in server.");
  67. }
  68. }
  69. }
  70. export async function serverFetchString<T>(...args: FetchParams) {
  71. const response = await serverFetch(...args);
  72. if (response.ok) {
  73. return response.text() as T;
  74. } else {
  75. switch (response.status) {
  76. case 401:
  77. signOutUser();
  78. default:
  79. console.error(await response.text());
  80. throw new ServerFetchError(
  81. "Something went wrong fetching data in server.",
  82. response,
  83. );
  84. }
  85. }
  86. }
  87. export async function serverFetchBlob<T>(...args: FetchParams) {
  88. const response = await serverFetch(...args);
  89. if (response.ok) {
  90. const body = response.body;
  91. // console.log(body)
  92. // console.log(body?.tee()[0].getReader())
  93. const reader = body?.getReader();
  94. let finalUInt8Array = new Uint8Array();
  95. let done = false;
  96. while (!done) {
  97. const read = await reader?.read();
  98. // version 1
  99. if (read?.done) {
  100. done = true;
  101. } else {
  102. const tempUInt8Array = new Uint8Array(
  103. finalUInt8Array.length + read?.value.length!,
  104. );
  105. tempUInt8Array.set(finalUInt8Array);
  106. tempUInt8Array.set(read?.value!, finalUInt8Array.length);
  107. finalUInt8Array = new Uint8Array(tempUInt8Array.length!);
  108. finalUInt8Array.set(tempUInt8Array);
  109. // console.log("1", finalUInt8Array)
  110. }
  111. }
  112. // version 2 & return bodyRead
  113. // const bodyRead = reader?.read().then(function processText({ done, value }): any {
  114. // // Result objects contain two properties:
  115. // // done - true if the stream has already given you all its data.
  116. // // value - some data. Always undefined when done is true.
  117. // if (done) {
  118. // console.log("Stream complete");
  119. // return { filename: response.headers.get("filename"), blobValue: finalUInt8Array } as T;;
  120. // }
  121. // // value for fetch streams is a Uint8Array
  122. // finalUInt8Array = new Uint8Array(value.length)
  123. // finalUInt8Array.set(value)
  124. // console.log(finalUInt8Array)
  125. // // Read some more, and call this function again
  126. // return reader.read().then(processText);
  127. // })
  128. // const bodyValue = bodyRead?.value
  129. // const blob = await response.blob()
  130. // const blobText = await blob.text();
  131. // const blobType = await blob.type;
  132. // console.log(bodyReader)
  133. // console.log("2", finalUInt8Array)
  134. // console.log(bodyValue)
  135. return {
  136. filename: response.headers.get("filename"),
  137. blobValue: finalUInt8Array,
  138. } as T;
  139. } else {
  140. switch (response.status) {
  141. case 401:
  142. signOutUser();
  143. default:
  144. console.error(await response.text());
  145. throw Error("Something went wrong fetching data in server.");
  146. }
  147. }
  148. }
  149. export const signOutUser = () => {
  150. const headersList = headers();
  151. const referer = headersList.get("referer");
  152. redirect(
  153. `/logout${referer ? `?callbackUrl=${encodeURIComponent(referer)}` : ""}`,
  154. );
  155. };