Refactor supabase client file

Refactor the supabase client file into smaller modules.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-15 15:44:11 +00:00
parent 1c3c4f37e0
commit f25d55690d
5 changed files with 212 additions and 145 deletions

View File

@@ -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);

View 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);
}
}

View 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;
}

View File

@@ -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
};

View 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;
}