@@ -41,9 +41,16 @@ async function getCanonicalHostnameForTenant(
4141}
4242
4343function normalizeRoutePath ( www_route_path ?: string | null ) : string {
44- const raw = ( www_route_path ?? "" ) . trim ( ) ;
44+ let raw = ( www_route_path ?? "" ) . trim ( ) ;
4545 if ( ! raw ) return "" ;
46- if ( raw === "/" ) return "" ;
46+
47+ // Remove any trailing slashes first ("/west/" -> "/west", "///" -> "").
48+ raw = raw . replace ( / \/ + $ / , "" ) ;
49+ if ( ! raw || raw === "/" ) return "" ;
50+
51+ // Ensure at most one leading slash ("//west" -> "/west").
52+ raw = raw . replace ( / ^ \/ + / , "/" ) ;
53+
4754 return raw . startsWith ( "/" ) ? raw : `/${ raw } ` ;
4855}
4956
@@ -52,8 +59,16 @@ function normalizeRoutePath(www_route_path?: string | null): string {
5259 *
5360 * Return shape:
5461 * - Always returns a string that **does not end with `/`**
55- * - Examples:\n+ * - `https://acme.example.com/west`\n+ * - `https://acme.grida.site/west`\n+ * - `http://acme.localhost:3000/west`\n+ * - `https://acme.grida.site` (when `www_route_path` is empty)\n+ *
56- * Intended usage:\n+ * - Build links by simple templating: `${base}/t/${code}`\n+ */
62+ *
63+ * Examples:
64+ * - `https://acme.example.com/west`
65+ * - `https://acme.grida.site/west`
66+ * - `http://acme.localhost:3000/west`
67+ * - `https://acme.grida.site` (when `www_route_path` is empty)
68+ *
69+ * Intended usage:
70+ * - Build links by simple templating: `${base}/t/${code}`
71+ */
5772export async function buildTenantSiteBaseUrl ( {
5873 www_name,
5974 www_route_path,
@@ -84,4 +99,3 @@ export async function buildTenantSiteBaseUrl({
8499
85100 return `https://${ canonicalHost ?? platformHost } ${ route } ` ;
86101}
87-
0 commit comments