Refactor SupabaseSettingsForm component
The SupabaseSettingsForm component was refactored into smaller, more manageable components to improve readability and maintainability.
This commit is contained in:
@@ -19,11 +19,19 @@ interface SupabaseSettingsFormProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved }) => {
|
const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved }) => {
|
||||||
const [supabaseUrl, setSupabaseUrl] = useState('');
|
// 상태 관리
|
||||||
const [supabaseKey, setSupabaseKey] = useState('');
|
const [formState, setFormState] = useState({
|
||||||
const [useProxy, setUseProxy] = useState(false);
|
supabaseUrl: '',
|
||||||
const [proxyType, setProxyType] = useState('corsproxy.io');
|
supabaseKey: '',
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
useProxy: false,
|
||||||
|
proxyType: 'corsproxy.io',
|
||||||
|
isSaving: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// 상태 업데이트 핸들러
|
||||||
|
const updateState = (update: Partial<typeof formState>) => {
|
||||||
|
setFormState(prev => ({ ...prev, ...update }));
|
||||||
|
};
|
||||||
|
|
||||||
// 저장된 설정 불러오기
|
// 저장된 설정 불러오기
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -32,18 +40,25 @@ const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved })
|
|||||||
const proxyEnabled = isCorsProxyEnabled();
|
const proxyEnabled = isCorsProxyEnabled();
|
||||||
const savedProxyType = getProxyType();
|
const savedProxyType = getProxyType();
|
||||||
|
|
||||||
if (savedUrl) setSupabaseUrl(savedUrl);
|
setFormState(prev => ({
|
||||||
if (savedKey) setSupabaseKey(savedKey);
|
...prev,
|
||||||
setUseProxy(proxyEnabled);
|
supabaseUrl: savedUrl || '',
|
||||||
setProxyType(savedProxyType);
|
supabaseKey: savedKey || '',
|
||||||
|
useProxy: proxyEnabled,
|
||||||
|
proxyType: savedProxyType
|
||||||
|
}));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// URL 유효성 검사
|
||||||
const validateUrl = (url: string): boolean => {
|
const validateUrl = (url: string): boolean => {
|
||||||
// URL 유효성 검사: http:// 또는 https://로 시작하는지 확인
|
|
||||||
return /^https?:\/\/.+/.test(url);
|
return /^https?:\/\/.+/.test(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 폼 제출 및 설정 저장
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
|
const { supabaseUrl, supabaseKey, useProxy, proxyType } = formState;
|
||||||
|
|
||||||
|
// 입력값 검증
|
||||||
if (!supabaseUrl || !supabaseKey) {
|
if (!supabaseUrl || !supabaseKey) {
|
||||||
toast({
|
toast({
|
||||||
title: "입력 오류",
|
title: "입력 오류",
|
||||||
@@ -62,7 +77,8 @@ const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved })
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsSaving(true);
|
// 저장 처리
|
||||||
|
updateState({ isSaving: true });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Supabase 설정 적용
|
// Supabase 설정 적용
|
||||||
@@ -81,38 +97,38 @@ const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved })
|
|||||||
description: "Supabase 설정을 저장하는 중 오류가 발생했습니다.",
|
description: "Supabase 설정을 저장하는 중 오류가 발생했습니다.",
|
||||||
variant: "destructive"
|
variant: "destructive"
|
||||||
});
|
});
|
||||||
setIsSaving(false);
|
updateState({ isSaving: false });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<SupabaseUrlInput
|
<SupabaseUrlInput
|
||||||
supabaseUrl={supabaseUrl}
|
supabaseUrl={formState.supabaseUrl}
|
||||||
setSupabaseUrl={setSupabaseUrl}
|
setSupabaseUrl={(url) => updateState({ supabaseUrl: url })}
|
||||||
useProxy={useProxy}
|
useProxy={formState.useProxy}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SupabaseKeyInput
|
<SupabaseKeyInput
|
||||||
supabaseKey={supabaseKey}
|
supabaseKey={formState.supabaseKey}
|
||||||
setSupabaseKey={setSupabaseKey}
|
setSupabaseKey={(key) => updateState({ supabaseKey: key })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CorsProxyToggle
|
<CorsProxyToggle
|
||||||
useProxy={useProxy}
|
useProxy={formState.useProxy}
|
||||||
setUseProxy={setUseProxy}
|
setUseProxy={(value) => updateState({ useProxy: value })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{useProxy && (
|
{formState.useProxy && (
|
||||||
<ProxyTypeSelector
|
<ProxyTypeSelector
|
||||||
proxyType={proxyType}
|
proxyType={formState.proxyType}
|
||||||
setProxyType={setProxyType}
|
setProxyType={(type) => updateState({ proxyType: type })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<SaveSettingsButton
|
<SaveSettingsButton
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
isSaving={isSaving}
|
isSaving={formState.isSaving}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,31 +1,35 @@
|
|||||||
|
|
||||||
import { supabase } from '../client';
|
import { SupabaseClient } from '@supabase/supabase-js';
|
||||||
|
import { TestResult } from './types';
|
||||||
|
|
||||||
// 데이터베이스 연결 테스트
|
export const testDatabaseConnection = async (
|
||||||
export const testDatabaseConnection = async (): Promise<{ success: boolean; error?: any }> => {
|
supabase: SupabaseClient
|
||||||
|
): Promise<TestResult> => {
|
||||||
try {
|
try {
|
||||||
console.log('데이터베이스 연결 테스트 시작...');
|
// 간단한 쿼리 실행으로 데이터베이스 연결 테스트
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from('transactions')
|
.from('_tests')
|
||||||
.select('*')
|
.select('*')
|
||||||
.limit(1);
|
.limit(1)
|
||||||
|
.maybeSingle();
|
||||||
|
|
||||||
if (error) {
|
// 오류가 있으면 실패로 처리 (404 제외 - 테이블이 없는 것은 정상)
|
||||||
let errorMsg = error.message;
|
if (error && error.code !== '42P01' && error.code !== 'PGRST116') {
|
||||||
|
return {
|
||||||
// 익명 인증 오류 처리
|
success: false,
|
||||||
if (errorMsg.includes('Auth session missing') || errorMsg.includes('JWT')) {
|
error: `데이터베이스 연결 오류: ${error.message}`
|
||||||
errorMsg += ' - 로그인이 필요하거나 권한 설정을 확인해주세요.';
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error('데이터베이스 테스트 실패:', error);
|
// 성공
|
||||||
return { success: false, error: { message: errorMsg } };
|
return {
|
||||||
} else {
|
success: true,
|
||||||
console.log('데이터베이스 테스트 성공', data);
|
error: null
|
||||||
return { success: true };
|
};
|
||||||
}
|
} catch (error: any) {
|
||||||
} catch (err) {
|
return {
|
||||||
console.error('데이터베이스 테스트 중 예외:', err);
|
success: false,
|
||||||
return { success: false, error: err };
|
error: `데이터베이스 테스트 중 예외 발생: ${error.message || '알 수 없는 오류'}`
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,88 +1,55 @@
|
|||||||
|
|
||||||
import { supabase } from '../client';
|
import { testAuth } from './authTests';
|
||||||
import { testAuthService } from './authTests';
|
|
||||||
import { testRestApi } from './apiTests';
|
import { testRestApi } from './apiTests';
|
||||||
import { testDatabase } from './databaseTests';
|
import { testDatabaseConnection } from './databaseTests';
|
||||||
|
import { TestResults } from './types';
|
||||||
|
import { supabase, isValidUrl } from '../client';
|
||||||
|
import { getSupabaseUrl, getSupabaseKey, isCorsProxyEnabled, getProxyType } from '../config';
|
||||||
|
|
||||||
export const testSupabaseConnection = async () => {
|
export const testSupabaseConnection = async (): Promise<TestResults> => {
|
||||||
console.log('Supabase 연결 테스트 시작...');
|
// 기본 결과 객체 초기화
|
||||||
|
const results: TestResults = {
|
||||||
// 결과값을 저장할 객체
|
url: getSupabaseUrl(),
|
||||||
const results = {
|
usingProxy: isCorsProxyEnabled(),
|
||||||
client: false,
|
proxyType: getProxyType(),
|
||||||
|
client: true,
|
||||||
restApi: false,
|
restApi: false,
|
||||||
auth: false,
|
auth: false,
|
||||||
database: false,
|
database: false,
|
||||||
url: '', // Supabase URL
|
errors: []
|
||||||
usingProxy: false, // CORS 프록시 사용 여부
|
|
||||||
proxyUrl: '', // 사용 중인 프록시 URL
|
|
||||||
errors: [] as string[], // 오류 메시지 배열
|
|
||||||
debugInfo: { // 디버깅 정보
|
|
||||||
proxyAttempts: [] as string[],
|
|
||||||
corsErrors: [] as string[],
|
|
||||||
timeouts: [] as string[],
|
|
||||||
backupProxySuccess: false
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 테스트 1: REST API 연결 테스트
|
// 클라이언트 유효성 체크
|
||||||
console.log('REST API 연결 테스트 중...');
|
if (!supabase) {
|
||||||
const apiTest = await testRestApi();
|
results.client = false;
|
||||||
results.restApi = apiTest.success;
|
results.errors.push('Supabase 클라이언트 초기화 실패');
|
||||||
|
|
||||||
if (!apiTest.success && apiTest.error) {
|
|
||||||
results.errors.push(`REST API 예외: ${apiTest.error.message || '알 수 없는 오류'}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 테스트 2: 인증 서비스 테스트
|
|
||||||
console.log('인증 서비스 테스트 중...');
|
|
||||||
const authTest = await testAuthService();
|
|
||||||
results.auth = authTest.success;
|
|
||||||
|
|
||||||
if (!authTest.success && authTest.error) {
|
|
||||||
results.errors.push(`인증 오류: ${authTest.error.message || '알 수 없는 오류'}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 테스트 3: 데이터베이스 테스트
|
|
||||||
console.log('데이터베이스 테스트 중...');
|
|
||||||
const dbTest = await testDatabase();
|
|
||||||
results.database = dbTest.success;
|
|
||||||
|
|
||||||
if (!dbTest.success && dbTest.error) {
|
|
||||||
results.errors.push(`데이터베이스 오류: ${dbTest.error.message || '알 수 없는 오류'}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 테스트 결과 요약
|
|
||||||
results.client = true; // 클라이언트가 초기화되었다면 여기까지 왔을 것임
|
|
||||||
|
|
||||||
// Supabase URL 및 프록시 정보 추가
|
|
||||||
const supabaseUrl = (supabase as any).supabaseUrl || '';
|
|
||||||
results.url = supabaseUrl;
|
|
||||||
|
|
||||||
// CORS 프록시 감지
|
|
||||||
const isProxied = supabaseUrl.includes('corsproxy.io') ||
|
|
||||||
supabaseUrl.includes('cors-anywhere') ||
|
|
||||||
supabaseUrl.includes('thingproxy.freeboard.io') ||
|
|
||||||
supabaseUrl.includes('allorigins.win');
|
|
||||||
|
|
||||||
results.usingProxy = isProxied;
|
|
||||||
|
|
||||||
if (isProxied) {
|
|
||||||
// 프록시 URL 추출
|
|
||||||
const proxyMatch = supabaseUrl.match(/(https?:\/\/[^\/]+\/)/);
|
|
||||||
if (proxyMatch) {
|
|
||||||
results.proxyUrl = proxyMatch[1];
|
|
||||||
} else {
|
|
||||||
results.proxyUrl = '알 수 없는 프록시';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Supabase 연결 테스트 완료:', results);
|
|
||||||
return results;
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 테스트 실행
|
||||||
|
const authResults = await testAuth(supabase, results.url);
|
||||||
|
const apiResults = await testRestApi(supabase);
|
||||||
|
const dbResults = await testDatabaseConnection(supabase);
|
||||||
|
|
||||||
|
// 결과 업데이트
|
||||||
|
results.auth = authResults.success;
|
||||||
|
results.restApi = apiResults.success;
|
||||||
|
results.database = dbResults.success;
|
||||||
|
|
||||||
|
// 오류 수집
|
||||||
|
if (!authResults.success) {
|
||||||
|
results.errors.push(`인증 테스트 실패: ${authResults.error}`);
|
||||||
|
}
|
||||||
|
if (!apiResults.success) {
|
||||||
|
results.errors.push(`REST API 테스트 실패: ${apiResults.error}`);
|
||||||
|
}
|
||||||
|
if (!dbResults.success) {
|
||||||
|
results.errors.push(`DB 테스트 실패: ${dbResults.error}`);
|
||||||
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Supabase 연결 테스트 중 예외 발생:', error);
|
results.errors.push(`테스트 실행 오류: ${error.message || '알 수 없는 오류'}`);
|
||||||
results.errors.push(`예상치 못한 오류: ${error.message || '알 수 없는 오류'}`);
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user