Files
thePlug/frontend/src/composables/controlPlaneDiscovery.ts
T

81 lines
2.1 KiB
TypeScript

import { computed, type Ref } from "vue";
import { bindingsFor, folderBasename } from "./controlPlaneDraft";
import type { DockerService, ProxyDocument } from "../types";
export function useControlPlaneDiscovery(
services: Ref<DockerService[]>,
proxies: Ref<ProxyDocument[]>,
) {
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,
};
}