import { computed, type Ref } from "vue"; import { bindingsFor, folderBasename } from "./controlPlaneDraft"; import type { DockerService, ProxyDocument } from "../types"; export function useControlPlaneDiscovery( services: Ref, proxies: Ref, ) { const serviceEntries = computed(() => services.value.flatMap((service) => bindingsFor(service).map((binding) => { const proxy = proxies.value.find( (item) => item.service.name === service.name && item.service.folder === service.folder && item.service.port === binding.published, ) ?? null; return { id: `${service.folder}:${service.name}:${binding.host ?? "*"}:${binding.published}`, service, binding, proxy, listenHost: binding.host ?? "0.0.0.0", }; }), ), ); const missingServiceCount = computed( () => serviceEntries.value.filter((entry) => !entry.proxy).length, ); const serviceGroups = computed(() => { const groups = new Map< string, { id: string; title: string; folder: string; entries: (typeof serviceEntries.value)[number][]; } >(); for (const entry of serviceEntries.value) { const folder = entry.service.folder ?? ""; const existing = groups.get(folder); if (existing) { existing.entries.push(entry); continue; } groups.set(folder, { id: folder || entry.service.name, title: folderBasename(folder) || "Compose folder", folder, entries: [entry], }); } return [...groups.values()] .map((group) => ({ ...group, entries: [...group.entries].sort((left, right) => { const byName = left.service.name.localeCompare(right.service.name); if (byName !== 0) return byName; return left.binding.published - right.binding.published; }), })) .sort((left, right) => left.title.localeCompare(right.title)); }); return { missingServiceCount, serviceEntries, serviceGroups, }; }