82 lines
2.1 KiB
TypeScript
82 lines
2.1 KiB
TypeScript
function workspaceOrigins(): Record<string, string> {
|
|
const value = process.env.WRNEXUS_WORKSPACE_ORIGINS;
|
|
|
|
if (!value) {
|
|
return {};
|
|
}
|
|
|
|
try {
|
|
const parsed = JSON.parse(value);
|
|
|
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
return {};
|
|
}
|
|
|
|
return parsed as Record<string, string>;
|
|
} catch {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
function normalizePath(path: string): string {
|
|
if (!path) return "/";
|
|
|
|
return path.startsWith("/") ? path : `/${path}`;
|
|
}
|
|
|
|
export function appOrigin(appName: string): string {
|
|
const origins = workspaceOrigins();
|
|
const origin = origins[appName];
|
|
|
|
if (!origin) {
|
|
throw new Error(
|
|
`Unknown workspace app "${appName}". Available apps: ${
|
|
Object.keys(origins).join(", ") || "none"
|
|
}.`,
|
|
);
|
|
}
|
|
|
|
return new URL(origin).origin;
|
|
}
|
|
|
|
export function appUrl(appName: string, path = "/"): string {
|
|
return new URL(normalizePath(path), `${appOrigin(appName)}/`).href;
|
|
}
|
|
|
|
export function currentAppName(): string | undefined {
|
|
return process.env.WRNEXUS_APP_NAME;
|
|
}
|
|
|
|
export function currentAppOrigin(): string | undefined {
|
|
const value = process.env.WRNEXUS_APP_ORIGIN;
|
|
|
|
return value ? new URL(value).origin : undefined;
|
|
}
|
|
|
|
export function workspaceAppOrigins(): Readonly<Record<string, string>> {
|
|
return Object.freeze({ ...workspaceOrigins() });
|
|
}
|
|
|
|
/** Shared DNS suffix for configured workspace apps (for example `staging.example.com`). */
|
|
export function workspaceRootDomain(): string {
|
|
const hosts = Object.values(workspaceOrigins()).map((origin) =>
|
|
new URL(origin).hostname.toLowerCase(),
|
|
);
|
|
if (!hosts.length) {
|
|
throw new Error("Workspace origins are unavailable.");
|
|
}
|
|
|
|
const labels = hosts.map((host) => host.split(".").reverse());
|
|
const common: string[] = [];
|
|
for (let index = 0; index < labels[0]!.length; index++) {
|
|
const label = labels[0]![index];
|
|
if (!labels.every((parts) => parts[index] === label)) break;
|
|
common.push(label!);
|
|
}
|
|
|
|
if (!common.length) {
|
|
throw new Error(`Workspace apps do not share a root domain: ${hosts.join(", ")}.`);
|
|
}
|
|
return common.reverse().join(".");
|
|
}
|