pc 프로그램 다운로드 기능 적용
This commit is contained in:
@@ -14,8 +14,8 @@ export type StrategyFlowLayoutStore = Record<string, unknown>;
|
||||
/** 배포 APK·exdev (모바일 APK — http) */
|
||||
export const PRODUCTION_API_BASE = 'http://exdev.co.kr/api';
|
||||
|
||||
/** Tauri desktop — macOS ATS 호환 (https 필수) */
|
||||
export const DESKTOP_API_BASE = 'https://exdev.co.kr/api';
|
||||
/** Tauri desktop — exdev HTTP (HTTPS /api는 Caddy에서 빈 응답) */
|
||||
export const DESKTOP_API_BASE = 'http://exdev.co.kr/api';
|
||||
|
||||
function viteEnv(): Record<string, string> | undefined {
|
||||
return typeof import.meta !== 'undefined'
|
||||
@@ -43,7 +43,6 @@ function isDesktopClient(): boolean {
|
||||
}
|
||||
|
||||
function resolveApiBase(): string {
|
||||
// Desktop(Tauri): https exdev (macOS ATS — http 차단)
|
||||
if (isDesktopClient()) {
|
||||
return DESKTOP_API_BASE;
|
||||
}
|
||||
@@ -128,6 +127,18 @@ const DEFAULT_FETCH_TIMEOUT_MS = 45_000;
|
||||
/** exdev 첫 로그인 응답이 60초 이상 걸리는 경우 있음 */
|
||||
const LOGIN_FETCH_TIMEOUT_MS = 180_000;
|
||||
|
||||
type HttpFetchFn = typeof fetch;
|
||||
let httpFetchImpl: HttpFetchFn | null = null;
|
||||
|
||||
/** Tauri 등 WebView fetch 대신 네이티브 HTTP 사용 (desktop bootstrap에서 호출) */
|
||||
export function setHttpFetch(fn: HttpFetchFn): void {
|
||||
httpFetchImpl = fn;
|
||||
}
|
||||
|
||||
function httpFetch(): HttpFetchFn {
|
||||
return httpFetchImpl ?? fetch;
|
||||
}
|
||||
|
||||
function wrapNetworkError(e: unknown): Error {
|
||||
if (e instanceof TypeError || (e instanceof Error && /failed to fetch|load failed/i.test(e.message))) {
|
||||
return new Error(
|
||||
@@ -145,7 +156,7 @@ async function fetchWithTimeout(
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
||||
try {
|
||||
return await fetch(url, {
|
||||
return await httpFetch()(url, {
|
||||
...init,
|
||||
signal: controller.signal,
|
||||
headers: { ...authHeaders(), ...(init?.headers ?? {}) },
|
||||
@@ -978,7 +989,7 @@ export async function loadStrategy(id: number): Promise<StrategyDto | null> {
|
||||
|
||||
/** 전략 저장 (id 없으면 신규, 있으면 수정) — 실패 시 Error throw */
|
||||
export async function saveStrategy(dto: StrategyDto): Promise<StrategyDto> {
|
||||
const res = await fetch(`${API_BASE}/strategies`, {
|
||||
const res = await httpFetch()(`${API_BASE}/strategies`, {
|
||||
method: 'POST',
|
||||
headers: authHeaders(),
|
||||
body: JSON.stringify(dto),
|
||||
@@ -1337,7 +1348,7 @@ export async function repairStrategyTimeframes(strategyId: number): Promise<void
|
||||
/** 차트 실시간 파이프라인 pin (STOMP warm-up) */
|
||||
export async function pinCandleWatch(market: string, candleType: string): Promise<void> {
|
||||
try {
|
||||
await fetch(
|
||||
await httpFetch()(
|
||||
`${API_BASE}/candles/watch?market=${encodeURIComponent(market)}&type=${encodeURIComponent(candleType)}`,
|
||||
{ method: 'POST' },
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user