@molecule/app-version
v1.1.1
Published
Version and update management interface for molecule.dev
Maintainers
Readme
@molecule/app-version
Version and update management interface for molecule.dev.
Tracks the running build, polls a same-origin /version.json for new deploys,
manages the service-worker update lifecycle (waiting worker, skip-waiting,
reload), and emits events. Headless: the app owns the "update available"
banner/toast — styled via getClassMap() and translated via t() — while this
package owns detection, apply, and dismiss.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import {
applyUpdate,
getProvider,
setCurrentVersion,
startPeriodicChecks,
} from '@molecule/app-version'
// At startup — build-time values injected by the bundler:
setCurrentVersion({ buildId: __BUILD_ID__, version: __APP_VERSION__ })
startPeriodicChecks({ immediate: true }) // polls /version.json (default: every 5 min)
// Render your own update UI from events:
getProvider().on('update-available', () => {
showUpdateBanner({ onReload: () => applyUpdate() })
})Type
core
Installation
npm install @molecule/app-version @molecule/app-bond @molecule/app-i18n @molecule/app-loggerAPI
Interfaces
ServiceWorkerTemplateOptions
Options for generating the service worker template.
interface ServiceWorkerTemplateOptions {
/**
* Whether to include push notification handlers.
* @default false
*/
pushNotifications?: boolean
/**
* Maximum number of cached images.
* @default 50
*/
maxImageCacheEntries?: number
/**
* Additional file extensions to cache (besides .png).
* @default []
*/
imageCacheExtensions?: string[]
}VersionInfo
Static build metadata (version string, build ID, commit hash, branch, timestamp).
interface VersionInfo {
/**
* Build ID (e.g., from CI/CD).
*/
buildId: string
/**
* Semantic version string.
*/
version: string
/**
* Build timestamp.
*/
buildTime?: string
/**
* Git commit hash.
*/
commitHash?: string
/**
* Git branch.
*/
branch?: string
}VersionState
Reactive version state including current build info, update availability, and checking status.
interface VersionState extends VersionInfo {
/**
* New build ID if update detected.
*/
newBuildId?: string
/**
* New version if update detected.
*/
newVersion?: string
/**
* Whether a new version is available.
*/
isUpdateAvailable: boolean
/**
* Whether a new service worker is waiting.
*/
isServiceWorkerWaiting: boolean
/**
* Last check timestamp.
*/
lastChecked?: Date
/**
* Whether currently checking for updates.
*/
isChecking: boolean
}ServiceWorkerController
Service worker registration with update capability.
interface ServiceWorkerController {
/**
* Registers the service worker.
*/
register(scriptUrl?: string): Promise<ServiceWorkerRegistration | null>
/**
* Unregisters the service worker.
*/
unregister(): Promise<boolean>
/**
* Checks for service worker updates.
*/
update(): Promise<void>
/**
* Skips waiting and activates new service worker.
*/
skipWaiting(): void
/**
* Gets the current registration.
*/
getRegistration(): ServiceWorkerRegistration | null
/**
* Gets the waiting service worker.
*/
getWaiting(): ServiceWorker | null
/**
* Checks if a service worker is waiting.
*/
isWaiting(): boolean
/**
* Posts a message to the service worker.
*/
postMessage(message: unknown): void
}UpdateCheckOptions
Update check options.
interface UpdateCheckOptions {
/**
* URL to check for version info.
*/
versionUrl?: string
/**
* Interval in milliseconds between checks.
*/
interval?: number
/**
* Whether to check immediately on start.
*/
immediate?: boolean
}VersionProvider
Version provider interface that all version bond packages must implement. Manages version tracking, update detection, and service worker lifecycle.
interface VersionProvider {
/**
* Gets the current version state.
*/
getState(): VersionState
/**
* Sets the current version info.
*/
setCurrentVersion(info: VersionInfo): void
/**
* Checks for updates.
*/
checkForUpdates(): Promise<boolean>
/**
* Starts periodic update checks.
*/
startPeriodicChecks(options?: UpdateCheckOptions): void
/**
* Stops periodic update checks.
*/
stopPeriodicChecks(): void
/**
* Gets the service worker controller.
*/
getServiceWorker(): ServiceWorkerController
/**
* Applies the update (reloads the page).
*/
applyUpdate(options?: { force?: boolean }): void
/**
* Dismisses the update notification.
*/
dismissUpdate(): void
/**
* Subscribes to version events.
*/
on<T>(event: VersionEvent, handler: VersionEventHandler<T>): () => void
/**
* Unsubscribes from events.
*/
off<T>(event: VersionEvent, handler: VersionEventHandler<T>): void
/**
* Destroys the provider.
*/
destroy(): void
}ReleaseNoteEntry
One change listed in release-notes.json.
interface ReleaseNoteEntry {
/** Kind of change. */
type: ReleaseNoteType
/** Commit time (ISO 8601). */
time: string
/** Short user-facing description, when the change has one. */
text?: string
}ReleaseNotes
Shape of release-notes.json.
interface ReleaseNotes {
/** Commit time of the build that wrote the file (ISO 8601). */
builtAt?: string
/** Recent changes, newest first. */
entries: ReleaseNoteEntry[]
}UpdateSummary
What a waiting update brings, as one line for the update banner.
interface UpdateSummary {
/** The full line — "3 new features, 2 bugs fixed, and performance improvements". */
text: string
/** The line for narrow screens — "3 features, 2 fixes, faster". */
compact: string
}Types
VersionEvent
Version lifecycle events emitted during update checks and service worker transitions.
type VersionEvent =
| 'update-available'
| 'service-worker-waiting'
| 'service-worker-activated'
| 'check-start'
| 'check-complete'
| 'check-error'VersionEventHandler
Callback for version events. Receives event-specific data.
type VersionEventHandler<T = unknown> = (data: T) => voiddata— Event payload (varies by event type).
ReleaseNoteType
Kind of a user-visible change: a new feature, a bug fix, a performance improvement, or anything else that ships to users (refactors, dependency updates).
type ReleaseNoteType = 'feat' | 'fix' | 'perf' | 'other'Functions
createVersionChecker(getState, updateState, emit)
Creates a version checker.
function createVersionChecker(
getState: () => VersionState,
updateState: (partial: Partial<VersionState>) => void,
emit: <T>(event: VersionEvent, data: T) => void,
): () => Promise<boolean>getState— Function to get the current version state.updateState— Function to update the version state.emit— Function to emit events.
Returns: The check for updates function.
createWebVersionProvider()
Creates a browser-based version provider that checks for updates
by polling a /version.json endpoint, manages a service worker
for cache invalidation, and emits events when updates are available.
function createWebVersionProvider(): VersionProviderReturns: A fully configured VersionProvider for browser environments.
setProvider(provider)
Registers a version provider as the active singleton.
function setProvider(provider: VersionProvider): voidprovider— The version provider implementation to bond.
getProvider()
Retrieves the bonded version provider. If none is bonded, automatically creates a browser-based version provider.
function getProvider(): VersionProviderReturns: The active version provider instance.
getState()
Returns the current version state snapshot (build ID, version string, update availability, service worker status).
function getState(): VersionStateReturns: A copy of the current VersionState.
setCurrentVersion(info)
Sets the current application version info. Typically called at startup with build-time values injected by the bundler.
function setCurrentVersion(info: VersionInfo): voidinfo— Build metadata including version, buildId, and optional commitHash.
Returns: Nothing.
checkForUpdates()
Checks for application updates by fetching /version.json and
comparing the remote build ID against the current one.
function checkForUpdates(): Promise<boolean>Returns: true if an update is available.
startPeriodicChecks(options)
Starts periodic update checks at the specified interval.
function startPeriodicChecks(options?: UpdateCheckOptions): voidoptions— Check interval and whether to run an immediate check on start.
Returns: Nothing.
stopPeriodicChecks()
Stops periodic update checks started by startPeriodicChecks().
function stopPeriodicChecks(): voidReturns: Nothing.
getServiceWorker()
Returns the service worker controller for managing cache invalidation and skip-waiting lifecycle events.
function getServiceWorker(): ServiceWorkerControllerReturns: The ServiceWorkerController instance.
applyUpdate(options)
Applies a pending update by activating a waiting service worker
(if present) and reloading the page. If no service worker is
waiting, reloads the page when an update is available or force is set.
function applyUpdate(options?: { force?: boolean }): voidoptions— Pass{ force: true }to reload even without a detected update.options.force— Whether to force a reload regardless of update status.
Returns: Nothing.
dismissUpdate()
Dismisses the current update notification by clearing the
isUpdateAvailable flag in state.
function dismissUpdate(): voidReturns: Nothing.
getRunningBuildTime()
Reads the running build's commit time from its <meta> stamp.
function getRunningBuildTime(): string | undefinedReturns: The ISO time, or undefined when the page carries no stamp.
summarizeReleaseNotes(notes, since, options)
Summarizes the changes newer than since in one short line: the change's own
description when there is exactly one (and it has one), otherwise counts —
"3 new features, 2 bugs fixed, and performance improvements", or with
compact "3 features, 2 fixes, faster" for narrow screens.
function summarizeReleaseNotes(
notes: ReleaseNotes,
since?: string,
options?: { compact?: boolean },
): string | nullnotes— The new build's release notes.since— Commit time of the running build (ISO 8601).options— Formatting options.options.compact— Use the short forms (and a shorter limit for a specific description).
Returns: The summary, or null when nothing user-visible changed or since is unknown.
fetchReleaseNotes(url)
Fetches the deployed release-notes.json. Bypasses every cache (including a
service worker's precache) so it reads the NEW build's file.
function fetchReleaseNotes(url?: string): Promise<ReleaseNotes | null>url— Where the file is served (default/release-notes.json).
Returns: The notes, or null when the file is missing or malformed.
getUpdateSummary(url)
What the waiting update brings, for the update banner: the full line, and a compact one to show when the full line does not fit.
function getUpdateSummary(url?: string): Promise<UpdateSummary | null>url— Whererelease-notes.jsonis served (default/release-notes.json).
Returns: Both lines, or null when there is nothing to say.
generateServiceWorkerTemplate(options)
Generates a service worker TypeScript source file.
function generateServiceWorkerTemplate(options?: ServiceWorkerTemplateOptions): stringoptions— Template configuration options.
Returns: The service worker source code as a string.
createServiceWorkerController(updateState, emit)
Creates a service worker controller.
function createServiceWorkerController(
updateState: (partial: Partial<VersionState>) => void,
emit: <T>(event: VersionEvent, data: T) => void,
): {
controller: ServiceWorkerController
getRegistration: () => ServiceWorkerRegistration | null
}updateState— Function to update the version state.emit— Function to emit events.
Returns: The service worker controller.
Constants
DEFAULT_CHECK_INTERVAL
Default version check interval (5 minutes).
const DEFAULT_CHECK_INTERVAL: numberDEFAULT_VERSION_URL
Default version URL.
const DEFAULT_VERSION_URL: '/version.json'RELEASE_NOTES_FILENAME
File every build writes next to index.html.
const RELEASE_NOTES_FILENAME: 'release-notes.json'BUILD_TIME_META_NAME
<meta name> carrying the build's commit time (ISO 8601).
const BUILD_TIME_META_NAME: 'molecule-build-time'Injection Notes
Requirements
Peer dependencies:
@molecule/app-bond^1.0.1@molecule/app-i18n^1.0.1@molecule/app-logger^1.0.1
Runtime Dependencies
@molecule/app-bond@molecule/app-i18n@molecule/app-loggerNo bond wiring needed on the web.
getProvider()auto-creates a browser-based provider on first access; callsetProvider()only to substitute a custom/native implementation.Update detection has TWO prerequisites this package does not create: (1)
setCurrentVersion()must run at startup with real build-time values — the checker only reports an update when the CURRENTbuildId/versionis non-empty and differs from the remote; (2) the app must serve/version.json(same-origin,VersionInfoshape:{ buildId, version, … }) and regenerate it on every deploy. Miss either and checks silently never find an update.applyUpdate()reloads the page (activating a waiting service worker first when present). Surface theupdate-availableevent in UI and let the user opt in — never call it unprompted; unsaved state is lost on reload."What's new" line for the banner.
getUpdateSummary()returns one short line for the waiting update — the change's own description when there is one change, else counts ("3 new features, 2 bugs fixed, and performance improvements") — as{ text, compact }(compact: "3 features, 2 fixes, faster", for whentextdoes not fit), ornull. It needs the build plugin:import { releaseNotesPlugin } from '@molecule/app-version/build'invite.config.ts(@molecule/app-vite-config-defaultalready includes it). The plugin reads the app directory's conventional commits (feat:,fix:,perf:;test/ci/docs/style/buildare skipped) intorelease-notes.jsonand stamps the build's commit time intoindex.html. ARelease-Note: <text>commit trailer replaces the description shown;Release-Note: noneleaves the commit out. Labels use theversion.summary.*keys from@molecule/app-locales-version.service-worker-template.tsgenerates service-worker SOURCE at scaffold time (precache + push handlers); it is not a runtime service worker itself.
Translations
Translation strings are provided by @molecule/app-locales-version.
