MCPcopy
hub / github.com/learnhouse/learnhouse / getUriWithOrg

Function getUriWithOrg

apps/web/services/config/config.ts:272–335  ·  view source on GitHub ↗
(orgslug: string, path: string)

Source from the content-addressed store, hash-verified

270 * the menu to forge a non-existent subdomain like `default.localhost:3000`.
271 */
272export const getUriWithOrg = (orgslug: string, path: string) => {
273 const tenancy = getTenancy()
274
275 // Client-side
276 if (typeof window !== 'undefined') {
277 // Single tenancy → always relative. The browser keeps us on the same host.
278 // Custom domain → relative (we're already on the org's host).
279 // Missing slug → relative (caller wants a generic intra-app URL).
280 if (tenancy === 'single' || getCustomDomainFromContext() || !orgslug) {
281 return path
282 }
283
284 // Multi tenancy: relative if we're already on the correct subdomain.
285 const baseDomain = stripPort(getLEARNHOUSE_DOMAIN())
286 const currentHostname = window.location.hostname
287 const expectedHostname = `${orgslug}.${baseDomain}`
288 if (currentHostname === expectedHostname) {
289 return path
290 }
291
292 // Safety net: only synthesize an absolute subdomain URL when the user is
293 // on the apex base domain itself (e.g. the org-selection screen) or on
294 // some subdomain of it. On any other host — localhost, a host that
295 // doesn't end in `.{baseDomain}` — building `${slug}.${baseDomain}` would
296 // land them on a hostname that may not resolve (e.g. `default.localhost`),
297 // so we return a relative path and keep navigation on the current origin.
298 //
299 // The apex case is essential: the org-selection screen lives on the apex
300 // (`{baseDomain}`), and from there every org link must cross to its
301 // `${slug}.${baseDomain}` subdomain. `isSubdomainOf` is false for the apex
302 // (a host is not a subdomain of itself), so without the `isSameHost` check
303 // org links would collapse to the apex path and loop back to the selector.
304 if (!isSubdomainOf(currentHostname, baseDomain) && !isSameHost(currentHostname, baseDomain)) {
305 return path
306 }
307
308 // Crossing subdomains — build an absolute URL with current scheme/port.
309 const protocol = window.location.protocol + '//'
310 const port = window.location.port
311 const portSuffix = port && port !== '80' && port !== '443' ? `:${port}` : ''
312 return `${protocol}${orgslug}.${baseDomain}${portSuffix}${path}`
313 }
314
315 // Server-side
316 // Single tenancy → relative. The page will render on whatever host the
317 // request came in on; relative URLs resolve correctly at the client.
318 if (tenancy === 'single') {
319 return path
320 }
321
322 // Multi tenancy server-side: build the subdomain URL because we can't
323 // assume server components know the user's current host.
324 if (orgslug) {
325 const protocol = getLEARNHOUSE_HTTP_PROTOCOL()
326 const domain = getLEARNHOUSE_DOMAIN()
327 return `${protocol}${orgslug}.${domain}${path}`
328 }
329 const explicitDomain = getConfig('NEXT_PUBLIC_LEARNHOUSE_DOMAIN')

Callers 15

HeaderProfileBoxFunction · 0.90
AdminAuthorizationFunction · 0.90
AuthMobileHeaderFunction · 0.90
AuthBrandingPanelFunction · 0.90
LandingClassicFunction · 0.90
TrailCourseElementFunction · 0.90
UserCertificatesFunction · 0.90
TrailCourseCardFunction · 0.90
ActivityFunction · 0.90
CertificatePageFunction · 0.90
navigateToActivityFunction · 0.90

Calls 8

stripPortFunction · 0.90
isSubdomainOfFunction · 0.90
isSameHostFunction · 0.90
getTenancyFunction · 0.85
getLEARNHOUSE_DOMAINFunction · 0.85
getConfigFunction · 0.85

Tested by

no test coverage detected