Skip to content
← Public packages

@kody/mailroom

Offline-first PWA for your Kody mailbox: sent and received threads, copy-prompt for agents, no send.

src/ui/app-url.ts

39 lines · 1.4 KB · TypeScript
export function resolveAppUrl(base: string, path: string, origin: string): string {
	const root = new URL(base || '/', origin)
	if (!root.pathname.endsWith('/')) root.pathname += '/'
	return new URL(String(path).replace(/^\//, ''), root).toString()
}

export function scopedAssetPath(scope: string, path: string): string {
	const root = scope.endsWith('/') ? scope : `${scope}/`
	return `${root}${String(path).replace(/^\//, '')}`
}

export function serviceWorkerScope(base: string, origin: string): string {
	const root = new URL(base || '/', origin)
	if (!root.pathname.endsWith('/')) root.pathname += '/'
	return root.href
}

export function shouldCanonicalizeClientPath(pathname: string): boolean {
	return Boolean(pathname) && !pathname.endsWith('/')
}

export function serviceWorkerAllowedPath(base: string): string {
	const path = base.startsWith('/') ? base : `/${base}`
	return path.endsWith('/') && path !== '/' ? path.slice(0, -1) : path
}

export function needsCanonicalAppRedirect(
	pathname: string,
	appBasePath: string,
): boolean {
	return pathname === appBasePath
}

/** Parse a query int. Missing/blank must not become 0 — `Number(null)` is 0. */
export function numberParam(value: string | null, fallback: number): number {
	if (value == null || value.trim() === '') return fallback
	const parsed = Number(value)
	return Number.isFinite(parsed) ? parsed : fallback
}