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 { createClient } from '@supabase/supabase-js';
|
||||||
import { getSupabaseUrl, getSupabaseKey } from './config';
|
import { getSupabaseUrl, getSupabaseKey } from './config';
|
||||||
|
import { customFetch } from './customFetch';
|
||||||
|
|
||||||
const supabaseUrl = getSupabaseUrl();
|
const supabaseUrl = getSupabaseUrl();
|
||||||
const supabaseAnonKey = getSupabaseKey();
|
const supabaseAnonKey = getSupabaseKey();
|
||||||
@@ -25,153 +26,10 @@ try {
|
|||||||
},
|
},
|
||||||
global: {
|
global: {
|
||||||
// 커스텀 fetch 구현
|
// 커스텀 fetch 구현
|
||||||
fetch: (...args) => {
|
fetch: customFetch
|
||||||
// 첫 번째 인자는 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;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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 연결 로그
|
// Supabase 연결 로그
|
||||||
console.log('Supabase 클라이언트가 생성되었습니다.');
|
console.log('Supabase 클라이언트가 생성되었습니다.');
|
||||||
|
|
||||||
@@ -179,6 +37,14 @@ try {
|
|||||||
if (!isValidUrl) {
|
if (!isValidUrl) {
|
||||||
console.warn('경고: 기본 Supabase URL 또는 Anon Key가 감지되었습니다. Supabase 설정 페이지에서 온프레미스 설정을 구성하세요.');
|
console.warn('경고: 기본 Supabase URL 또는 Anon Key가 감지되었습니다. Supabase 설정 페이지에서 온프레미스 설정을 구성하세요.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 연결 테스트 - 별도 파일로 이동됨
|
||||||
|
import('./connectionTest').then(module => {
|
||||||
|
module.testConnection(supabaseClient, supabaseUrl, supabaseAnonKey);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('연결 테스트 모듈 로딩 오류:', err);
|
||||||
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Supabase 클라이언트 생성 오류:', 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 { supabase, isValidUrl } from './client';
|
||||||
import { testSupabaseConnection } from './tests';
|
import { testSupabaseConnection } from './tests';
|
||||||
import { createRequiredTables, checkTablesStatus } from './setup';
|
import { createRequiredTables, checkTablesStatus } from './setup';
|
||||||
|
import { customFetch } from './customFetch';
|
||||||
|
import { modifyStorageApiRequest, getStorageApiHeaders } from './storageUtils';
|
||||||
|
import { testConnection } from './connectionTest';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
supabase,
|
supabase,
|
||||||
isValidUrl,
|
isValidUrl,
|
||||||
testSupabaseConnection,
|
testSupabaseConnection,
|
||||||
createRequiredTables,
|
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