collapse consecutive port mappings into ranges in container list (#821)

This commit is contained in:
jarek committed 2026-04-19 09:30:42 +02:00
1 parent c44f244b1d
commit 84e0a0bf14
2 files changed
+64 -25

No files matched your search

+61
View File
@@ -0,0 +1,61 @@
export interface PortMapping {
publicPort: number;
privatePort: number;
display: string;
isRange?: boolean;
}
interface PortInfo {
PublicPort: number;
PrivatePort: number;
}
/**
* Format Docker port mappings, collapsing consecutive ranges.
* e.g. 8080:8080, 8081:8081, 8082:8082 → 8080-8082:8080-8082
*/
export function formatPorts(ports: PortInfo[] | undefined | null): PortMapping[] {
if (!ports || ports.length === 0) return [];
const seen = new Set<string>();
const individual = ports
.filter(p => p.PublicPort)
.map(p => ({
publicPort: p.PublicPort,
privatePort: p.PrivatePort,
display: `${p.PublicPort}:${p.PrivatePort}`
}))
.filter(p => {
const key = p.display;
if (seen.has(key)) return false;
seen.add(key);
return true;
})
.sort((a, b) => a.publicPort - b.publicPort);
// Collapse consecutive port ranges
if (individual.length <= 1) return individual;
const result: PortMapping[] = [];
let rangeStart = individual[0];
let rangeEnd = individual[0];
for (let i = 1; i < individual.length; i++) {
const curr = individual[i];
const offset = curr.publicPort - rangeStart.publicPort;
const expectedPrivate = rangeStart.privatePort + offset;
if (curr.publicPort === rangeEnd.publicPort + 1 && curr.privatePort === expectedPrivate) {
rangeEnd = curr;
} else {
result.push(rangeStart.publicPort === rangeEnd.publicPort
? rangeStart
: { publicPort: rangeStart.publicPort, privatePort: rangeStart.privatePort, display: `${rangeStart.publicPort}-${rangeEnd.publicPort}:${rangeStart.privatePort}-${rangeEnd.privatePort}`, isRange: true });
rangeStart = curr;
rangeEnd = curr;
}
}
result.push(rangeStart.publicPort === rangeEnd.publicPort
? rangeStart
: { publicPort: rangeStart.publicPort, privatePort: rangeStart.privatePort, display: `${rangeStart.publicPort}-${rangeEnd.publicPort}:${rangeStart.privatePort}-${rangeEnd.privatePort}`, isRange: true });
return result;
}