import {
buildQueryStringFromState,
useChartStore,
type FilterState,
} from "src/store";
import { type HoneypotEvent } from "src/types";
import {
filterEvents,
transformToChartPoint,
type ChartDataPoint,
} from "utils/filters";
import { URL } from "utils/utils";
import {
computed,
onBeforeUnmount,
onMounted,
ref,
toValue,
watch,
type MaybeRefOrGetter,
} from "vue";
import { useWebSocket } from "./useWebSocket";
export function useChartData(config: {
onLoaded?: () => void;
filters?: MaybeRefOrGetter<FilterState>;
enabled?: MaybeRefOrGetter<boolean>;
}) {
const chartStore = useChartStore();
const filters = computed(() => toValue(config.filters) || chartStore.state);
const enabled = computed(() => toValue(config.enabled) ?? true);
const queryString = computed(() => {
return buildQueryStringFromState(filters.value);
});
const loading = ref(true);
const chartData = ref<ChartDataPoint[]>([]);
const error = ref<Error | null>(null);
async function fetchData() {
if (!enabled.value) return;
loading.value = true;
error.value = null;
try {
const response = await fetch(`${URL()}/api/events?${queryString.value}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
const events: HoneypotEvent[] = data.events ?? [];
// Transform events to chart data points
chartData.value = events
.filter((evt) => evt.remote_addr)
.map(transformToChartPoint)
.sort((a, b) => a.time.getTime() - b.time.getTime());
config.onLoaded?.();
} catch (err) {
error.value = err instanceof Error ? err : new Error(String(err));
chartData.value = [];
} finally {
loading.value = false;
}
}
const { connect, disconnect, connectionStatus } = useWebSocket(
(batch: HoneypotEvent[]) => {
if (!enabled.value) return;
const filteredEvents = filterEvents(batch, filters.value);
if (filteredEvents.length === 0) {
return;
}
// Transform all events to chart data points
const newDataPoints: ChartDataPoint[] = filteredEvents
.filter((data) => data.remote_addr)
.map(transformToChartPoint)
.sort((a, b) => a.time.getTime() - b.time.getTime());
chartData.value.push(...newDataPoints);
config.onLoaded?.();
},
);
onMounted(() => {
if (enabled.value) {
fetchData();
}
});
onBeforeUnmount(() => {
chartData.value = [];
});
watch(
() => [queryString.value, enabled.value],
([newQs, newEnabled], [oldQs, oldEnabled]) => {
if (newEnabled && (newQs !== oldQs || !oldEnabled)) {
fetchData();
}
},
);
return {
loading,
chartData,
error,
fetchData,
queryString,
connectionStatus,
connect,
disconnect,
};
}