Skip to content

Kody is live

Watch the launch video — what Kody is, and why it exists.

← Public packages

@kentcdodds/package-app-kit

Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.

starter-fetch/src/version.ts

63 lines · 1.5 KB · TypeScript
import { packageStorage } from 'kody:runtime'

/** Published app version metadata stored in packageStorage for About + update checks. */
export type AppVersion = {
	sha: string
	shortSha: string
	message: string
	committedAt: string
	publishedAt: string
}

export const APP_VERSION_STORAGE_KEY = 'app_version'

export function emptyVersion(): AppVersion {
	return {
		sha: '',
		shortSha: '',
		message: '',
		committedAt: '',
		publishedAt: '',
	}
}

export function normalizeVersion(
	input: Partial<AppVersion> & { sha?: string },
): AppVersion {
	const sha = String(input.sha ?? '').trim()
	return {
		sha,
		shortSha: sha.slice(0, 7),
		message: String(input.message ?? '').split('\n')[0] ?? '',
		committedAt: String(input.committedAt ?? ''),
		publishedAt: String(input.publishedAt ?? ''),
	}
}

export async function getAppVersion(): Promise<AppVersion> {
	try {
		const raw = await packageStorage().get(APP_VERSION_STORAGE_KEY)
		if (raw == null) return emptyVersion()
		if (typeof raw === 'string') {
			return normalizeVersion(JSON.parse(raw) as Partial<AppVersion>)
		}
		if (typeof raw === 'object') {
			return normalizeVersion(raw as Partial<AppVersion>)
		}
		return emptyVersion()
	} catch {
		return emptyVersion()
	}
}

export async function setAppVersion(
	input: Partial<AppVersion> & { sha: string },
): Promise<AppVersion> {
	const next = normalizeVersion({
		...(await getAppVersion()),
		...input,
		publishedAt: input.publishedAt || new Date().toISOString(),
	})
	await packageStorage().set(APP_VERSION_STORAGE_KEY, next)
	return next
}