Refactor supabase client file
Refactor the supabase client file into smaller modules.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
import { getSupabaseUrl, getSupabaseKey } from './config';
|
||||
import { customFetch } from './customFetch';
|
||||
|
||||
const supabaseUrl = getSupabaseUrl();
|
||||
const supabaseAnonKey = getSupabaseKey();
|
||||
@@ -25,153 +26,10 @@ try {
|
||||
},
|
||||
global: {
|
||||
// 커스텀 fetch 구현
|
||||
fetch: (...args) => {
|
||||
// 첫 번째 인자는 URL 또는 Request 객체
|
||||
let requestToUse = args[0];
|
||||
let url = '';
|
||||
let headers = {};
|
||||
|
||||
// URL 형식 변환 및 헤더 수정
|
||||
if (typeof requestToUse === 'string') {
|
||||
url = requestToUse;
|
||||
|
||||
// Storage API 엔드포인트 경로 수정 (buckets → bucket)
|
||||
if (url.includes('/storage/v1/buckets')) {
|
||||
url = url.replace('/storage/v1/buckets', '/storage/v1/bucket');
|
||||
console.log('Storage API 경로 수정:', url);
|
||||
// 문자열 URL인 경우 수정된 URL을 requestToUse에 할당
|
||||
requestToUse = url;
|
||||
}
|
||||
|
||||
// 두 번째 인자에서 헤더 가져오기
|
||||
if (args[1] && args[1].headers) {
|
||||
headers = args[1].headers;
|
||||
}
|
||||
} else if (requestToUse instanceof Request) {
|
||||
url = requestToUse.url;
|
||||
|
||||
// Storage API 엔드포인트 경로 수정 (buckets → bucket)
|
||||
if (url.includes('/storage/v1/buckets')) {
|
||||
const newUrl = url.replace('/storage/v1/buckets', '/storage/v1/bucket');
|
||||
// Request 객체인 경우 새 Request 객체 생성
|
||||
const newRequest = new Request(newUrl, requestToUse);
|
||||
requestToUse = newRequest;
|
||||
url = newUrl;
|
||||
console.log('Storage API Request 객체 경로 수정:', url);
|
||||
}
|
||||
}
|
||||
|
||||
// Storage API 호출 감지 및 헤더 형식 수정
|
||||
if (url.includes('/storage/v1/')) {
|
||||
console.log('Supabase Storage API 호출 감지');
|
||||
|
||||
// 두 번째 인자에서 헤더 가져오기 및 수정
|
||||
if (args[1] && args[1].headers) {
|
||||
const originalHeaders = args[1].headers;
|
||||
const apiKey = originalHeaders['apikey'] || originalHeaders['Apikey'] || supabaseAnonKey;
|
||||
|
||||
// 새 헤더 객체 생성
|
||||
const newHeaders = new Headers(originalHeaders);
|
||||
|
||||
// apikey 헤더가 있으면 삭제하고 Authorization 헤더로 교체
|
||||
if (newHeaders.has('apikey')) {
|
||||
const apiKeyValue = newHeaders.get('apikey');
|
||||
newHeaders.delete('apikey');
|
||||
newHeaders.set('Authorization', `Bearer ${apiKeyValue}`);
|
||||
} else if (newHeaders.has('Apikey')) {
|
||||
const apiKeyValue = newHeaders.get('Apikey');
|
||||
newHeaders.delete('Apikey');
|
||||
newHeaders.set('Authorization', `Bearer ${apiKeyValue}`);
|
||||
} else {
|
||||
// apikey 헤더가 없지만 Storage API를 호출하는 경우
|
||||
newHeaders.set('Authorization', `Bearer ${supabaseAnonKey}`);
|
||||
}
|
||||
|
||||
// 수정된 헤더로 새 옵션 객체 생성
|
||||
args[1].headers = newHeaders;
|
||||
console.log('Storage API 헤더 형식 수정 완료');
|
||||
}
|
||||
}
|
||||
|
||||
// URL 로깅 및 디버깅
|
||||
console.log('Supabase fetch 요청:', url);
|
||||
|
||||
// 기본 fetch 호출
|
||||
return fetch(requestToUse, args[1])
|
||||
.then(response => {
|
||||
console.log('Supabase 응답 상태:', response.status);
|
||||
return response;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Supabase fetch 오류:', err);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
fetch: customFetch
|
||||
}
|
||||
});
|
||||
|
||||
// CORS 문제 확인을 위한 기본 헤더 테스트
|
||||
(async () => {
|
||||
try {
|
||||
// 기본 서버 상태 확인 (CORS 테스트)
|
||||
console.log('Supabase 서버 상태 확인 중...');
|
||||
const response = await fetch(`${supabaseUrl}/auth/v1/`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': supabaseAnonKey,
|
||||
},
|
||||
});
|
||||
|
||||
if (response.ok || response.status === 401 || response.status === 404) {
|
||||
console.log('Supabase 서버 연결 성공:', response.status);
|
||||
} else {
|
||||
console.warn('Supabase 서버 연결 실패:', response.status, response.statusText);
|
||||
// 응답 세부 정보 로깅
|
||||
try {
|
||||
const errorText = await response.text();
|
||||
console.warn('Supabase 서버 응답 내용:', errorText);
|
||||
} catch (e) {
|
||||
console.error('응답 내용 읽기 실패:', e);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Supabase 서버 상태 확인 중 오류 (CORS 문제 가능성):', err);
|
||||
}
|
||||
})();
|
||||
|
||||
// Supabase 연결 테스트
|
||||
(async () => {
|
||||
try {
|
||||
console.log('Supabase 인증 테스트 시도 중...');
|
||||
const { data, error } = await supabaseClient.auth.getSession();
|
||||
if (error) {
|
||||
console.warn('Supabase 연결 테스트 실패:', error.message);
|
||||
} else {
|
||||
console.log('Supabase 연결 성공!', data);
|
||||
}
|
||||
|
||||
// 추가 테스트: 공개 데이터 조회 시도
|
||||
try {
|
||||
console.log('Supabase 데이터베이스 공개 테이블 조회 시도...');
|
||||
const { data: tableData, error: tableError } = await supabaseClient
|
||||
.from('transactions')
|
||||
.select('*')
|
||||
.limit(1);
|
||||
|
||||
if (tableError) {
|
||||
console.warn('Supabase 데이터베이스 테스트 실패:', tableError.message);
|
||||
} else {
|
||||
console.log('Supabase 데이터베이스 테스트 성공:', tableData);
|
||||
}
|
||||
} catch (dbErr) {
|
||||
console.error('Supabase 데이터베이스 테스트 중 예외 발생:', dbErr);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Supabase 연결 확인 중 오류:', err);
|
||||
}
|
||||
})();
|
||||
|
||||
// Supabase 연결 로그
|
||||
console.log('Supabase 클라이언트가 생성되었습니다.');
|
||||
|
||||
@@ -179,6 +37,14 @@ try {
|
||||
if (!isValidUrl) {
|
||||
console.warn('경고: 기본 Supabase URL 또는 Anon Key가 감지되었습니다. Supabase 설정 페이지에서 온프레미스 설정을 구성하세요.');
|
||||
}
|
||||
|
||||
// 연결 테스트 - 별도 파일로 이동됨
|
||||
import('./connectionTest').then(module => {
|
||||
module.testConnection(supabaseClient, supabaseUrl, supabaseAnonKey);
|
||||
}).catch(err => {
|
||||
console.error('연결 테스트 모듈 로딩 오류:', err);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Supabase 클라이언트 생성 오류:', error);
|
||||
|
||||
|
||||
69
src/lib/supabase/connectionTest.ts
Normal file
69
src/lib/supabase/connectionTest.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
import { SupabaseClient } from '@supabase/supabase-js';
|
||||
|
||||
/**
|
||||
* Supabase 연결 테스트
|
||||
*/
|
||||
export async function testConnection(
|
||||
supabaseClient: SupabaseClient,
|
||||
supabaseUrl: string,
|
||||
supabaseAnonKey: string
|
||||
): Promise<void> {
|
||||
// CORS 문제 확인을 위한 기본 헤더 테스트
|
||||
try {
|
||||
// 기본 서버 상태 확인 (CORS 테스트)
|
||||
console.log('Supabase 서버 상태 확인 중...');
|
||||
const response = await fetch(`${supabaseUrl}/auth/v1/`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': supabaseAnonKey,
|
||||
},
|
||||
});
|
||||
|
||||
if (response.ok || response.status === 401 || response.status === 404) {
|
||||
console.log('Supabase 서버 연결 성공:', response.status);
|
||||
} else {
|
||||
console.warn('Supabase 서버 연결 실패:', response.status, response.statusText);
|
||||
// 응답 세부 정보 로깅
|
||||
try {
|
||||
const errorText = await response.text();
|
||||
console.warn('Supabase 서버 응답 내용:', errorText);
|
||||
} catch (e) {
|
||||
console.error('응답 내용 읽기 실패:', e);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Supabase 서버 상태 확인 중 오류 (CORS 문제 가능성):', err);
|
||||
}
|
||||
|
||||
// Supabase 연결 테스트
|
||||
try {
|
||||
console.log('Supabase 인증 테스트 시도 중...');
|
||||
const { data, error } = await supabaseClient.auth.getSession();
|
||||
if (error) {
|
||||
console.warn('Supabase 연결 테스트 실패:', error.message);
|
||||
} else {
|
||||
console.log('Supabase 연결 성공!', data);
|
||||
}
|
||||
|
||||
// 추가 테스트: 공개 데이터 조회 시도
|
||||
try {
|
||||
console.log('Supabase 데이터베이스 공개 테이블 조회 시도...');
|
||||
const { data: tableData, error: tableError } = await supabaseClient
|
||||
.from('transactions')
|
||||
.select('*')
|
||||
.limit(1);
|
||||
|
||||
if (tableError) {
|
||||
console.warn('Supabase 데이터베이스 테스트 실패:', tableError.message);
|
||||
} else {
|
||||
console.log('Supabase 데이터베이스 테스트 성공:', tableData);
|
||||
}
|
||||
} catch (dbErr) {
|
||||
console.error('Supabase 데이터베이스 테스트 중 예외 발생:', dbErr);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Supabase 연결 확인 중 오류:', err);
|
||||
}
|
||||
}
|
||||
78
src/lib/supabase/customFetch.ts
Normal file
78
src/lib/supabase/customFetch.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
import { getSupabaseKey } from './config';
|
||||
import { modifyStorageApiRequest } from './storageUtils';
|
||||
|
||||
/**
|
||||
* Supabase 클라이언트에서 사용할 커스텀 fetch 구현
|
||||
*/
|
||||
export const customFetch = (...args: [RequestInfo | URL, RequestInit?]): Promise<Response> => {
|
||||
// 첫 번째 인자는 URL 또는 Request 객체
|
||||
let requestToUse = args[0];
|
||||
let url = '';
|
||||
|
||||
// URL 형식 변환
|
||||
if (typeof requestToUse === 'string') {
|
||||
url = requestToUse;
|
||||
} else if (requestToUse instanceof Request) {
|
||||
url = requestToUse.url;
|
||||
}
|
||||
|
||||
// Storage API 호출 감지 및 요청 수정
|
||||
if (url.includes('/storage/v1/')) {
|
||||
requestToUse = modifyStorageApiRequest(requestToUse, args[1], getSupabaseKey());
|
||||
|
||||
// args[1]이 존재하는 경우 modifyStorageApiHeaders 함수를 통해 헤더 수정
|
||||
if (args[1]) {
|
||||
args[1] = modifyStorageApiHeaders(args[1], getSupabaseKey());
|
||||
}
|
||||
}
|
||||
|
||||
// URL 로깅 및 디버깅
|
||||
console.log('Supabase fetch 요청:', url);
|
||||
|
||||
// 기본 fetch 호출
|
||||
return fetch(requestToUse, args[1])
|
||||
.then(response => {
|
||||
console.log('Supabase 응답 상태:', response.status);
|
||||
return response;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Supabase fetch 오류:', err);
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Storage API 요청에 대한 헤더 수정
|
||||
*/
|
||||
function modifyStorageApiHeaders(options: RequestInit, supabaseAnonKey: string): RequestInit {
|
||||
if (!options.headers) {
|
||||
return options;
|
||||
}
|
||||
|
||||
console.log('Storage API 호출 감지');
|
||||
|
||||
// 헤더 수정
|
||||
const originalHeaders = options.headers;
|
||||
const newHeaders = new Headers(originalHeaders);
|
||||
|
||||
// apikey 헤더가 있으면 삭제하고 Authorization 헤더로 교체
|
||||
if (newHeaders.has('apikey')) {
|
||||
const apiKeyValue = newHeaders.get('apikey');
|
||||
newHeaders.delete('apikey');
|
||||
newHeaders.set('Authorization', `Bearer ${apiKeyValue}`);
|
||||
} else if (newHeaders.has('Apikey')) {
|
||||
const apiKeyValue = newHeaders.get('Apikey');
|
||||
newHeaders.delete('Apikey');
|
||||
newHeaders.set('Authorization', `Bearer ${apiKeyValue}`);
|
||||
} else {
|
||||
// apikey 헤더가 없지만 Storage API를 호출하는 경우
|
||||
newHeaders.set('Authorization', `Bearer ${supabaseAnonKey}`);
|
||||
}
|
||||
|
||||
// 수정된 헤더로 새 옵션 객체 생성
|
||||
const newOptions = { ...options, headers: newHeaders };
|
||||
console.log('Storage API 헤더 형식 수정 완료');
|
||||
|
||||
return newOptions;
|
||||
}
|
||||
@@ -2,11 +2,18 @@
|
||||
import { supabase, isValidUrl } from './client';
|
||||
import { testSupabaseConnection } from './tests';
|
||||
import { createRequiredTables, checkTablesStatus } from './setup';
|
||||
import { customFetch } from './customFetch';
|
||||
import { modifyStorageApiRequest, getStorageApiHeaders } from './storageUtils';
|
||||
import { testConnection } from './connectionTest';
|
||||
|
||||
export {
|
||||
supabase,
|
||||
isValidUrl,
|
||||
testSupabaseConnection,
|
||||
createRequiredTables,
|
||||
checkTablesStatus
|
||||
checkTablesStatus,
|
||||
customFetch,
|
||||
modifyStorageApiRequest,
|
||||
getStorageApiHeaders,
|
||||
testConnection
|
||||
};
|
||||
|
||||
47
src/lib/supabase/storageUtils.ts
Normal file
47
src/lib/supabase/storageUtils.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
/**
|
||||
* Storage API 경로 수정 (buckets → bucket)
|
||||
*/
|
||||
export function modifyStorageApiRequest(
|
||||
request: RequestInfo | URL,
|
||||
options?: RequestInit,
|
||||
supabaseAnonKey?: string
|
||||
): RequestInfo | URL {
|
||||
let url = '';
|
||||
|
||||
// URL 추출
|
||||
if (typeof request === 'string') {
|
||||
url = request;
|
||||
|
||||
// Storage API 엔드포인트 경로 수정 (buckets → bucket)
|
||||
if (url.includes('/storage/v1/buckets')) {
|
||||
url = url.replace('/storage/v1/buckets', '/storage/v1/bucket');
|
||||
console.log('Storage API 경로 수정:', url);
|
||||
return url;
|
||||
}
|
||||
} else if (request instanceof Request) {
|
||||
url = request.url;
|
||||
|
||||
// Storage API 엔드포인트 경로 수정 (buckets → bucket)
|
||||
if (url.includes('/storage/v1/buckets')) {
|
||||
const newUrl = url.replace('/storage/v1/buckets', '/storage/v1/bucket');
|
||||
// Request 객체인 경우 새 Request 객체 생성
|
||||
const newRequest = new Request(newUrl, request);
|
||||
console.log('Storage API Request 객체 경로 수정:', newUrl);
|
||||
return newRequest;
|
||||
}
|
||||
}
|
||||
|
||||
// 수정이 필요 없으면 원래 요청 반환
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage API에 사용할 헤더 가져오기
|
||||
*/
|
||||
export function getStorageApiHeaders(supabaseAnonKey: string): Headers {
|
||||
const headers = new Headers();
|
||||
headers.set('Authorization', `Bearer ${supabaseAnonKey}`);
|
||||
headers.set('Content-Type', 'application/json');
|
||||
return headers;
|
||||
}
|
||||
Reference in New Issue
Block a user