Skip to content

Changelog

All notable changes to the Timekeeper Countdown packages are documented here.

The format is based on Keep a Changelog, and these packages adhere to Semantic Versioning. Both packages are versioned in lockstep and always share one version.

@timekeeper-countdown/core

[Unreleased]

[0.3.2] - 2026-07-11

Changed

  • Internal refactor only — no public API or behavior change. The CountdownSnapshot type moved to its own leaf module (still exported from the package root with an identical shape); the three repeated time-validation guards in the safe time provider were consolidated into one helper (restoring a MAX_SAFE_INTEGER upper bound the fallback path had dropped — internal and unreachable in practice); and the published buildSnapshot testing helper now delegates to the engine's canonical implementation, so the test double can no longer drift from production.

[0.3.1] - 2026-06-27

Fixed

  • Lowered the published engines.node floor from >=22 to >=18. The shipped dist targets es2022 and uses no Node-22-only API, so the previous floor needlessly warned (or, under engine-strict, blocked) installs on Node 18/20. Building and testing the library still require Node 22 (declared only at the private workspace root).

[0.3.0] - 2026-06-27

Changed

  • Single-emit per transition (behavior change): each state transition (start/pause/resume/stop and natural completion) now emits exactly one snapshot; redundant emissions were removed. Consumers relying on the previous (larger) number of onSnapshot/onStateChange callbacks per transition must update.
  • The unit breakdown (years/weeks/days/…, the standalone formatDays/formatWeeks/formatYears, and getDays/getWeeks/getYears) is now computed by a single lossless successive-subtraction ladder (year = 365 days, week = 7 days), so the parts always reconstruct the total. Behavior change: values around the 52-week / 365-day boundaries are now corrected — e.g. 364 days no longer renders as all-zero.
  • CountdownEngine.setSeconds(n) now validates its argument like the constructor and reset(n): it throws on a negative / non-finite / non-integer / out-of-range value instead of silently coercing it. Valid values behave as before.
  • buildSnapshot now sanitizes both initialSeconds and totalSeconds (non-finite/negative → 0, floored, capped at MAX_SAFE_INTEGER) and derives isCompleted from the clamped total, so every snapshot is self-consistent. Behavior change: callers that previously read back a raw/oversized/non-integer initialSeconds now receive the clamped value.
  • A single canonical decompose() is now shared by the engine, the formatters, and the published testing utilities (removing three divergent copies).
  • Raised the minimum supported Node to >=22 (was >=18), declared via the engines field, so installing on older Node emits a warning or fails under engine-strict.

Fixed

  • A hostile timeProvider can no longer corrupt the countdown. Every provider (default or caller-supplied) is wrapped in a monotonic, finite-enforcing guard, so a NaN/Infinity/backward clock reading (NTP/DST/sleep-wake, or a buggy custom provider) is repaired to the last good value instead of producing a NaN snapshot, a runaway timer that never completes, a countdown that counts up, or a spurious instant completion. The interval also clamps remaining time to [0, initialValue].
  • A non-finite or non-positive tickIntervalMs now falls back to the 100 ms default instead of reaching setInterval as NaN/Infinity (which degenerated into a ~0 ms CPU tight-loop).

[0.2.0] - 2026-03-03

Changed

  • Renamed onUpdate to onSnapshot, added an onError callback, and exported the Countdown façade.
  • Added function overloads to all format helpers for better TypeScript DX.
  • Removed redundant try-catch in the safeFormat and safeExecute wrappers.

[0.1.4] - 2026-02-17

Added

  • Dual CJS+ESM build output for Jest and CJS-consumer compatibility.

[0.1.3] - 2026-02-17

Changed

  • Synced core and react package versions.

[0.1.2] - 2026-02-17

Fixed

  • formatMinutes now returns the decomposed value (0–59) instead of total minutes.

[0.1.1] - 2025-10-07

Added

  • Comprehensive README documentation for the core and react packages.

[0.1.0] - 2025-10-07

Added

  • Initial core package for the 0.1.0 React-first release.

@timekeeper-countdown/react

[Unreleased]

[0.3.2] - 2026-07-11

Changed

  • Lockstep release with @timekeeper-countdown/core 0.3.2 (internal refactor only — no changes to the useCountdown hook). Bumps the @timekeeper-countdown/core dependency to ^0.3.2.

[0.3.1] - 2026-06-27

Fixed

  • Lowered the published engines.node floor from >=22 to >=18 (the hook adds no Node-22 requirement of its own). Building and testing the library still require Node 22 (declared only at the private workspace root).

[0.3.0] - 2026-06-27

Changed

  • The useCountdown hook inherits the engine hardening (see @timekeeper-countdown/core 0.3.0): a hostile timeProvider (NaN/Infinity/backward clock) can no longer corrupt the countdown, tickIntervalMs is sanitized, and the time decomposition is lossless. Behavior change: the hook's setSeconds(value) now throws on an invalid argument (negative / non-finite / non-integer / out-of-range) instead of silently coercing it; reset(value) and construction already threw in 0.2.0 (unchanged).
  • Single-emit per transition (behavior change): useCountdown now receives exactly one snapshot per engine state transition (redundant emissions removed), which can break consumers that relied on the previous number of update callbacks per transition.
  • Now declares engines.node >=22 (the package previously declared no engines field); installing on older Node emits a warning or fails under engine-strict.
  • Bumped @timekeeper-countdown/core to ^0.3.0.

[0.2.0] - 2026-03-03

Changed

  • Bumped @timekeeper-countdown/core to ^0.2.0.

[0.1.4] - 2026-02-17

Changed

  • Bumped @timekeeper-countdown/core to ^0.1.4.

[0.1.3] - 2026-02-17

Changed

  • Bumped @timekeeper-countdown/core to ^0.1.3.

[0.1.2] - 2026-02-17

Changed

  • Updated the @timekeeper-countdown/core dependency to 0.1.2.

[0.1.1] - 2025-10-07

Added

  • Comprehensive README documentation.

Changed

  • Bumped @timekeeper-countdown/core to ^0.1.1.

[0.1.0] - 2025-10-07

Added

  • Initial React adapter (useCountdown) for the 0.1.0 React-first release.