2026-02-23 18:45:21 +09:00
|
|
|
/**
|
|
|
|
|
* useConnectionResolver - 런타임 컴포넌트 연결 해석기
|
|
|
|
|
*
|
|
|
|
|
* PopViewerWithModals에서 사용.
|
|
|
|
|
* layout.dataFlow.connections를 읽고, 소스 컴포넌트의 __comp_output__ 이벤트를
|
|
|
|
|
* 타겟 컴포넌트의 __comp_input__ 이벤트로 자동 변환/중계한다.
|
|
|
|
|
*
|
|
|
|
|
* 이벤트 규칙:
|
|
|
|
|
* 소스: __comp_output__${sourceComponentId}__${outputKey}
|
|
|
|
|
* 타겟: __comp_input__${targetComponentId}__${inputKey}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { useEffect, useRef } from "react";
|
|
|
|
|
import { usePopEvent } from "./usePopEvent";
|
|
|
|
|
import type { PopDataConnection } from "@/components/pop/designer/types/pop-layout";
|
|
|
|
|
|
|
|
|
|
interface UseConnectionResolverOptions {
|
|
|
|
|
screenId: string;
|
|
|
|
|
connections: PopDataConnection[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useConnectionResolver({
|
|
|
|
|
screenId,
|
|
|
|
|
connections,
|
|
|
|
|
}: UseConnectionResolverOptions): void {
|
|
|
|
|
const { publish, subscribe } = usePopEvent(screenId);
|
|
|
|
|
|
|
|
|
|
// 연결 목록을 ref로 저장하여 콜백 안정성 확보
|
|
|
|
|
const connectionsRef = useRef(connections);
|
|
|
|
|
connectionsRef.current = connections;
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!connections || connections.length === 0) return;
|
|
|
|
|
|
|
|
|
|
const unsubscribers: (() => void)[] = [];
|
|
|
|
|
|
|
|
|
|
// 소스별로 그룹핑하여 구독 생성
|
|
|
|
|
const sourceGroups = new Map<string, PopDataConnection[]>();
|
|
|
|
|
for (const conn of connections) {
|
|
|
|
|
const sourceEvent = `__comp_output__${conn.sourceComponent}__${conn.sourceOutput || conn.sourceField}`;
|
|
|
|
|
const existing = sourceGroups.get(sourceEvent) || [];
|
|
|
|
|
existing.push(conn);
|
|
|
|
|
sourceGroups.set(sourceEvent, existing);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const [sourceEvent, conns] of sourceGroups) {
|
|
|
|
|
const unsub = subscribe(sourceEvent, (payload: unknown) => {
|
|
|
|
|
for (const conn of conns) {
|
|
|
|
|
const targetEvent = `__comp_input__${conn.targetComponent}__${conn.targetInput || conn.targetField}`;
|
|
|
|
|
|
2026-02-24 12:52:29 +09:00
|
|
|
// 항상 통일된 구조로 감싸서 전달: { value, filterConfig?, _connectionId }
|
|
|
|
|
const enrichedPayload = {
|
|
|
|
|
value: payload,
|
|
|
|
|
filterConfig: conn.filterConfig,
|
|
|
|
|
_connectionId: conn.id,
|
|
|
|
|
};
|
2026-02-23 18:45:21 +09:00
|
|
|
|
|
|
|
|
publish(targetEvent, enrichedPayload);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
unsubscribers.push(unsub);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
for (const unsub of unsubscribers) {
|
|
|
|
|
unsub();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}, [screenId, connections, subscribe, publish]);
|
|
|
|
|
}
|