(spec: string)
| 118 | // "127.0.0.1:5432:5432", "8080:80/tcp") into the host interface + port. Returns |
| 119 | // undefined for specs with no fixed host port (container-only, ranges, ${VAR}). |
| 120 | function parseHostPortSpec(spec: string): PublishedPort | undefined { |
| 121 | let s = spec.trim(); |
| 122 | s = s.replace(/\s+#.*$/, '').trim(); // strip inline comment |
| 123 | s = s.replace(/^["']|["']$/g, '').trim(); // strip surrounding quotes |
| 124 | s = s.replace(/\/(tcp|udp|sctp)$/i, ''); // strip protocol suffix |
| 125 | const parts = s.split(':'); |
| 126 | let host = '0.0.0.0'; |
| 127 | let hostPort: string; |
| 128 | if (parts.length === 1) { |
| 129 | // Only a container port given — Docker picks a random host port, nothing to check. |
| 130 | return undefined; |
| 131 | } else if (parts.length === 2) { |
| 132 | hostPort = parts[0]; |
| 133 | } else { |
| 134 | // IP:HOST:CONTAINER |
| 135 | host = parts[parts.length - 3]; |
| 136 | hostPort = parts[parts.length - 2]; |
| 137 | } |
| 138 | // Skip port ranges (e.g. "8000-8010") and env-interpolated values (e.g. "${PORT}"). |
| 139 | if (!/^\d+$/.test(hostPort)) { |
| 140 | return undefined; |
| 141 | } |
| 142 | return { host, port: Number(hostPort) }; |
| 143 | } |
| 144 | |
| 145 | // Parses every `ports:` block in a docker-compose.yml and returns the unique set |
| 146 | // of host ports it would publish. Sufficient for our generated compose file; not a |
no outgoing calls
no test coverage detected