37 lines
1.9 KiB
TypeScript
37 lines
1.9 KiB
TypeScript
import { defaultRuntimeTheme, type RuntimeTheme } from "./contract"
|
|
import { applyRuntimeTheme, isRuntimeTheme, resetRuntimeTheme } from "./runtime"
|
|
import { beginThemeRequest, isCurrentThemeRequest } from "./requests"
|
|
|
|
/** Fetch/validate only. No DOM access, fixed URL, storage or framework dependency. */
|
|
export async function fetchRuntimeTheme(url: string | URL, request?: RequestInit): Promise<RuntimeTheme> {
|
|
const response = await fetch(url, request)
|
|
if (!response.ok) throw new Error(`Theme request failed: HTTP ${response.status}`)
|
|
const theme: unknown = await response.json()
|
|
if (!isRuntimeTheme(theme)) throw new Error("Invalid Runtime Theme v1 document")
|
|
return { schemaVersion: 1, tokens: { ...theme.tokens } }
|
|
}
|
|
|
|
/** Resolve a supplied default + partial override using the existing v1 contract. */
|
|
export function resolveRuntimeTheme(theme: unknown, defaults: unknown = defaultRuntimeTheme): RuntimeTheme {
|
|
if (!isRuntimeTheme(defaults) || !isRuntimeTheme(theme)) throw new Error("Invalid Runtime Theme v1 document")
|
|
return { schemaVersion: 1, tokens: { ...defaultRuntimeTheme.tokens, ...defaults.tokens, ...theme.tokens } }
|
|
}
|
|
|
|
export type RuntimeThemeLoadOptions = { request?: RequestInit; defaults?: RuntimeTheme }
|
|
|
|
/** Convenience path: CDN/settings URL -> validate -> optional merge -> apply.
|
|
* Failure releases this API's override to the host/HM CSS fallback.
|
|
* Superseded requests never apply or reset the newer owner's theme.
|
|
*/
|
|
export async function loadRuntimeTheme(root: HTMLElement, url: string | URL, options: RuntimeThemeLoadOptions = {}): Promise<boolean> {
|
|
const request = beginThemeRequest(root)
|
|
try {
|
|
const theme = await fetchRuntimeTheme(url, options.request)
|
|
if (!isCurrentThemeRequest(root, request)) return false
|
|
return applyRuntimeTheme(root, options.defaults ? resolveRuntimeTheme(theme, options.defaults) : theme)
|
|
} catch {
|
|
if (isCurrentThemeRequest(root, request)) resetRuntimeTheme(root)
|
|
return false
|
|
}
|
|
}
|