npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@molecule/app-version

v1.1.1

Published

Version and update management interface for molecule.dev

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.ts JSDoc, 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-logger

API

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) => void
  • data — 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(): VersionProvider

Returns: A fully configured VersionProvider for browser environments.

setProvider(provider)

Registers a version provider as the active singleton.

function setProvider(provider: VersionProvider): void
  • provider — 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(): VersionProvider

Returns: The active version provider instance.

getState()

Returns the current version state snapshot (build ID, version string, update availability, service worker status).

function getState(): VersionState

Returns: 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): void
  • info — 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): void
  • options — Check interval and whether to run an immediate check on start.

Returns: Nothing.

stopPeriodicChecks()

Stops periodic update checks started by startPeriodicChecks().

function stopPeriodicChecks(): void

Returns: Nothing.

getServiceWorker()

Returns the service worker controller for managing cache invalidation and skip-waiting lifecycle events.

function getServiceWorker(): ServiceWorkerController

Returns: 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 }): void
  • options — 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(): void

Returns: Nothing.

getRunningBuildTime()

Reads the running build's commit time from its <meta> stamp.

function getRunningBuildTime(): string | undefined

Returns: 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 | null
  • notes — 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 — Where release-notes.json is 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): string
  • options — 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: number

DEFAULT_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-logger

  • No bond wiring needed on the web. getProvider() auto-creates a browser-based provider on first access; call setProvider() 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 CURRENT buildId/version is non-empty and differs from the remote; (2) the app must serve /version.json (same-origin, VersionInfo shape: { 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 the update-available event 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 when text does not fit), or null. It needs the build plugin: import { releaseNotesPlugin } from '@molecule/app-version/build' in vite.config.ts (@molecule/app-vite-config-default already includes it). The plugin reads the app directory's conventional commits (feat:, fix:, perf:; test/ci/docs/style/build are skipped) into release-notes.json and stamps the build's commit time into index.html. A Release-Note: <text> commit trailer replaces the description shown; Release-Note: none leaves the commit out. Labels use the version.summary.* keys from @molecule/app-locales-version.

  • service-worker-template.ts generates 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.