apiClient.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import { API_BASE_URL } from '../utils/constants';
  2. interface ApiResponse<T = any> {
  3. data: T;
  4. status: number;
  5. }
  6. class ApiClient {
  7. private baseURL: string;
  8. constructor(baseURL: string) {
  9. this.baseURL = baseURL;
  10. }
  11. private getAuthHeaders(): Record<string, string> {
  12. // V2 API key auth (primary)
  13. const apiKey = localStorage.getItem('kb_api_key');
  14. // Legacy JWT token (fallback, kept for compatibility during transition)
  15. const token = localStorage.getItem('authToken') || localStorage.getItem('token');
  16. const language = localStorage.getItem('userLanguage') || 'ja';
  17. return {
  18. 'Content-Type': 'application/json',
  19. 'x-user-language': language,
  20. ...(apiKey && { 'x-api-key': apiKey }),
  21. ...(token && { Authorization: `Bearer ${token}` }),
  22. };
  23. }
  24. // 新しい API 呼び出し方法、{ data, status } を返す
  25. async get<T = any>(url: string): Promise<ApiResponse<T>> {
  26. const response = await fetch(`${this.baseURL}${url}`, {
  27. method: 'GET',
  28. headers: this.getAuthHeaders(),
  29. });
  30. if (!response.ok) {
  31. const errorData = await response.json();
  32. throw new Error(errorData.message || 'Request failed');
  33. }
  34. const data = await response.json();
  35. return { data, status: response.status };
  36. }
  37. async post<T = any>(url: string, body?: any): Promise<ApiResponse<T>> {
  38. const response = await fetch(`${this.baseURL}${url}`, {
  39. method: 'POST',
  40. headers: this.getAuthHeaders(),
  41. body: body ? JSON.stringify(body) : undefined,
  42. });
  43. if (!response.ok) {
  44. const errorData = await response.json();
  45. throw new Error(errorData.message || 'Request failed');
  46. }
  47. const data = await response.json();
  48. return { data, status: response.status };
  49. }
  50. async put<T = any>(url: string, body?: any): Promise<ApiResponse<T>> {
  51. const response = await fetch(`${this.baseURL}${url}`, {
  52. method: 'PUT',
  53. headers: this.getAuthHeaders(),
  54. body: body ? JSON.stringify(body) : undefined,
  55. });
  56. if (!response.ok) {
  57. const errorData = await response.json();
  58. throw new Error(errorData.message || 'Request failed');
  59. }
  60. const data = await response.json();
  61. return { data, status: response.status };
  62. }
  63. async delete<T = any>(url: string): Promise<ApiResponse<T>> {
  64. const response = await fetch(`${this.baseURL}${url}`, {
  65. method: 'DELETE',
  66. headers: this.getAuthHeaders(),
  67. });
  68. if (!response.ok) {
  69. const errorData = await response.json();
  70. throw new Error(errorData.message || 'Request failed');
  71. }
  72. const data = await response.json();
  73. return { data, status: response.status };
  74. }
  75. // Legacy compatibility method — returns raw Response for streaming and other special cases
  76. async request(path: string, options: RequestInit = {}): Promise<Response> {
  77. const apiKey = localStorage.getItem('kb_api_key');
  78. const token = localStorage.getItem('authToken');
  79. const headers = new Headers(options.headers);
  80. if (apiKey) headers.set('x-api-key', apiKey);
  81. if (token) headers.set('Authorization', `Bearer ${token}`);
  82. const language = localStorage.getItem('userLanguage') || 'ja';
  83. headers.set('x-user-language', language);
  84. let url = path;
  85. if (!path.startsWith('http')) {
  86. const cleanPath = path.startsWith('/') ? path : `/${path}`;
  87. url = `${this.baseURL}${cleanPath}`;
  88. }
  89. const response = await fetch(url, {
  90. ...options,
  91. headers,
  92. });
  93. if (response.status === 401) {
  94. localStorage.removeItem('kb_api_key');
  95. localStorage.removeItem('authToken');
  96. window.location.href = '/login';
  97. throw new Error('Unauthorized');
  98. }
  99. return response;
  100. }
  101. }
  102. export const apiClient = new ApiClient(API_BASE_URL);