67 lines
2.3 KiB
TypeScript
67 lines
2.3 KiB
TypeScript
/**
|
|
* 전략 DTO 정규화 — API·DB에서 문자열 JSON·flowLayout 보정
|
|
*/
|
|
import type { LogicNode } from './strategyTypes';
|
|
import type { StrategyDto } from './backendApi';
|
|
import { extractVirtualConditions } from './virtualStrategyConditions';
|
|
import { decodeConditionForEditor, encodeConditionForSave } from './strategyConditionSerde';
|
|
import { normalizeLogicRootForPersistence } from './strategyConditionNormalize';
|
|
import type { StrategyFlowLayoutStore } from './strategyEditorLayoutStorage';
|
|
|
|
export function asLogicNode(raw: unknown): LogicNode | null {
|
|
if (!raw) return null;
|
|
if (typeof raw === 'string') {
|
|
const t = raw.trim();
|
|
if (!t) return null;
|
|
try {
|
|
return JSON.parse(t) as LogicNode;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
if (typeof raw === 'object') return raw as LogicNode;
|
|
return null;
|
|
}
|
|
|
|
export function normalizeMarketCode(market: string): string {
|
|
const s = market.trim().toUpperCase();
|
|
if (!s) return 'KRW-BTC';
|
|
return s.startsWith('KRW-') ? s : `KRW-${s}`;
|
|
}
|
|
|
|
/** buy/sell DSL 파싱·flowLayout 재인코딩으로 조건 추출 가능 상태로 보정 */
|
|
export function hydrateStrategyDto(strategy: StrategyDto): StrategyDto {
|
|
const buy = asLogicNode(strategy.buyCondition);
|
|
const sell = asLogicNode(strategy.sellCondition);
|
|
let next: StrategyDto = {
|
|
...strategy,
|
|
buyCondition: normalizeLogicRootForPersistence(buy) ?? buy ?? undefined,
|
|
sellCondition: normalizeLogicRootForPersistence(sell) ?? sell ?? undefined,
|
|
};
|
|
|
|
if (extractVirtualConditions(next).length > 0) return next;
|
|
|
|
const layout = strategy.flowLayout as StrategyFlowLayoutStore | null | undefined;
|
|
if (!layout) return next;
|
|
|
|
try {
|
|
const normalizedBuy = asLogicNode(next.buyCondition);
|
|
const normalizedSell = asLogicNode(next.sellCondition);
|
|
const buyState = decodeConditionForEditor(normalizedBuy);
|
|
const sellState = decodeConditionForEditor(normalizedSell);
|
|
const encodedBuy = encodeConditionForSave(buyState);
|
|
const encodedSell = encodeConditionForSave(sellState);
|
|
if (encodedBuy || encodedSell) {
|
|
next = {
|
|
...next,
|
|
buyCondition: encodedBuy ?? normalizedBuy ?? undefined,
|
|
sellCondition: encodedSell ?? normalizedSell ?? undefined,
|
|
};
|
|
}
|
|
} catch {
|
|
/* flowLayout 보정 실패 — 원본 유지 */
|
|
}
|
|
|
|
return next;
|
|
}
|