rspace-online/shared/url-helpers.ts

94 lines
3.0 KiB
TypeScript

/**
* Subdomain-aware URL helpers for rSpace navigation.
*
* Canonical URL pattern: {space}.rspace.online/{moduleId}
* Bare domain pattern: rspace.online/{moduleId} (implicitly demo space)
* Fallback (localhost): /{space}/{moduleId}
*/
const RESERVED_SUBDOMAINS = ["www", "rspace", "create", "new", "start", "auth"];
/** Detect if the current page is on a {space}.rspace.online subdomain */
export function isSubdomain(): boolean {
const parts = window.location.host.split(":")[0].split(".");
return (
parts.length >= 3 &&
parts.slice(-2).join(".") === "rspace.online" &&
!RESERVED_SUBDOMAINS.includes(parts[0])
);
}
/** Detect if the current page is on the bare rspace.online domain (no subdomain) */
export function isBareDomain(): boolean {
const host = window.location.host.split(":")[0];
return host === "rspace.online" || host === "www.rspace.online";
}
/** Get the current space from subdomain or path */
export function getCurrentSpace(): string {
if (isSubdomain()) {
return window.location.host.split(":")[0].split(".")[0];
}
// Bare domain: space is implicit (demo by default, until auto-provision)
if (isBareDomain()) {
return "demo";
}
// Path-based (localhost): /{space}/{moduleId}
const pathParts = window.location.pathname.split("/").filter(Boolean);
return pathParts[0] || "demo";
}
/** Get the current module from the path (works for subdomain, bare domain, and path routing) */
export function getCurrentModule(): string {
const parts = window.location.pathname.split("/").filter(Boolean);
if (isSubdomain()) {
return parts[0] || "rspace";
}
// Bare domain: path is /{moduleId}
if (isBareDomain()) {
return parts[0] || "rspace";
}
// Path-based (localhost): /{space}/{moduleId}
return parts[1] || "rspace";
}
/**
* Generate a navigation URL for a given space + module.
*
* On subdomains: same-space links use /{moduleId}, cross-space links
* switch the subdomain to {newSpace}.rspace.online/{moduleId}.
* On bare domain (rspace.online): stays on bare domain as /{moduleId}
* for default (demo) space, subdomain for explicit spaces.
* On localhost: uses /{space}/{moduleId}.
*/
export function rspaceNavUrl(space: string, moduleId: string): string {
const hostParts = window.location.host.split(":")[0].split(".");
const onSubdomain =
hostParts.length >= 3 &&
hostParts.slice(-2).join(".") === "rspace.online" &&
!RESERVED_SUBDOMAINS.includes(hostParts[0]);
if (onSubdomain) {
// Same space → just change the path
if (hostParts[0] === space) {
return `/${moduleId}`;
}
// Different space → switch subdomain
const baseDomain = hostParts.slice(-2).join(".");
return `${window.location.protocol}//${space}.${baseDomain}/${moduleId}`;
}
// Bare domain (rspace.online)
if (isBareDomain()) {
// Default space → stay on bare domain: /{moduleId}
if (space === "demo") {
return `/${moduleId}`;
}
// Explicit space → switch to subdomain
return `${window.location.protocol}//${space}.rspace.online/${moduleId}`;
}
// Localhost/dev
return `/${space}/${moduleId}`;
}