# retoor <retoor@molodetz.nl>
from __future__ import annotations
import re
from faker import Faker
from devplacepy.config import WORKSPACE_TUNNEL_DOMAIN
from devplacepy.database import get_setting, get_table
LABEL = re.compile(r"^[a-z0-9]([a-z0-9-]{0,48}[a-z0-9])?$")
MAX_ATTEMPTS = 12
_faker = Faker()
def domain() -> str:
return get_setting("workspace_tunnel_domain", WORKSPACE_TUNNEL_DOMAIN).strip(".")
def host_pattern() -> str:
return get_setting("workspace_hostname_pattern", "{name}.{domain}")
def port_pattern() -> str:
return get_setting("workspace_port_hostname_pattern", "{port}-{name}.{domain}")
def is_valid_label(value: str) -> bool:
return bool(value) and bool(LABEL.match(value))
def _slugify(value: str) -> str:
cleaned = re.sub(r"[^a-z0-9]+", "-", value.lower()).strip("-")
return cleaned[:49].strip("-")
def candidate(index: int) -> str:
words = [_slugify(_faker.word()) for _ in range(2)]
words = [word for word in words if word]
if not words:
words = ["workspace"]
name = "-".join(words)
if index:
name = f"{name}-{index}"
return name if is_valid_label(name) else "workspace"
def taken(name: str) -> bool:
return bool(get_table("instances").find_one(tunnel_name=name, deleted_at=None))
def generate(fallback_uid: str = "") -> str:
for attempt in range(MAX_ATTEMPTS):
name = candidate(attempt)
if not taken(name):
return name
tail = (fallback_uid or "").replace("-", "")[-8:]
return f"workspace-{tail}" if tail else "workspace"
def hostname_for(name: str, port: int = 0) -> str:
if not name:
return ""
pattern = port_pattern() if port else host_pattern()
return pattern.format(name=name, domain=domain(), port=port)
def proxy_uri_template(name: str) -> str:
if not name:
return ""
return "https://" + port_pattern().format(
name=name, domain=domain(), port="{{port}}"
)
def is_tunnel_host(host: str) -> bool:
if not host:
return False
bare = host.split(":", 1)[0].lower().rstrip(".")
suffix = "." + domain().lower()
return bare.endswith(suffix)